メインコンテンツまでスキップ

AWS CLIでVPCを作ってEC2を起動する

· 約10分
moritalous

マネジメントコンソールを使うと、色々と自動でやってくれるので便利ではあるのですが、CLIで一つ一つ作成することで理解が深まると思います。

事前知識

シェルコマンドの実行結果を変数に代入する

変数=`コマンド`
実行例
[cloudshell-user@ip-10-0-113-58 ~]$ echo "Hello, World"
Hello, World
[cloudshell-user@ip-10-0-113-58 ~]$ message=`echo "Hello, World"`
[cloudshell-user@ip-10-0-113-58 ~]$ echo ${message}
Hello, World
[cloudshell-user@ip-10-0-113-58 ~]$

AWS CLIの--queryの使い方

  • --queryなし
aws ec2  describe-regions
出力例
{
"Regions": [
{
"Endpoint": "ec2.eu-north-1.amazonaws.com",
"RegionName": "eu-north-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.ap-south-1.amazonaws.com",
"RegionName": "ap-south-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.eu-west-3.amazonaws.com",
"RegionName": "eu-west-3",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.eu-west-2.amazonaws.com",
"RegionName": "eu-west-2",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.eu-west-1.amazonaws.com",
"RegionName": "eu-west-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.ap-northeast-3.amazonaws.com",
"RegionName": "ap-northeast-3",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.ap-northeast-2.amazonaws.com",
"RegionName": "ap-northeast-2",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.ap-northeast-1.amazonaws.com",
"RegionName": "ap-northeast-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.sa-east-1.amazonaws.com",
"RegionName": "sa-east-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.ca-central-1.amazonaws.com",
"RegionName": "ca-central-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.ap-southeast-1.amazonaws.com",
"RegionName": "ap-southeast-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.ap-southeast-2.amazonaws.com",
"RegionName": "ap-southeast-2",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.eu-central-1.amazonaws.com",
"RegionName": "eu-central-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.us-east-1.amazonaws.com",
"RegionName": "us-east-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.us-east-2.amazonaws.com",
"RegionName": "us-east-2",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.us-west-1.amazonaws.com",
"RegionName": "us-west-1",
"OptInStatus": "opt-in-not-required"
},
{
"Endpoint": "ec2.us-west-2.amazonaws.com",
"RegionName": "us-west-2",
"OptInStatus": "opt-in-not-required"
}
]
}
  • RegionNameap-northeast-1のものだけに限定
aws ec2  describe-regions \
--query "Regions[?RegionName == 'ap-northeast-1']"
出力例
[
{
"Endpoint": "ec2.ap-northeast-1.amazonaws.com",
"RegionName": "ap-northeast-1",
"OptInStatus": "opt-in-not-required"
}
]
  • RegionNameap-northeast-1Endpointだけを取得
aws ec2  describe-regions \
--query "Regions[?RegionName == 'ap-northeast-1'].Endpoint | [0]" \
--output text
出力例

--output textによってダブルクオートを外します。

ec2.ap-northeast-1.amazonaws.com

VPC

VPCを作成

VPCを作成します。

vpc_id=`aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=vpc}, {Key=test-id,Value=test}]' \
--query Vpc.VpcId \
--output text`

プライベートサブネットを作成

サブネットを作るとプライベートサブネットとして作成されます。

private_subnet_id=`aws ec2 create-subnet \
--vpc-id ${vpc_id} \
--cidr-block 10.0.1.0/24 \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-subnet}, {Key=test-id,Value=test}]' \
--query Subnet.SubnetId \
--output text`
注記

後続の手順上、必須ではありませんが作成してみました。

パブリックサブネットを作成

サブネットを作っただけではパブリックサブネットにはなりませんので、いくつか対応が必要です。

  1. サブネットを作成
  2. インターネットゲートウェイを作成
  3. VPCにインターネットゲートウェイをアタッチ
  4. カスタムルートテーブルを作成
  5. カスタムルートを追加
  6. サブネットにカスタムルートを関連付け
  7. IPアドレスの自動割り当て有効化

