AWS CLIで Web サイトを構築、管理、運用する(18日目)

18日目！

EC2 インスタンスの可用性向上のために冗長化をするシリーズ2日目です。
昨日は、サブネットを追加し、さらに ALB を作成しました。
今回は、AutoScaling の設定をしますよ！

# 18日目の要約
冗長化するよ！

# AWS CLI の準備
このあたりをみて、好きなバージョンとお使いのOSにあった環境設定をしてくださいね。
なんなら、 AWS CloudShell で実行するのも楽でよいと思います。
この記事シリーズは、AWS CloudShell で実行し、実行例を載せています。

バージョン１
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv1.html

バージョン２
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html

# 概要
AutoScaling をつかって EC2 インスタンスの可用性を高めるよ！！


# さあ、やってみよう！
## 16日目に起動した EC2 インスタンスのイメージを取得する
これから Auto Scaling を設定し起動する EC2 インスタンスはプライベートサブネットに起動させるのでユーザーデータ内で Apache(HTTPサーバー)をインストールすることができません。16日目に起動した EC2 インスタンスには Apache(HTTPサーバー)がインストールされているので、 Amazon Machine Image(AMI) を取得して利用します。

ec2 create-image コマンドで AMI を取得することができます。

```sh
aws ec2 create-image --instance-id <16日目に起動したEC2インスタンスのID> --name ami-web-server
```

AMI の作成が行われると、以下のような json が返ってきます。
この AMI ID を使って、この後の起動設定を作成していきます。

```json
{
    "ImageId": "ami-＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊"
}
```


## 起動設定を作る
使用する AMI ID が判明したら、```autoscaling create-launch-configuration```` コマンドで起動設定を作っていきます。

実行前にユーザーデータを作成しておきます。

```sh:userdata2.sh
#!/bin/bash
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`

echo "<HTML><HEAD><TITLE>from EC2</TITLE><BODY>This is ${INSTANCE_ID}.<br>Enjoy Auto Scaling!!</BODY></HTML>" > /var/www/html/ec2/index.html
```

ユーザーデータを作成したら、```autoscaling create-launch-configuration```` コマンドを実行します。

```sh
aws autoscaling create-launch-configuration \
--launch-configuration-name lc-web-server \
--image-id <先ほど取得した AMI ID> \
--security-groups <sg_web2 の ID> \
--instance-type t2.micro \
--user-data file://userdata2.sh
```

実行しても何も返りません。

## Auto Scaling グループを作成する

```sh
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name asg-web-server \
--launch-configuration-name lc-web-server \
--min-size 2 \
--max-size 2 \
--desired-capacity 2 \
--target-group-arns <ターゲットグループの ARN> \
--health-check-type ELB \
--health-check-grace-period 300 \
--vpc-zone-identifier "<1つ目のプライベートサブネットのID>,<2つ目のプライベートサブネットのID>" 
```

こちらも特に何も返りません。

## CloudFront のディストリビューション設定を変更する
16日目に、 EC2 インスタンスをディストリビューションに登録していたので、この設定を ALB の　CNAME に置き換えます。

やはり、これまで何回も実施したディストリビューションの変更手順と同じです。

1. cloudfront get-distribution-config コマンドで現状の設定を取得する
2. ETag の値を確認する
3. 取得した json ファイルに対して、設定変更を加える
4. cloudfront update-distribution コマンドを実行して更新する

### ディストリビューションの現状の設定を確認する
cloudfront get-distribution-config コマンドを実行して、現在のディストリビューションの設定を出力します。

```sh
aws cloudfront get-distribution-config --id <CloudFront の Distribution ID> > distribution_asg_tmp.json
```

次に、必要な部分だけ抽出して更新用の元ファイルにします。jq コマンドを使うので、必要に応じてインストールしてください。AWS CloudShell であれば標準でインストール済みです。

```sh
cat distribution_asg_tmp.json | jq .DistributionConfig > distribution_asg.json
```

### ETag の値を確認する
ディストリビューションの設定変更時に必要になる、 ETag の値を確認します。

```sh
cat distribution_asg_tmp.json | grep ETag
```

以下のように出力されます。

```json
    "ETag": "**************",
```

### json ファイルを編集する
以下を編集します。

* Origins

#### Origins
取得してきたディストリビューションには、16日目で指定した EC2 インスタンスの DNSName が入っていると思います。```DomainName``` の値を ALB のDNSName に置き換えます。
※```Id``` も同じ値が入っていますが、今回は16日目で指定した EC2 インスタンスのDNSName のままにします。



#### 仕上げ
以下のように頭と末尾に情報を入力します。
1行目に波括弧({)があるので、その2行目に対して、 “DistributionConfig”: { を追加します。

```json:distributionconfig.json_頭
{
"DistributionConfig": {
  "CallerReference": 

（省略）
```

次に末尾です。

```json:distributionconfig.json_末尾
(省略)
  "WebACLId": "",
  "HttpVersion": "http2",
  "IsIPV6Enabled": true
 }
}   <-- これを追加する
```
末尾に閉じ波括弧(})を追加します。


### ディストリビューションの設定を更新する
更新用のファイルが準備できたら、cloudfront update-distribution コマンドを実行して、設定変更を行います。

```sh
aws cloudfront update-distribution --id <CloudFront Distribution ID> --cli-input-json file://distribution_asg.json --if-match 確認したETag の値
```

コマンド実行に成功すると、Distribution の内容が記された json が返されます。
案の定、長いので割愛します💦


## 動作確認
設定変更ができたので、以下の様に curl を実行してみましょう。

```sh
curl https://<CloudFrontのドメイン名>/ec2/index.html
```

すると、以下の様に インスタンスID が入った HTML が返ってきます。
返ってこない場合は、WAF のアノニマスIPアドレスのルールが当たっている可能性があります。
その場合はルールを一時的に解除するか、ローカルのターミナルなどでご確認ください。

```HTML:見やすく改行を入れています。
<HTML>
 <HEAD>
 <TITLE>from EC2</TITLE>
 <BODY>
  This is <AutoScaling EC2 インスタンス1つ目のID>.<br>
  Enjoy Auto Scaling!!.
 </BODY>
</HTML>
```

Auto Scaling を設定しているので、リクエストを飛ばす度にインスタンスIDが切り替わります。

```sh
curl https://<CloudFrontのドメイン名>/ec2/index.html
<HTML><HEAD><TITLE>from EC2</TITLE><BODY>This is <AutoScaling EC2 インスタンス2つ目のID>.<br>Enjoy Auto Scaling!!.</BODY></HTML>

curl https://<CloudFrontのドメイン名>/ec2/index.html
<HTML><HEAD><TITLE>from EC2</TITLE><BODY>This is <AutoScaling EC2 インスタンス1つ目のID>.<br>Enjoy Auto Scaling!!.</BODY></HTML>

curl https://<CloudFrontのドメイン名>/ec2/index.html
<HTML><HEAD><TITLE>from EC2</TITLE><BODY>This is <AutoScaling EC2 インスタンス2つ目のID>.<br>Enjoy Auto Scaling!!.</BODY></HTML>
```

# まとめ
というわけで、EC2 インスタンスを Auto Scaling の設定を行いました。
これにより、EC2 インスタンスの可用性を高めることに繋げられました。
例えば、EC2 インスタンスが止まったとしても、自動的に置き換えが行われます。
これで何かあった時も安心ですね！