16日目!
今回は、ついに EC2 を立ち上げます。
14日目、15日目はこのためにありました・・・!
16日目の要約
仮想マシンを立ち上げて、動的なコンテンツを表示できるようにするよ!
AWS CLI の準備
このあたりをみて、好きなバージョンとお使いのOSにあった環境設定をしてくださいね。
なんなら、 AWS CloudShell で実行するのも楽でよいと思います。
この記事シリーズは、AWS CloudShell で実行し、実行例を載せています。
バージョン1
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv1.html
バージョン2
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html
概要
最新の AMI を使って、EC2インスタンスを立ち上げます。さらに、名前解決できるようにしてCloudFrontのディストリビューションとしても登録するよ!
さあ、やってみよう!
最新の Amazon Linux 2 の AMI ID を確認する
EC2 インスタンスを作成、起動するには、Amazon Machine Image(AMI)が必要です。どの AMI を使用するのか特定するために、 AMI ID を確認します。
最新の Amazon Linux 2 の AMI ID を特定するには、Simple Systems Manager のコマンドである、 ssm get-parameter を実行します。
aws ssm get-parameter --name /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \
正常に実行できると、以下のような json が返るので、 Value の値を確認します。
この値が 最新の AMI ID です。
{
"Parameter": {
"Name": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2",
"Type": "String",
"Value": "ami-0abaa5b0faf689830",
"Version": 55,
"LastModifiedDate": "2021-12-02T04:23:22.207000+00:00",
"ARN": "arn:aws:ssm:ap-northeast-1::parameter/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2",
"DataType": "text"
}
}
EC2 インスタンスを起動する!
AMI ID の特定ができたら、次は、EC2 インスタンスを起動します。
以下の情報が必要になるので、確認をしてください。
- AMI ID
- サブネット ID
- セキュリティグループ ID
- Route53 のホスティッドゾーン ID
- Route53 に登録したいレコード名(ホスト名+これまでに設定したドメイン名)
- インスタンスプロファイル名
まずは、EC2 インスタンスが起動時に実行するユーザーデータを作成します。
流れとしては、インスタンスメタデータにアクセスし、インスタンス側からパブリックIPv4アドレスとインスタンスIDを取得します。
こうすることにより、起動時に動的に情報を取得・更新、Route53 へのレコード登録ができるようになります。
以下を参考にして、お好みのテキストエディタで作成してください。
#!/bin/bash
HOSTED_ZONE_ID=<Route53 のホスティッドゾーン ID>
RECORD_NAME=<登録したいホスト名>.<ドメイン名>
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
INSTANCE_ID=`curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/instance-id`
IP_ADDRESS=`curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/public-ipv4`
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
usermod -a -G apache ec2-user
mkdir -p /var/www/html/ec2
chown -R ec2-user:apache /var/www
chmod 2775 /var/www
find /var/www -type d -exec chmod 2775 {} \;
find /var/www -type f -exec chmod 0664 {} \;
echo "<HTML><HEAD><TITLE>from EC2</TITLE><BODY>This is ${INSTANCE_ID}.</BODY></HTML>" > /var/www/html/ec2/index.html
aws route53 change-resource-record-sets --hosted-zone-id ${HOSTED_ZONE_ID} \
--change-batch "{\"Changes\": [ { \"Action\": \"UPSERT\", \"ResourceRecordSet\": { \"Name\": \"${RECORD_NAME}.\", \"Type\": \"A\", \"TTL\": 3600, \"ResourceRecords\": [{\"Value\": \"${IP_ADDRESS}\"}]}}]}"
ユーザーデータのファイルが作成できたら、以下を参考にして、 ec2 run-instances コマンドを実行して EC2 インスタンスを起動します。
AMI_ID=<AMI の ID>
SUBNET_ID=<サブネットのID>
SECURITY_GROUP_ID=<セキュリティグループのID>
INSTANCE_PROFILE=<インスタンスプロファイル名>
aws ec2 run-instances \
--image-id ${AMI_ID} \
--instance-type t2.micro \
--subnet-id ${SUBNET_ID} \
--iam-instance-profile "Name=${INSTANCE_PROFILE}" \
--security-group-ids ${SECURITY_GROUP_ID} \
--user-data file://userdata.sh
正常に実行・起動できると json が返りますが長いのでこの記事では割愛します。
念のため、InstanceId
の値を確認してください。
ちなみに、 ec2 run-instances コマンドの --iam-instance-profile
オプションは Name
と Arn
を指定する必要があるような記載がマニュアルにあります。
しかし、実際に両方指定して実行すると、以下のようなエラーが返りますご注意ください。
An error occurred (InvalidParameterCombination) when calling the RunInstances operation: The parameter 'iamInstanceProfile.name' may not be used in combination with 'iamInstanceProfile.arn'
これで、EC2 インスタンスが起動しました。
起動出来たら動作確認として、 curl コマンドでアクセスしたくなりますが、セキュリティグループのインバウンドルールに入っているのは CloudFront からのIPアドレス群のみです。
そのため、動作確認はディストリビューションの設定を変えてからです。
CloudFront のディストリビューションに EC2 をオリジンとして登録する
これまで何回も実施したディストリビューションの変更手順と同じです。
復習を兼ねてみていきましょう。
- cloudfront get-distribution-config コマンドで現状の設定を取得する
- ETag の値を確認する
- 取得した json ファイルに対して、設定変更を加える
- cloudfront update-distribution コマンドを実行して更新する
ディストリビューションの現状の設定を確認する
cloudfront get-distribution-config コマンドを実行して、現在のディストリビューションの設定を出力します。
aws cloudfront get-distribution-config --id <CloudFront の Distribution ID> > distribution_ec2_tmp.json
次に、必要な部分だけ抽出して更新用の元ファイルにします。jq コマンドを使うので、必要に応じてインストールしてください。AWS CloudShell であれば標準でインストール済みです。
cat distribution_ec2_tmp.json | jq .DistributionConfig > distribution_ec2.json
ETag の値を確認する
ディストリビューションの設定変更時に必要になる、 ETag の値を確認します。
cat distribution_ec2_tmp.json | grep ETag
以下のように出力されます。
"ETag": "**************",
json ファイルを編集する
以下を編集します。
- Origins
- CacheBehaviors
Origins
取得してきたディストリビューションには、S3バケットをオリジンとする設定が入っていると思われます。
そのため、2つ目として、EC2 インスタンスをオリジンとして登録します。
- Quantity の値を2にします
- 以下の内容を Items のS3 バケットをオリジンとする定義の前に書き込みます。
{
"Id": "<Route53 に登録したEC2のレコード>",
"DomainName": "<Route53 に登録したEC2のレコード>",
"OriginPath": "",
"CustomHeaders": {
"Quantity": 0
},
"CustomOriginConfig": {
"HTTPPort": 80,
"HTTPSPort": 443,
"OriginProtocolPolicy": "http-only",
"OriginSslProtocols": {
"Quantity": 3,
"Items": [
"TLSv1",
"TLSv1.1",
"TLSv1.2"
]
},
"OriginReadTimeout": 30,
"OriginKeepaliveTimeout": 5
},
"ConnectionAttempts": 3,
"ConnectionTimeout": 10,
"OriginShield": {
"Enabled": false
}
},
CacheBehaviors
次にキャッシュビヘイビアの設定を行います。
今回は、キャッシュのTTLをゼロにします。
EC2 インスタンスのユーザーデータの内容を確認された方ならこれでピンとくるかもしれませんが、起動時にインスタンス ID を index.html に書き込んでいます。
この index.html をキャッシュに持ってしまうと、EC2 インスタンスが入れ替わった際にも TTL が切れるまで古いインスタンス ID の情報が返ってしまいます。
それを防ぐために、敢えてゼロとしました。
ちなみにデフォルトの TTL は86,400秒、つまり、24時間です(3,600 秒 * 24時間)。最大TTLは、31,536,000秒なので1年が設定されています。
- 以下の内容を CacheBehaviors の定義を編集します。
"CacheBehaviors": {
"Quantity": 0
},
"CacheBehaviors": {
"Quantity": 1,
"Items": [
{
"PathPattern": "ec2/*",
"TargetOriginId": "<Route53 に登録したEC2のレコード>",
"TrustedSigners": {
"Enabled": false,
"Quantity": 0
},
"TrustedKeyGroups": {
"Enabled": false,
"Quantity": 0
},
"ViewerProtocolPolicy": "allow-all",
"AllowedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
],
"CachedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
]
}
},
"SmoothStreaming": false,
"Compress": true,
"LambdaFunctionAssociations": {
"Quantity": 0
},
"FunctionAssociations": {
"Quantity": 0
},
"FieldLevelEncryptionId": "",
"ForwardedValues": {
"QueryString": false,
"Cookies": {
"Forward": "none"
},
"Headers": {
"Quantity": 0
},
"QueryStringCacheKeys": {
"Quantity": 0
}
},
"MinTTL": 0,
"DefaultTTL": 0,
"MaxTTL": 0
}
]
},
仕上げ
以下のように頭と末尾に情報を入力します。
1行目に波括弧({)があるので、その2行目に対して、 “DistributionConfig”: { を追加します。
{
"DistributionConfig": {
"CallerReference":
(省略)
次に末尾です。
(省略)
"WebACLId": "",
"HttpVersion": "http2",
"IsIPV6Enabled": true
}
} <-- これを追加する
末尾に閉じ波括弧(})を追加します。
ディストリビューションの設定を更新する
更新用のファイルが準備できたら、cloudfront update-distribution コマンドを実行して、設定変更を行います。
aws cloudfront update-distribution --id <CloudFront Distribution ID> --cli-input-json file://distribution_ec2.json --if-match 確認したETag の値
コマンド実行に成功すると、Distribution の内容が記された json が返されます。
案の定、長いので割愛します💦
動作確認
設定変更ができたので、以下の様に curl を実行してみましょう。
curl https://<CloudFrontのドメイン名>/ec2/index.html
すると、以下の様に インスタンスID が入った HTML が返ってきます。
返ってこない場合は、WAF のアノニマスIPアドレスのルールが当たっている可能性があります。
その場合はルールを一時的に解除するか、ローカルのターミナルなどでご確認ください。
<HTML><HEAD><TITLE>from EC2</TITLE><BODY>This is (インスタンスID).</BODY></HTML>
まとめ
準備編が2回あり、ついに EC2 インスタンスが起動しました!
さて、明日は、現在1台の EC2 インスタンスの可用性を挙げるべく、冗長構成にしていきます。
お楽しみに♪