サブネットを作成

プライベートサブネットと同じ要領で作成します。

public_subnet_id=`aws ec2 create-subnet \
--vpc-id ${vpc_id} \
--cidr-block 10.0.0.0/24 \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=public-subnet}, {Key=test-id,Value=test}]' \
--query Subnet.SubnetId \
--output text`

インターネットゲートウェイを作成

インターネットゲートウェイを作成します。

internet_gateway_id=`aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=igw}, {Key=test-id,Value=test}]' \
--query InternetGateway.InternetGatewayId \
--output text`

VPCにインターネットゲートウェイをアタッチ

aws ec2 attach-internet-gateway \
--vpc-id ${vpc_id} \
--internet-gateway-id ${internet_gateway_id}
注意

インターネットゲートウェイはサブネットではなく VPC にアタッチします。

カスタムルートテーブルを作成

  • メインルートテーブル

VPCを作成すると自動的にメインルートテーブルが作成され、カスタムルートテーブルを関連付けていないサブネットは、メインルートテーブルの設定に従ってルーティングされます。

ルートテーブルを確認します。

aws ec2 describe-route-tables \
--query "RouteTables[?VpcId == '${vpc_id}'].{RouteTableId: RouteTableId, Routes: Routes, Associations: Associations}" \
--output table
出力例
-----------------------------------------------------------------------
| DescribeRouteTables |
+---------------------------------------------------------------------+
| RouteTableId |
+---------------------------------------------------------------------+
| rtb-003ca71ad31ef5905 |
+---------------------------------------------------------------------+
|| AssociationsMain ||
|+-------------------------------------------------------------------+|
|| True ||
|+-------------------------------------------------------------------+|
|| Routes ||
|+-----------------------+------------+--------------------+---------+|
|| DestinationCidrBlock | GatewayId | Origin | State ||
|+-----------------------+------------+--------------------+---------+|
|| 10.0.0.0/16 | local | CreateRouteTable | active ||
|+-----------------------+------------+--------------------+---------+|

カスタムルートテーブルを作成します。

public_route_table_id=`aws ec2 create-route-table \
--vpc-id ${vpc_id} \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=rtb-public}, {Key=test-id,Value=test}]' \
--query RouteTable.RouteTableId \
--output text`

カスタムルートを作成

aws ec2 create-route \
--route-table-id ${public_route_table_id} \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id ${internet_gateway_id}

サブネットにカスタムルートを関連付け

aws ec2 associate-route-table \
--subnet-id ${public_subnet_id} \
--route-table-id ${public_route_table_id}

再度ルートテーブルを確認します。

