「お前には n 日間でAWSを学んでもらう」 #2 です. IAMユーザーも作ったので色々遊んでみます.

この記事のスコープ

  • AWS CLI (Version 2) を PowerShellで使う
  • VPC, サブネット
  • セキュリティグループ
  • インスタンスの起動と終了

スコープ外

  • AWS CLI v2 のインストール
  • IAMユーザーの作成

AWS CLI v2のインストールについてはドキュメントを参考にして実施してください. また, IAMユーザーの作成については前記事を参考にしてください.

免責事項

思わぬ請求他, 生じた損害に対しては一切の責任を負いかねます.

AWS CLI (AWS Command Line Interface)

公式によりますとコマンドラインシェルでAWSサービスとやり取りするためのオープンソースツールだそうです.

AWSのマネジメントコンソールから出来ることというのは実際にはAWSのサービスが提供しているものの一部だそうで, 最大限活かすためには避けて通れないものになるそうです.

なお, シェルを使えるということはシェルスクリプトを用いた自動化なども効くということです.  (シェルスクリプト, 全く触ったことがないのでいつかやらなくちゃ...)

aws configure

まず設定情報を登録します. 事前に作成したIAMユーザーのアクセスID, シークレットキーを用意してください. csvファイルの中にかかれています.

$ aws configure
AWS Access Key ID [None]: Your Access Key ID
AWS Secret Access Key [None]: Your Secret Access Key
Default region name [None]: ap-northeast-1
Default output format [None]:

この情報は秘密にしておきましょう!

設定が完了していることを確認してみましょう.

$ ls ~/.aws

Mode                 LastWriteTime         Length Name                                                                  ----                 -------------         ------ ----                                                                  -a----        2020/06/28     20:45             36 config                                                                -a----        2020/06/28     20:45            119 credentials 

config と credentials とが出来ています. credentialsに機密性の高い認証情報 Access Key IDとSecret Accesss Keyが格納されています.

目標物

今回は次のような構成を作ってみようと思います. インスタンスをインターネットに繋げちゃうのですが, セキュリティグループにより自分のグローバルIPアドレスからのSSH接続以外を拒否しようと思います.

目標とする構成

VPCの作成

早速VPCを作成してみます.  AWS CLI Command Referenceを見てみると create-vpcはAWSのEC2のところにまとめられているようです.

このSynopsisに従って次のように叩いてみましょう.

$ aws ec2 create-vpc --cidr-block 10.0.0.0/16

次のようなレスポンスが返ってきます.

{
    "Vpc": {
        "CidrBlock": "10.0.0.0/16",
        "DhcpOptionsId": "dopt-xxxxxxxx",
        "State": "pending",
        "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
        "OwnerId": "xxxxxxxxxxxx",
        "InstanceTenancy": "default",
        "Ipv6CidrBlockAssociationSet": [],
        "CidrBlockAssociationSet": [
            {
                "AssociationId": "vpc-cidr-assoc-xxxxxxxxxxxxxxxxx",
                "CidrBlock": "10.0.0.0/16",
                "CidrBlockState": {
                    "State": "associated"
                }
            }
        ],
        "IsDefault": false
    }
}

これでvpcの作成が完了ですね!

サブネットの作成

次にサブネットを作成していきます. VPCのIdが必要です. create-vpc のレスポンスからも見られたのですが, describe-vpcs で調べることもできます.

