amareloのブログ(仮)

IT系勉強会で感じた想いや知見をメインに書いていきます。

JAWS-UG CLI専門支部 #158R EC2基礎(AMI) 参加レポート

6/18(木)、JAWS-UG CLI専門支部 #158R EC2基礎(AMI) に参加しました。今回もハンズオンの感想と学んだコマンドについて書こうと思います。

目次

イベントページ

jawsug-cli.connpass.com

ハンズオンでやったこと

以下の通りです。事前準備として、Cloud9上にハンズオン環境を構築しました。 ハンズオンでは、Cloud9のターミナルでコマンド実行しました。

AMI(Amazon Machine Images)とは

  • Amazon マシンイメージ (AMI) には、インスタンスの起動に必要な情報が用意されている(公式ドキュメントより)。
  • インスタンスを起動するときは、AMI を指定する必要がある(公式ドキュメントより)。
  • AMIはEBSスナップショットに紐づいた形で登録される。
  • 登録を解除するときはAMIの削除だけでなく、EBSスナップショットも削除する。

感想

前回のEBSの時は出席できませんでしたが、それでもついていくことができてホッとしています(EBS回のハンズオンを後日実施してブログ書きます)。AMIでインスタンスを作成する手順を一つ一つ追うことができて、マネジメントコンソールでやってきたことを再確認しながら理解を深められて良かったです。

ハンズオンで学んだコマンド

事前作業・ハンズオン手順は、こちらを参照してください。

なお、ハンズオン概要としては、以下の通りです。構成図は、こちらを参照してください。

  • CloudformationでVPC作成
  • セキュリティグループにルール追加
  • EC2構築
  • CLIでブラウザアクセス
  • AMI作成
  • AMIからEC2構築
  • 後片付け
1.VPCの構築
  • Cloudformationテンプレートのダウンロードをします。
    • ${CLOUDFORMATION_TEMPLATE_URL} はダウンロード元URLを指定します。
    • ${FILE_CLOUDFORMATION_TEMPLATE} はテンプレート保存ファイル名(フルパス)を指定します。
curl ${CLOUDFORMATION_TEMPLATE_URL} \
  > ${FILE_CLOUDFORMATION_TEMPLATE}
  • cloudformation validate-templateでCloudFormationテンプレートが有効であることを確認します。
    • --tempate-body でテンプレート保存ファイル名(フルパス)を指定します。
aws cloudformation validate-template \
  --template-body file://${FILE_CLOUDFORMATION_TEMPLATE}
  • cloudformation create-stack でCloudformationスタックを作成します。
    • --stack-name でcloudformationスタック名を指定します。
    • --template-body でテンプレート保存ファイル名(フルパス)を指定します。
aws cloudformation create-stack \
  --stack-name ${CLOUDFORMATION_STACK_NAME} \
  --template-body file://${FILE_CLOUDFORMATION_TEMPLATE}
  • cloudformation list-stackでCloudformationスタックが作成されたことを確認します。
aws cloudformation list-stacks \
  --query "StackSummaries[? \
    StackName == \`${CLOUDFORMATION_STACK_NAME}\` \
      && StackStatus != \`DELETE_COMPLETE\` \
    ].StackName" \
  --output text
  • Cloudformationスタックがステータスが"CREATE_COMPLETE"になっていることを確認します。
CLOUDFORMATION_STACK_STATUS=$(\
  aws cloudformation list-stacks \
    --query "StackSummaries[? \
      StackName == \`${CLOUDFORMATION_STACK_NAME}\` \
        && StackStatus != \`DELETE_COMPLETE\` \
      ].StackStatus" \
    --output text \
) \
  && echo ${CLOUDFORMATION_STACK_STATUS}
2.セキュリティグループへのルール追加