aws ec2 describe-route-tables \
--query "RouteTables[?VpcId == '${vpc_id}'].{RouteTableId: RouteTableId, Routes: Routes, Associations: Associations}" \
--output table
出力例
------------------------------------------------------------------------------------------------
| DescribeRouteTables |
+----------------------------------------------------------------------------------------------+
| RouteTableId |
+----------------------------------------------------------------------------------------------+
| rtb-0592de70117fb7b99 |
+----------------------------------------------------------------------------------------------+
|| Associations ||
|+----------+--------------------------------------------+------------------------------------+|
|| Main | RouteTableAssociationId | RouteTableId ||
|+----------+--------------------------------------------+------------------------------------+|
|| True | rtbassoc-0e722bbcdf502afc3 | rtb-0592de70117fb7b99 ||
|+----------+--------------------------------------------+------------------------------------+|
||| AssociationState |||
||+----------------------------------+-------------------------------------------------------+||
||| State | associated |||
||+----------------------------------+-------------------------------------------------------+||
|| Routes ||
|+--------------------------------+-----------------+---------------------------+-------------+|
|| DestinationCidrBlock | GatewayId | Origin | State ||
|+--------------------------------+-----------------+---------------------------+-------------+|
|| 10.0.0.0/16 | local | CreateRouteTable | active ||
|+--------------------------------+-----------------+---------------------------+-------------+|
| DescribeRouteTables |
+----------------------------------------------------------------------------------------------+
| RouteTableId |
+----------------------------------------------------------------------------------------------+
| rtb-0723db61642f2892b |
+----------------------------------------------------------------------------------------------+
|| Associations ||
|+------+------------------------------+-------------------------+----------------------------+|
|| Main | RouteTableAssociationId | RouteTableId | SubnetId ||
|+------+------------------------------+-------------------------+----------------------------+|
||False | rtbassoc-0cee35b9612d14061 | rtb-0723db61642f2892b | subnet-0c575916b8ff55ec5 ||
|+------+------------------------------+-------------------------+----------------------------+|
||| AssociationState |||
||+----------------------------------+-------------------------------------------------------+||
||| State | associated |||
||+----------------------------------+-------------------------------------------------------+||
|| Routes ||
|+--------------------------+-----------------------------+-----------------------+-----------+|
|| DestinationCidrBlock | GatewayId | Origin | State ||
|+--------------------------+-----------------------------+-----------------------+-----------+|
|| 10.0.0.0/16 | local | CreateRouteTable | active ||
|| 0.0.0.0/0 | igw-01f367841e3ef93b9 | CreateRoute | active ||
|+--------------------------+-----------------------------+-----------------------+-----------+|

インターネットゲートウェイへのルートのあるルートテーブルが、パブリックサブネットに関連づいていることが確認できます。

ヒント

少し手順が多いですが、これでパブリックサブネットが作成できました。

(オプション)IPアドレスの自動割り当て有効化

自動でパブリックIPを割り当てる設定を有効化します。

aws ec2 modify-subnet-attribute \
--subnet-id ${public_subnet_id} \
--map-public-ip-on-launch
注記

サブネット単位での設定なので、プライベートサブネットには影響しません。

EC2

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

セキュリティグループを作成します。

security_group_id=`aws ec2 create-security-group \
--group-name security-group --description "Security group" \
--vpc-id ${vpc_id} \
--query GroupId \
--output text`
注記

セッションマネージャで接続する場合は、インバウンドールールは不要です。

(オプション)セキュリティグループのインバウンドルールを追加

今回の手順では必須ではありませんが、方法だけ紹介です。

注意

セキュリティ的に良くない例となっていますのでご注意ください。

aws ec2 authorize-security-group-ingress \
--group-id ${security_group_id} \
--protocol tcp \
--port 22 \
--cidr 0.0.0.0/0

インスタンスプロファイルを作成

EC2にロールを付与するためのインスタンスプロファイルを作成します。 Systems Managerのセッションマネージャの機能を使いたいので、以下の2つのポリシーを付与します。

  • AmazonSSMManagedInstanceCore
  • AmazonSSMPatchAssociation

IAMロールの作成

信頼関係のポリシードキュメントを作成します。

  • role-trust-policy-for-ec2.json
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}
}
参考情報:ヒアドキュメントを使ったファイルの作成方法
cat <<EOF > role-trust-policy-for-ec2.json
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}
}
EOF

IAMロールを作成します。

aws iam create-role \
--role-name ec2-ssm-role \
--assume-role-policy-document file://role-trust-policy-for-ec2.json

IAMロールにポリシーをアタッチ

ロールにAWS管理ポリシーをアタッチします。

aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore --role-name ec2-ssm-role
aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonSSMPatchAssociation --role-name ec2-ssm-role

インスタンスプロファイルの作成

インスタンスプロファイルを作成します。

aws iam create-instance-profile \
--instance-profile-name ec2-ssm-instance-profile

インスタンスプロファイルにIAMロールを付与

