ちょうど今AWS環境におけるサーバ構築の効率化を進めているので、
使っている AWS CLI をまとめたいと思います。
前提
aws cli のインストール、認証情報の登録は済んでいることとする。
使用するAMIは準備済み。
EC2インスタンス作成
最初に AWS CLI でインスタンスを作成してみる。
AWS CLI は json形式で設定値を流し込むことが出来ます。
--generate-cli-skeleton オプションで jsonファイルのひな型を出力することが出来るので以下を実行。
aws ec2 run-instances --generate-cli-skeleton
jsonファイルが出力されるので、それを基に以下のような感じで指定したい項目を埋めていく。
※適宜必要な項目を埋めて下さい。
{
"BlockDeviceMappings": [
{
"DeviceName": "/dev/sda1",
"VirtualName": "${InstanceName}",
"Ebs": {
"DeleteOnTermination": true,
"VolumeSize": 40,
"VolumeType": "gp2"
},
"NoDevice": ""
}
],
"ImageId": "${AMIID}",
"InstanceType": "t2.micro",
"MaxCount": 1,
"MinCount": 1,
"Monitoring": {
"Enabled": false
},
"Placement": {
"AvailabilityZone": "ap-northeast-1d"
},
"SubnetId": "${SubnetID}",
"UserData": "",
"AdditionalInfo": "",
"DisableApiTermination": true,
"DryRun": false,
"IamInstanceProfile": {
"Name": "${RoleName}"
},
"InstanceInitiatedShutdownBehavior": "stop",
"NetworkInterfaces": [
{
"AssociatePublicIpAddress": true,
"DeleteOnTermination": true,
"Description": "",
"DeviceIndex": 0,
"Groups": [
"${SecurityGroupID}"
],
"PrivateIpAddresses": [
{
"Primary": true,
"PrivateIpAddress": "173.16.0.5"
}
],
"SubnetId": "${SubnetID}"
}
],
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [
{
"Value": "${任意の値}",
"Key": "${任意のキー}"
},
{
"Value": "${任意の値}",
"Key": "${任意のキー}"
}
]
},
{
"ResourceType": "volume",
"Tags": [
{
"Value": "${任意の値}",
"Key": "${任意のキー}"
},
{
"Value": "${任意の値}",
"Key": "${任意のキー}"
}
]
}
]
}
- VirtualName ... インスタンス名
- VolumeSize ... EBSボリュームサイズ
- VolumeType ... EBSボリュームタイプ
- DeleteOnTermination ... インスタンス削除時にEBSボリュームも一緒に削除するかどうか
- ImageId ... ベースとなるAMI ID を指定
- DisableApiTermination ... 削除保護の有無
- IamInstanceProfile ... IAMロール名
- Groups ... セキュリティグループ名
- PrivateIpAddress ... プライベートIPアドレス
- SubnetId ... サブネットID
- TagSpecifications ... タグの指定(上記の例ではインスタンスとボリュームの両方に2つずつタグをつけている)
で、それを --cli-input-json で指定すればOK
aws ec2 run-instances --cli-input-json file:///path/to/dir/ec2.json
※jsonファイルは file:// で指定しないと以下のようなエラーになるので注意。
[エラー文言]
Error parsing parameter 'cli-input-json': Invalid JSON: No JSON object could be decoded
これでインスタンスが作成されます。
EIP取得
次は、EIPを取得してさっき作成したインスタンスに紐づけてみる。
まずは、EIPを取得。
※ --output text は特定の値を取りたいときに便利です。以下の場合は AllocationID が戻り値で取れます。
aws ec2 allocate-address --domain vpc --query AllocationId --output text
そして、紐付けたい AllocationID と InstanceID を指定すればOK
aws ec2 associate-address --allocation-id ${AllocationID} --instance ${InstanceID}
これで作成したインスタンスにEIPが紐づきました。
SecurityGroup作成
次は、セキュリティグループの作成から、ルールの追加、インスタンスへの紐づけをやってみる。
これも json ファイルを出力する。
aws ec2 create-security-group --generate-cli-skeleton
少ないからオプションで指定してもいいかもしれないが、せっかくだから --cli-input-json でやりたい。
{
"Description": "${Description}",
"GroupName": "${SecurityGroupName}",
"VpcId": "${VPCID}"
}
- Description ... 説明
- GroupName ... セキュリティグループ名
- VpcId ... VPC ID
こんな感じで値を入れて、以下の通り実行。
※ --output text を入れているので戻り値は SecurityGroupID
aws ec2 create-security-group --cli-input-json file:///path/to/dir/securitygroup.json --output text
そして、作ったセキュリティグループにルールを追加。
これもまずは json 出力して
aws ec2 authorize-security-group-ingress --generate-cli-skeleton
必要な値を入れて
{
"GroupId": "${SecurityGroupID}",
"IpPermissions": [
{
"FromPort": 0,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "173.16.0.5/32",
"Description": ""
}
],
"FromPort": 22,
"ToPort": 22
}
],
"DryRun": false
}
- GroupId ... セキュリティグループID
- CidrIp ... ソースIP
- FromPort,ToPort ... ポート範囲
以下の通り実行。
aws ec2 authorize-security-group-ingress --cli-input-json file:///path/to/dir/rule.json
これでセキュリティグループが作成できたので、インスタンスに適用してみよう。
aws ec2 modify-instance-attribute --group ${SecurityGroupID} --instance-id ${InstanceID}
既にセキュリティグループが設定されているインスタンスの場合は置き換わってしまうので注意!
--group で指定したセキュリティグループのみになってしまうので、追加したい場合は下記のようにスペース区切りで複数指定して下さい。
aws ec2 modify-instance-attribute --group ${SecurityGroupID} ${SecurityGroupID} --instance-id ${InstanceID}
#running になるまで待つ
EIPの紐づけにしても、セキュリティグループの紐づけにしても、
インスタンスの状態が running にならないと以下のようなエラーになってしまう。
An error occurred (InvalidInstanceID) when calling the AssociateAddress operation: The pending instance '${InstanceID}' is not in a valid state for this operation.
なので、一連の処理をシェルスクリプト等でまとめてやろうとすると、
インスタンス状態の判定が必要になる。
僕は以下のようにインスタンスの状態を判定していたのだが、、
STATE=`aws ec2 describe-instances --instance-ids ${InstanceID} --query 'Reservations[*].Instances[*].State[].Name' --output text`
while [ $STATE != "running" ]
do
sleep 5
STATE=`aws ec2 describe-instances --instance-ids ${InstanceID} --query 'Reservations[*].Instances[*].State[].Name' --output text`
done
こんなことせずとも、以下でステータスの状態が running になるまで待ってくれます。。
aws ec2 wait instance-running --instance-ids ${InstanceID}
ちなみに、wait は他にも色んなオプションがあるので何かと便利。
例えば、システムチェックが終わるのを待ちたい場合はこれ。
aws ec2 wait instance-status-ok --instance-ids ${InstanceID}
FORK Advent Calendar 2018
18日目 ちょっとかわいいBrainF*ck @sunnyplace
19日目 git clone できない時の調べ方と対策 @izanari