$ aws ec2 create-subnet `
--availability-zone ap-northeast-1a `
--cidr-block 10.0.1.0/24 `
--vpc-id vpc-xxxxxxxxxxxxxxxxx

次のようなレスポンスが返ってきます

{
    "Subnet": {
        "AvailabilityZone": "ap-northeast-1a",
        "AvailabilityZoneId": "apne1-az4",
        "AvailableIpAddressCount": 251,
        "CidrBlock": "10.0.1.0/24",
        "DefaultForAz": false,
        "MapPublicIpOnLaunch": false,
        "State": "available",
        "SubnetId": "subnet-xxxxxxxxxxxxxxxxx",
        "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
        "OwnerId": "xxxxxxxxxxxx",
        "AssignIpv6AddressOnCreation": false,
        "Ipv6CidrBlockAssociationSet": [],
        "SubnetArn": "arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:subnet/subnet-xxxxxxxxxxxxxxxxx"
    }
}

Yeah!

インターネットゲートウェイの作成とVPCへのアタッチ

インターネットゲートウェイがVPCにアタッチされるまではVPC内の何もインターネットとつながることはできません. そこでInternet Gatewayを作成し, VPCにアタッチします.

$ aws ec2 create-internet-gateway
{
    "InternetGateway": {
        "Attachments": [],
        "InternetGatewayId": "igw-xxxxxxxxxxxxxxxxx",
        "OwnerId": "xxxxxxxxxxxx",
        "Tags": []
    }
}
create-internet-gatewayに対するレスポンス
$ aws ec2 attach-internet-gateway `
--internet-gateway-id igw-xxxxxxxxxxxxxxxxx `
--vpc-id vpc-xxxxxxxxxxxxxxxxx

上記コマンドに対してはレスポンスがありませんでした.

ルートテーブルの作成とルートの作成, サブネットへの関連付け

作成したサブネットがインターネットゲートウェイとつながるようにしましょう.

$ aws ec2 create-route-table --vpc-id vpc-xxxxxxxxxxxxxxxxx
{
    "RouteTable": {
        "Associations": [],
        "PropagatingVgws": [],
        "RouteTableId": "rtb-xxxxxxxxxxxxxxxxx",
        "Routes": [
            {
                "DestinationCidrBlock": "10.0.0.0/16",
                "GatewayId": "local",
                "Origin": "CreateRouteTable",
                "State": "active"
            }
        ],
        "Tags": [],
        "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
        "OwnerId": "xxxxxxxxxxxx"
    }
}
create-route-table に対するレスポンス

DestinationCidrBlock: "10.0.0.0/16" , "GatewayId": "local" という部分がありますね. あとはこれ以外のときインターネットゲートウェイに繋がってもらいましょう.

$ aws ec2 create-route `
--destination-cidr-block 0.0.0.0/0 `
--gateway-id igw-xxxxxxxxxxxxxxxxx `
--route-table-id rtb-xxxxxxxxxxxxxxxxx `
{
    "Return": true
}
create-route に対するレスポンス

describe-route-tables を使ってテーブルがどのようになったかを確かめることもできます.

最後, ルートテーブルをサブネットに関連付けしてしまいましょう.

$ aws ec2 associate-route-table `
--route-table-id rtb-xxxxxxxxxxxxxxxxx `
--subnet-id subnet-xxxxxxxxxxxxxxxxx
{
    "AssociationId": "rtbassoc-xxxxxxxxxxxxxxxxx",
    "AssociationState": {
        "State": "associated"
    }
}
associate-route-table に対するレスポンス

セキュリティグループの作成

あとでインスタンスに関連付けるセキュリティグループを作成しておきます. 内容としては自分の家のグローバルIPアドレスからの22番インバウンドアクセスの許可です.

$ aws ec2 create-security-group `
--description "for test instance" `
--group-name testInstanceGroup `
--vpc-id vpc-xxxxxxxxxxxxxxxxx `
{
    "GroupId": "sg-xxxxxxxxxxxxxxxxx"
}
create-security-group に対するレスポンス

ルールを追加しておきます. なお, xxx.xxx.xxx.xxxはあなたのグローバルIPアドレスをいれてください.

$ aws ec2 authorize-security-group-ingress `
--group-id sg-xxxxxxxxxxxxxxxxx `
--protocol tcp
--port 22
--cidr xxx.xxx.xxx.xxx/32

このコマンドは何も応答を返しませんが, 設定は describe-security-groups で確認できます.

キーペアの作成

インスタンスを作成するときにAmazon EC2にキーペアを指定する必要があります. そこでそのキーペアを作ってみましょう.

$ aws ec2 create-key-pair --key-name testKey --query 'KeyMaterial' --output text | out-file -encoding ascii -filepath testKeyPair.pem

作業ディレクトリ上に testKeyPair.pem が出来ていることが確認できると思います.

インスタンスの作成

これでインスタンスを作れます! 無料利用枠の対象となるように次のものを使います.

  • Amazon Linux 2 AMI (HVM), SSD Volume Type: ami-0a1c2ec61571737db
  • インスタンスタイプ t2.micro
$ aws ec2 run-instances `
--image-id ami-0a1c2ec61571737db `
--count 1 `
--instance-type t2.micro `
--key-name testKey `
--security-group-ids sg-xxxxxxxxxxxxxxxxx `
--subnet-id subnet-xxxxxxxxxxxxxxxxx
{
    "Groups": [],
    "Instances": [
        {
            "AmiLaunchIndex": 0,
            "ImageId": "ami-0a1c2ec61571737db",
            "InstanceId": "i-xxxxxxxxxxxxxxxxx",
            "InstanceType": "t2.micro",
            "KeyName": "testKey",
            "LaunchTime": "2020-06-28T13:38:09+00:00",
            "Monitoring": {
                "State": "disabled"
            },
            "Placement": {
                "AvailabilityZone": "ap-northeast-1a",
                "GroupName": "",
                "Tenancy": "default"
            },
            "PrivateDnsName": "ip-10-0-1-148.ap-northeast-1.compute.internal",
            "PrivateIpAddress": "10.0.1.148",
            "ProductCodes": [],
            "PublicDnsName": "",
            "State": {
                "Code": 0,
                "Name": "pending"
            },
            "StateTransitionReason": "",
            "SubnetId": "subnet-xxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
            "Architecture": "x86_64",
            "BlockDeviceMappings": [],
            "ClientToken": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "EbsOptimized": false,
            "Hypervisor": "xen",
            "NetworkInterfaces": [
                {
                    "Attachment": {
                        "AttachTime": "2020-06-28T13:38:09+00:00",
                        "AttachmentId": "eni-attach-xxxxxxxxxxxxxxxxx",
                        "DeleteOnTermination": true,
                        "DeviceIndex": 0,
                        "Status": "attaching"
                    },
                    "Description": "",
                    "Groups": [
                        {
                            "GroupName": "testInstanceGroup",
                            "GroupId": "sg-xxxxxxxxxxxxxxxxx"
                        }
                    ],
                    "Ipv6Addresses": [],
                    "MacAddress": "06:09:de:b1:17:10",
                    "NetworkInterfaceId": "eni-xxxxxxxxxxxxxxxxx",
                    "OwnerId": "xxxxxxxxxxxx",
                    "PrivateIpAddress": "10.0.1.148",
                    "PrivateIpAddresses": [
                        {
                            "Primary": true,
                            "PrivateIpAddress": "10.0.1.148"
                        }
                    ],
                    "SourceDestCheck": true,
                    "Status": "in-use",
                    "SubnetId": "subnet-xxxxxxxxxxxxxxxxx",
                    "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
                    "InterfaceType": "interface"
                }
            ],
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "SecurityGroups": [
                {
                    "GroupName": "testInstanceGroup",
                    "GroupId": "sg-xxxxxxxxxxxxxxxxx"
                }
            ],
            "SourceDestCheck": true,
            "StateReason": {
                "Code": "pending",
                "Message": "pending"
            },
            "VirtualizationType": "hvm",
            "CpuOptions": {
                "CoreCount": 1,
                "ThreadsPerCore": 1
            },
            "CapacityReservationSpecification": {
                "CapacityReservationPreference": "open"
            },
            "MetadataOptions": {
                "State": "pending",
                "HttpTokens": "optional",
                "HttpPutResponseHopLimit": 1,
                "HttpEndpoint": "enabled"
            }
        }
    ],
    "OwnerId": "xxxxxxxxxxxx",
    "ReservationId": "r-xxxxxxxxxxxxxxxxx"
}
run-instances に対するレスポンス

起動確認してみましょう. なんとなく時間が経ったと思ったら実行してみてください.

$ aws ec2 describe-instance-status
{
    "InstanceStatuses": [
        {
            "AvailabilityZone": "ap-northeast-1a",
            "InstanceId": "i-xxxxxxxxxxxxxxxxx",
            "InstanceState": {
                "Code": 16,
                "Name": "running"
            },
            "InstanceStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "passed"
                    }
                ],
                "Status": "ok"
            },
            "SystemStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "passed"
                    }
                ],
                "Status": "ok"
            }
        }
    ]
}

インスタンスが起動できましたね!!!

おまけ:インスタンスへの接続

Elastic IP アドレスを取得, インスタンスに割り当てておきおましょう.

インスタンスにパブリックIPアドレスが割り当てられている場合, 次のコマンドでインスタンスのパブリックIPアドレスが確認できます

$ aws ec2 describe-addresses

お好きなSSHクライアントを使って接続してみましょう.

インスタンスへのSSH接続

お疲れさまです!インスタンスの起動が完了し, しかも接続できました!

インスタンスの終了

今回のインスタンスは終了しておきましょう.

$ aws ec2 terminate-instances --instance-ids i-xxxxxxxxxxxxxxxxx
{
    "TerminatingInstances": [
        {
            "CurrentState": {
                "Code": 32,
                "Name": "shutting-down"
            },
            "InstanceId": "i-0a3a1d247a89918b2",
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}
terminate-instances に対するレスポンス

インスタンスが終了したら, Elastic IPアドレスはリリースしておきましょう. 課金されてしまいます.

$ aws ec2 release-address `
--allocation-id eipalloc-xxxxxxxxxxxxxxxxx