※事前にユーザデータ作成がありますが、割愛します。

  • `ec2 describe-vpcs' でVPCタグ名よりVPC IDを取得します。
EC2_VPC_ID=$( \
  aws ec2 describe-vpcs \
    --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
    --query 'Vpcs[].VpcId' \
    --output text \
) \
  && echo ${EC2_VPC_ID}
  • ec2 describe-security-groupsでVPCIDとセキュリティグループ名よりセキュリティグループIDを取得します。
EC2_SECURITY_GROUP_ID=$( \
  aws ec2 describe-security-groups \
    --filter Name=vpc-id,Values=${EC2_VPC_ID} \
      Name=group-name,Values=${EC2_SECURITY_GROUP_NAME} \
    --query "SecurityGroups[].GroupId" \
    --output text \
) \
  && echo ${EC2_SECURITY_GROUP_ID}
  • ルール追加するセキュリティグループID、ルールに追加するプロトコルTCP/UDP)、ポート番号、CIDRを指定して、ec2 authiorize-security-group-ingress を実行します。
aws ec2 authorize-security-group-ingress \
  --group-id ${EC2_SECURITY_GROUP_ID} \
  --protocol ${EC2_SECURITY_GROUP_PROTOCOL} \
  --port ${EC2_SECURITY_GROUP_PORT} \
  --cidr ${EC2_SECURITY_GROUP_CIDR}
  • 追加したルールが存在することを確認します。
aws ec2 describe-security-groups \
  --filter Name=vpc-id,Values=${EC2_VPC_ID} \
    Name=group-name,Values=${EC2_SECURITY_GROUP_NAME} \
    Name=ip-permission.protocol,Values=${EC2_SECURITY_GROUP_PROTOCOL} \
    Name=ip-permission.to-port,Values=${EC2_SECURITY_GROUP_PORT} \
    Name=ip-permission.cidr,Values=${EC2_SECURITY_GROUP_CIDR} \
  --query "SecurityGroups[].IpPermissions[?IpProtocol == \`${EC2_SECURITY_GROUP_PROTOCOL}\` \
    && ToPort == \`${EC2_SECURITY_GROUP_PORT}\` \
    && IpRanges[?CidrIp == \`${EC2_SECURITY_GROUP_CIDR}\`]].IpRanges[][].CidrIp" \
  --output text
3.EC2インスタンスの起動
  • イメージID、インスタンスタイプ、セキュリティグループ、タグキーと値、サブネットID、ユーザデータファイルを指定して、ec2 run-instancesを実行します。
aws ec2 run-instances \
  --image-id ${EC2_IMAGE_ID} \
  --instance-type ${EC2_INSTANCE_TYPE} \
  --security-group-ids ${ARRAY_EC2_SECURITY_GROUP_IDS} \
  --tag-specifications ${STRING_TAG_CONF} \
  --subnet-id ${EC2_SUBNET_ID} \
  --user-data file://${FILE_USER_DATA}
4.EC2インスタンスへのCLIブラウザアクセス

インスタンスID取得

ARRAY_EC2_INSTANCE_IDS=$( \
  aws ec2 describe-instances \
    --filters Name=tag-key,Values=Name \
              Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
    --query Reservations[].Instances[].InstanceId \
    --output text \
) \
  && echo ${ARRAY_EC2_INSTANCE_IDS}

グローバルIPアドレス取得

EC2_PUBLIC_IP=$( \
  aws ec2 describe-instances \
    --filters Name=tag-key,Values=Name \
              Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
    --instance-ids ${ARRAY_EC2_INSTANCE_IDS} \
    --query "Reservations[].Instances[].PublicIpAddress" \
    --output text \
) \
  && echo ${EC2_PUBLIC_IP}
curl ${CURL_TARGET_URL}
curl -LI -Ss \
  -o /dev/null \
  -w '%{http_code}\n' \
  ${CURL_TARGET_URL}
5.AMIの作成
  • インスタンスID、マシンイメージ名、AMIの説明を指定して、ec2 create-imageを実行します。
aws ec2 create-image \
  --instance-id ${EC2_INSTANCE_ID} \
  --name ${EC2_MACHINE_IMAGE_NAME} \
  --description "${EC2_MACHINE_IMAGE_DESCRIPTION}"
  • describe-images で作成したAMIイメージが存在することを確認します。
aws ec2 describe-images \
  --filter "Name=name, Values=${EC2_MACHINE_IMAGE_NAME}" \
  --query 'Images[].Name' \
  --output text
  • 作成したAMIがavailableであることを確認します。
EC2_MACHINE_IMAGE_STATE=$( \
  aws ec2 describe-images \
    --filters Name=name,Values="${EC2_MACHINE_IMAGE_NAME}" \
    --query "Images[?Name == \`${EC2_MACHINE_IMAGE_NAME}\`].State" \
    --output text \
) \
  && echo ${EC2_MACHINE_IMAGE_STATE}
6.EC2インスタンスの終了

AMIを作成したEC2インスタンスを終了させます。

aws ec2 terminate-instances \
  --instance-ids ${ARRAY_EC2_INSTANCE_IDS}
  • 削除したインスタンスが、ステータス"running"で存在していないことを確認します。
aws ec2 describe-instances \
  --filters Name=tag-key,Values=Name \
            Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
            Name=instance-state-name,Values=running \
  --query Reservations[].Instances[].Tags[].Value \
  --output text
7.EC2インスタンス(AMI利用)の構築
  • 作成したAMI、インスタンスタイプ、セキュリティグループ、タグキーと値、サブネットIDを指定し、ec2 run-instances を実行します。
    • --associate-public-ip-address でパブリックIPアドレスが割り振られるよう指定します。
aws ec2 run-instances \
  --image-id ${EC2_IMAGE_ID} \
  --instance-type ${EC2_INSTANCE_TYPE} \
  --security-group-ids ${ARRAY_EC2_SECURITY_GROUP_IDS} \
  --tag-specifications ${STRING_TAG_CONF} \
  --subnet-id ${EC2_SUBNET_ID} \
  --associate-public-ip-address
  • 作成したEC2のインスタンス名が、ステータス"running"で存在することを確認します。
aws ec2 describe-instances \
  --filters Name=tag-key,Values=Name \
            Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
            Name=instance-state-name,Values=running \
  --query Reservations[].Instances[].Tags[].Value \
  --output text
  • [4.EC2インスタンスへのCLIブラウザアクセス]と同じ要領でCLIブラウザアクセスを実行します。
    • 正常にコンテンツにアクセスでき、ステータスコード200が返ってくることを確認します。
8.後始末

ハンズオン環境が不要になったら、ハンズオン手順の後始末以降の手順を実施します。

今回は後始末で実行したコマンドも書きます。

EC2インスタンスの終了
aws ec2 terminate-instances \
  --instance-ids ${ARRAY_EC2_INSTANCE_IDS}
セキュリティグループのIngressルール削除
  • 削除するセキュリティグループのグループID、削除するルール(プロトコル、ポート、CIDR)を指定して、ec2 revoke-security-group-ingress でルールの削除をします。
aws ec2 revoke-security-group-ingress \
  --group-id ${EC2_SECURITY_GROUP_ID} \
  --protocol ${EC2_SECURITY_GROUP_PROTOCOL} \
  --port ${EC2_SECURITY_GROUP_PORT} \
  --cidr ${EC2_SECURITY_GROUP_CIDR}
AMIの削除
  • イメージIDを指定してec2 deregister-imageを実行して、AMIを削除します。
aws ec2 deregister-image \
  --image-id ${EC2_MACHINE_IMAGE_ID}
  • スナップショットIDを指定してec2 delete-snapshotを実行して、EBSスナップショットを削除します。
aws ec2 delete-snapshot \
  --snapshot-id ${EC2_SNAPSHOT_ID}

※スナップショットIDは、AWSIDとマシンイメージを指定してec2 describe-snapshotsを実行して取得します。

EC2_SNAPSHOT_ID=$( \
  aws ec2 describe-snapshots \
    --filters Name=owner-id,Values=${AWS_ID} \
    --query "Snapshots[?contains(Description, \`${EC2_MACHINE_IMAGE_ID}\`)].SnapshotId" \
    --output text \
) \
  && echo ${EC2_SNAPSHOT_ID}
Cloudformationスタックの削除
  • Cloudformationスタック名を指定してcloudformation delete-stackを実行して、スタックを削除します。
aws cloudformation delete-stack \
  --stack-name ${CLOUDFORMATION_STACK_NAME}

最後に

CLI専門支部のハンズオンに何度も参加して復習してきたことで、初めてみるコマンドでも何となく意味が分かってきました。CLIAWS触ることが楽しくなってきました! 次回からはIAMのハンズオンが4回続きます。IAMはSAAの勉強の時に理解したつもりでしたが、きっと理解できていないと思うので、じっくり勉強したいです!

※次回のイベントページ

jawsug-cli.connpass.com