aws iam add-role-to-instance-profile \
--instance-profile-name ec2-ssm-instance-profile \
--role-name ec2-ssm-role
注記

インスタンスプロファイルを使用することで、EC2に対しての権限管理を行うことができます。EC2内にIAMユーザーの認証情報を保持する必要はありません。

EC2を起動する

いよいよEC2を起動します。

Amazon Linux2のAMI IDを検索

起動するAmazon LinuxのAMI IDを検索します。Systems Managerのパラメータストアに格納されているようです。

aws ssm get-parameters-by-path --path /aws/service/ami-amazon-linux-latest --query "Parameters[].Name"
出力例
[
"/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64",
"/aws/service/ami-amazon-linux-latest/al2022-ami-minimal-kernel-5.15-x86_64",
"/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs",
"/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2",
"/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-s3",
"/aws/service/ami-amazon-linux-latest/amzn-ami-minimal-hvm-x86_64-s3",
"/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2",
"/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-ebs",
"/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2",
"/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-x86_64-ebs",
"/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-5.15-x86_64",
"/aws/service/ami-amazon-linux-latest/al2022-ami-minimal-kernel-5.15-arm64",
"/aws/service/ami-amazon-linux-latest/al2022-ami-minimal-kernel-default-x86_64",
"/aws/service/ami-amazon-linux-latest/amzn-ami-minimal-hvm-x86_64-ebs",
"/aws/service/ami-amazon-linux-latest/amzn-ami-minimal-pv-x86_64-ebs",
"/aws/service/ami-amazon-linux-latest/amzn-ami-minimal-pv-x86_64-s3",
"/aws/service/ami-amazon-linux-latest/amzn-ami-pv-x86_64-s3",
"/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-arm64-gp2",
"/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-x86_64-gp2",
"/aws/service/ami-amazon-linux-latest/amzn2-ami-minimal-hvm-arm64-ebs",
"/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-5.15-arm64",
"/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64",
"/aws/service/ami-amazon-linux-latest/al2022-ami-minimal-kernel-default-arm64",
"/aws/service/ami-amazon-linux-latest/amzn-ami-pv-x86_64-ebs",
"/aws/service/ami-amazon-linux-latest/amzn2-ami-minimal-hvm-x86_64-ebs"
]
注記

マネジメントコンソールで新規作成する場合にデフォルトで選択されるAMIは/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-x86_64-gp2のようですのでこれを使用します。

EC2の起動

いよいよEC2の起動です。(作成と同時に起動します。)

  • AMI:Amazon linux 2
  • インスタンスタイプ:t2.micro
  • EBS:20GB
instance_id=`aws ec2 run-instances \
--image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-x86_64-gp2 \
--count 1 \
--instance-type t2.micro \
--security-group-ids ${securyty_group_id} \
--subnet-id ${public_subnet_id} \
--block-device-mappings "[{\"DeviceName\":\"/dev/xvda\",\"Ebs\":{\"VolumeSize\":20}}]" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=test}, {Key=test-id,Value=test}]' \
--iam-instance-profile Name=ec2-ssm-instance-profile \
--query "Instances[].InstanceId" \
--output text`

インスタンス起動後、マネジメントコンソールからセッションマネージャで接続できます。

ヒント

EC2にセッションマネージャでアクセスできました!

注記

プライベートサブネットでEC2を起動した場合はNATゲートウェイを配置するかVPCエンドポイントの作成が必要です。

EC2を操作するコマンド

  • インスタンス停止
aws ec2 stop-instances --instance-ids ${instance_id}
  • インスタンス起動
aws ec2 start-instances --instance-ids ${instance_id}
  • インスタンス再起動
aws ec2 reboot-instances --instance-ids ${instance_id}
  • インスタンス終了(インスタンスが削除されます)
aws ec2 terminate-instances --instance-ids ${instance_id}

参考サイト

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-subnets-commands-example.html