【AWS】ELBとAuto Scalingを使用したスケーラブルなWebアプリケーションの爆速構築

#はじめに

EC2は触ったことがあったのですが、ELBやAutoScalingはなかったので、
今回この記事を作ることにしました。

よくある構成だとは思いますが、
一連の流れを備忘として残して起きます。

今回構築するシステムの概要図は以下の通りです。

Application Load Balancer（ALB）で通信の負荷分散を行います。
また、Auto Scalingを用いて、アクセス量に応じてEC2のインスタンス数を増減させます。

インスタンス数の増減は、Cloud Watchで平均CPU使用率を求めて、
一定の使用率に達したらインスタンスの増減を行うようにしています。
![スクリーンショット 2021-10-02 13.39.34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/0949d4ac-61ce-da81-12ce-c1c5ef0900e1.jpeg)

Auto Scalingを行うことにより、
アクセス数の少ない時間帯（深夜や早朝？）はインスタンス数を減らし、
アクセス数の多い時間帯（昼間〜夕方）はインスタンス数を増やすことができます。

それによってEC2のコストを抑えることが出来るという仕組みですね。

##セキュリティグループの作成
はじめにセキュリティグループを作成します。

ブラウザからHTTPでアクセスするので、自分のIPアドレスかつ、
HTTPプロトコルの場合のみアクセス出来るようなセキュリティを作成します。

セキュリティグループの作成はEC2から行いますので、コンソールからEC2を選択して、
左ペインからセキュリティグループを選択します。

新しく作成する必要があるので、`セキュリティグループを作成`をクリックします。
![スクリーンショット 2021-10-02 13.59.58.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/71659840-3d86-8434-ccb0-4f4cea531c23.jpeg)

セキュリティグループ名はなんでもいいです。
今回は`For Web Server`とかにしておきます。

画像では入力されていませんが、説明も入力する必要があります。
`This is Demo Security`とかにしておきます。

インバウンドルールにて`ルールを追加`をクリックし、
タイプを`HTTP`、ソースを`マイIP`にします。
![スクリーンショット 2021-10-02 14.04.36 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/8b72fb58-9781-b563-2fe5-4b37c96a59fb.jpeg)

アウトバウンドルールはいじらなくて大丈夫です。

タグですが、今回の記事で作ったものだと分かりやすくなるように、
キーに`System`、値を`DemoELB`としてセキュリティグループを作成します。
![スクリーンショット 2021-10-02 14.07.08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/e22f5c87-0600-ed7c-611f-86befcbebdfb.jpeg)

##ターゲットグループの作成
次に、負荷分散を行うターゲットグループの作成を行います。

ターゲットグループの作成はEC2から行いますので、
EC2からの左ペインからターゲットグループを選択します。（結構下の方にあります。）

`ターゲットグループの作成`をクリックします。
![スクリーンショット 2021-10-02 14.13.29.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/5bbec633-6a85-e8bd-637a-45223e72cc95.jpeg)

ターゲットタイプは`インスタンス`を選択します。
![スクリーンショット 2021-10-02 14.15.59.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/dc336263-b54a-7b58-cdae-7ed3a4c8ec33.jpeg)

ターゲットグループ名は`DemoTargetGroup`にします。
プロトコルとVPC、プロトコルのバージョンはデフォルトのままでいきます。
![スクリーンショット 2021-10-02 14.16.47.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/7d3cefa2-b7af-886e-4bcf-dc81cbcbab41.jpeg)

ヘルスチェックプロトコルも`HTTP`を選択し、
ヘルスチェックパスは`/`を指定します。（デフォルト）
![スクリーンショット 2021-10-02 14.20.40.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/5dc03fbb-36d3-8b6c-b84d-4257829e1231.jpeg)

ヘルスチェックの詳細設定は、少し修正していきます。（デフォルトでも平気です。）
間隔を３０秒から`１０秒`に変更します。（すぐに確認できるようにするため）
![スクリーンショット 2021-10-02 14.21.57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/405a9841-578c-43f4-d97d-507a498fdf4b.jpeg)

タグは今回の記事で統一すつので以下のようにします。
これから色々作成するたびにこのタグを入れるので次からは省略します。
![スクリーンショット 2021-10-02 14.20.46.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/4273c600-d0e4-1346-dbe5-a0bc0f9e7b55.jpeg)

全て入力が終わったら、`次へ`をクリックします。
ターゲットはまだ登録できないので、そのままにして作成します。
![スクリーンショット 2021-10-02 14.25.25.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/7b33fbd9-88b6-275d-bfb6-e8ffb5629eae.jpeg)


##Application Load Balancer（ALB）の作成
複数のEC2インスタンスで同じWebアプリケーションを起動します。
入り口として、ALBを用いて負荷分散を行います。

先ほど作成した、セキュリティグループやターゲットグループを用いて、
特定のIPアドレスから特定のターゲットに負荷分散を行うことが可能です。

ALBの作成はEC2から行いますので、
EC2からの左ペインからロードバランサを選択します。（結構下の方にあります。）

何もない状態なので、`ロードバランサの作成`をクリックします。
![スクリーンショット 2021-10-02 13.46.47.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/b3152e6b-bfca-9edc-c565-46d18c5a1c5f.jpeg)

ロードバランサの種類は、一番左の`Application Load Balancer`を選択。

基本的な設定は以下の通りになります。

ロードバランサ名はそのままの意味です。
ここで入力する名前が、ロードバランサの[DNS](https://wa3.i-3-i.info/word1287.html)名に反映されます。

スキームは、`インターネット向け`を選択します。
内部のEC2からEC2にアクセスする際に負荷分散を行う場合は`内部`でいいですが、
今回はブラウザから普通にアクセスするので、インターネット向けにします。
![スクリーンショット 2021-10-02 13.50.26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/3f9c2898-ea80-aee7-26d8-a83151446ca9.jpeg)

ネットワークマッピングの設定は以下の通りです。（見切れてます。。。）
VPCは、とりあえず試すだけなのでデフォルトで設定します。

またAZに関しては、[可用性](https://wa3.i-3-i.info/word15460.html)を考慮するために、[AZ-a](https://e-words.jp/w/%E3%82%A2%E3%83%99%E3%82%A4%E3%83%A9%E3%83%93%E3%83%AA%E3%83%86%E3%82%A3%E3%82%BE%E3%83%BC%E3%83%B3.html)とAZ-cにしました。
`ap-northeast-1a`と`ap-northeast-1c`にチェックをすればOKです。
![スクリーンショット 2021-10-02 13.55.06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/55622cc8-7de3-40ba-1899-7c6ba14b64a6.jpeg)

セキュリティグループは、先ほど作成した`For Web Server`を選択します。
![スクリーンショット 2021-10-02 14.27.27.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/31b0b1a5-0bae-4273-bd49-1c3b72749b7f.jpeg)

リスナーとルーティングは、先ほど作成した`DemoTargetGroup`を選択します。
![スクリーンショット 2021-10-02 14.28.25.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/1e67541f-826e-9cc3-69c0-4de2f83e9de9.jpeg)

ロードバランサの設定は以上になりますので、
`ロードバランサの作成`をクリックして作成します。

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

またセキュリティグループの作成？？と思うかもしれませんが、
次は、先ほど作成したALBからEC2にアクセスするためのセキュリティグループを作成します。

面倒な方は飛ばしても大丈夫ですが、
そんなに面倒ではないですし、知っておいた方がいいことだと思います。

まず、セキュリティグループを作成する前に、
ALBのIPアドレスを調べる必要があります。

EC2の左ペインから`ネットワークインターフェース`を選択します。

検索欄にALBの名前を入力します。
私の場合は`DemoELB`です。

すると先ほど作成したALBのインターフェースがありますので、
その中の`プライベート IPv4アドレス`を確認します。

ちなみに、もう一つの方は`172.31.43.58`でした。
![スクリーンショット 2021-10-02 17.00.31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/a48dbf3f-2866-ce48-7c2b-258fe895833a.jpeg)


セキュリティグループの作成の手順は、一部割愛します。

インバウンドルールの箇所では、タイプを`HTTP`にし、
ソースは`カスタム`を選択後、右の空欄に`172.31.0.0/16`の形式で入力します。
`/16`にすることで、172.31.1~255.1~2551のアドレスがアクセスできます。

`172.31.0.0`の前半二つ（第二セグメントまで）の内容は私と異なっている可能性があります。
私自身きっちりと理解できておらず申し訳ないです・・・。

もう一つ、SSH接続するためのインバウンドルールを追加します。
`ルールを追加`をクリックし、タイプは`SSH`を選択、ソースは`マイIP`を選択。
![スクリーンショット 2021-10-02 17.07.12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/36e89646-7a5e-f37a-5d69-24199a077ff2.jpeg)


アウトバウンドルールについてもルールの追加を行います。
HTTPとHTTPSの許可を行いました。
![スクリーンショット 2021-10-02 16.19.06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/2fcd264c-53c3-22ce-b591-214b6060e401.jpeg)



##起動設定の作成
Auto Scalingでどのようなインスタンスを起動させるか設定します。

今回は、`Amazon Linux 2 インスタンス`を利用します。
EC2の左ペインからインスタンスを選択し、`インスタンスを起動`をクリックします。
![スクリーンショット 2021-10-02 14.38.12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/bc05367d-c740-f73a-6eb1-764434879c4d.jpeg)

マシンイメージが表示されていると思いますので、
`クイックスタート`の中にある、`Amazon Linux 2 AMI`を探します。

太文字の後に記載されている、**ami-02892~~~**をコピーしてください。
64ビットの前までで大丈夫です。（もしかしたら記載内容違うかもしれないです。）

コピー後に右上の`キャンセルして終了`をクリックします。
![スクリーンショット 2021-10-02 14.40.02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/b85824bc-1ab4-956a-cac4-6749a87b7af6.jpeg)

次にEC2の左ペインから起動設定を選択し、`起動設定の作成`をクリックします。
![スクリーンショット 2021-10-02 14.34.42.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/b71e0ad2-32c1-e9f5-9998-31997e515a15.jpeg)

名前は、`DemoStartupSettings`とかにしておきました。
AMIですが、先ほどコピーしたやつを貼り付けて、表示されたものを選択します。

インスタンスタイプは、無料利用枠対象の`t2.micro`を選択します。
![スクリーンショット 2021-10-02 14.45.44.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/d842fe74-2fbf-b935-6fb1-98f680e17b60.jpeg)

続いて、追加設定項目ですが、`高度な詳細`タブを開きます。
すると`ユーザデータ`という項目があるので、下記を入力します。

ユーザデータとは、初回起動時に自動実行してデプロイを自動かする機能です。

今回は、Apacheをインストール・起動して、
index.htmlにAZ、インスタンスID、IPアドレスを書き込んでいます。

```
#!/bin/bash -ex
yum -y update
yum -y install httpd
systemctl enable httpd.service
systemctl start httpd.service
AZ=`curl --silent http://169.254.169.254/latest/meta-data/placement/availability-zone`
INSTANCE_ID=`curl --silent http://169.254.169.254/latest/meta-data/instance-id`
IP_ADDRESS=`curl --silent http://169.254.169.254/latest/meta-data/public-ipv4`
echo $AZ\<br\> >> /var/www/html/index.html
echo $INSTANCE_ID\<br\> >> /var/www/html/index.html
echo $IP_ADDRESS\<br\> >> /var/www/html/index.html
```

ユーザデータ以外はデフォルト値でOKです。
入力後は以下のようなイメージです。
![スクリーンショット 2021-10-02 14.57.04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/eab9e603-03e4-5b95-b4d2-cadbbff316ae.jpeg)

ストレージは、デフォルトでOKです。

セキュリティグループは先ほど作成した、`ALB to EC2`を選択します。
![スクリーンショット 2021-10-02 15.19.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/a83705dd-792d-d835-94e4-1643874c0d82.jpeg)

EC2に接続する際に必要なキーペアですが、今回は`新しいキーペアの作成`を選択します。
キーペア名を適当に入力してから、`キーペアのダウンロード`をクリック。（必須）
![スクリーンショット 2021-10-02 15.21.10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/1c44e2ec-0f82-3734-8df5-845662b09de3.jpeg)

##Auto Scalingグループの作成
次にEC2の左ペインにある、`Auto Scalingグループ`を選択します。

名前は、適当な名前を入力します。

起動設定は、項目の右上にある、`起動設定に切り替える`という文字をクリックします。
その後先ほど作成した起動設定のものを選択して`次へ`をクリックします。
![スクリーンショット 2021-10-02 15.36.34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/4ada1be2-14a8-1408-9e4c-eb600ee0459e.jpeg)

ネットワークの設定では、サブネットに`AZ-a`と`AZ-c`を追加して`次へ`をクリックします。
![スクリーンショット 2021-10-02 15.39.13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/dc8992cf-f4a6-6d44-a804-62aa96fecc0f.jpeg)

次に詳細設定ですが、ロードバランサは作成しているので、
`既存のロードバランサにアタッチ`を選択します。

これを選択することにより、ALBのターゲットに追加されることになります。
![スクリーンショット 2021-10-02 15.41.12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/e58e0eae-863a-b5b6-db1d-1434bab67b99.jpeg)

ターゲットグループは先ほど作成したものを選択します。
その他の設定項目はデフォルトのままで`次へ`をクリックします。
![スクリーンショット 2021-10-02 15.42.31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/b59de963-247c-f18d-dece-d2142989ad47.jpeg)

グループサイズは以下のように設定しました。
最小でも2つのインスタンスを起動し、アクセス数が増えたら最大で10個まで起動します。
![スクリーンショット 2021-10-02 15.45.09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/bfbfede1-8741-dbe3-0b62-35824d626e93.jpeg)

スケーリングポリシーは以下の通りです。
全てのインスタンスの**平均CPU使用率が60%を超えた**場合にインスタンスを追加します。
![スクリーンショット 2021-10-02 15.47.18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/b70fdcd5-7686-8b73-2b77-1691168191f4.jpeg)

通知設定は特に行わないので、スキップして作成を行います。
Auto Scalingグループが作成できました。
![スクリーンショット 2021-10-02 15.49.45.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/d6fc0f02-3c7c-34da-4498-d57ad605bc5e.jpeg)

##動作確認
一通り構築が完了したので、これから動作確認を行いたいと思います。

###インスタンス確認
EC2インスタンスを確認したところ、Auto Scalingにより、
最小数である2つのインスタンスが作成されたことが分かります。
![スクリーンショット 2021-10-02 17.08.13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/cb5380ab-f777-12c5-fd58-7ecd9e552d80.jpeg)

###ヘルスチェック確認
左ペインのターゲットグループから、対象のターゲットを選択します。
インスタンスが2つ紐づいており、ヘルスステータスも`healthy`であることが確認できました。
![スクリーンショット 2021-10-02 17.09.31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/dc9ce0b9-6802-43d6-15e1-bcb7e29aa974.jpeg)

###Auto Scalingグループ確認
左ペインのAuto Scalingグループから、対象のグループを選択します。
インスタンス管理を開くと、2つのインスタンスを管理していることが確認できました。
![スクリーンショット 2021-10-02 17.11.40.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/9fe22977-b91b-04fb-b187-8bc8feebb124.jpeg)

###インスタンス接続確認
左ペインのロードバランサーから、対象のELBを選択します。
下にELBの情報が表示されますので、その中からDNS名をコピーします。
![スクリーンショット 2021-10-02 17.13.10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/3f4bb696-bc4f-00aa-e694-afdedba01317.jpeg)


ブラウザを開き、URL欄に先ほどコピーしたものを貼り付けます。

すると、`インスタンスのリージョン`と`インスタンスID`、
`パブリックIPアドレス`が記載されていることが確認できます。

何度か更新してみて、二つのインスタンスの情報が表示されていることを確認します。
確認できたら、しっかりと負荷分散できているということになります。
![スクリーンショット 2021-10-02 17.14.45.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/746e9cf6-ecfa-169d-fbe0-dd86906d00a3.jpeg)

次に、インスタンスのIPアドレスのみで検索した場合に、
表示されずにエラーが返ってくることを確認しましょう。

EC2へは、**自分のPCからのSSH接続**か、**ELB経由のHTTP接続**しか許可されていません。
なので、ELBを経由しないダイレクトなアクセスは拒否されます。
![スクリーンショット 2021-10-02 17.19.10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/4c01fbc6-ac40-88f8-0c6e-5e2979e9f51f.jpeg)

###スケールアウトの確認

問題なく構築できていることが確認できたので、
次にCPU使用率を60%以上にした場合の動きを見ていきます。

まずは、インスタンスに負荷をかけるために、
インスタンスに対してSSH接続を行います。

起動設定でダウンロードしたキーペアの出番です。
私の場合はMacで操作しているので、Windowsの方は少し操作が異なると思います。

まず、ターミナルを開いて以下のコマンドを実行します。
`/******/`は、キーペアが格納されている場所によって異なります。

ファイルをターミナルにドラッグ＆ドロップすれば自動で入力されるのでオススメです。

`-rw-r--r--`が、`-r--------`に変わればOKです。

```
$ ls -al /******/DemoEC2key.pem
-rw-r--r--@ 1 ryosuke  staff  1674 10  2 15:21 /******/DemoEC2key.pem
$ chmod 400 /******/DemoEC2key.pem
$ ls -al /******/DemoEC2key.pem
-r--------@ 1 ryosuke  staff  1674 10  2 15:21 /******/DemoEC2key.pem  
```

次にターミナルからSSH接続を行います。（windowsはTeraTermなどを利用します。）

1行目は各自のインスタンスのIPアドレスにしてください。
また、途中で`yes/no/[fingeprint]`と聞かれますので、yesと入力しEnterを押します。

`[ec2-user@ip-**-**-**-** ~]$ `と表示されればOKです。

```
$ ssh -i /*******/DemoEC2key.pem ec2-user@<パブリックIPアドレス>
The authenticity of host '54.64.219.57 (54.64.219.57)' can't be established.
ECDSA key fingerprint is SHA256:iISNxlgrJI8+2dVkZYWTGmJ+clGEHIplU8w0W9RXkdk.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '54.64.219.57' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-172-31-12-149 ~]$ 
```

これでインスタンスにログインすることができました。
次に負荷をかけてCPU使用率を上げようと思います。

ログインした状態で以下のコマンドを実行します。
実行後に応答が返ってきませんが、それが正常ですのでご安心を。
また、複数ターミナルを開いて実行すると早く使用率が上がります。

```
$ yes > /dev/null
```

実行後にAuto Scalingグループを確認します。

EC2の左ペインから、Auto Scalingグループを選択し、対象のグループを選択します。
その後、モニタリングタブを開きEC2を選択します。

すると、CPU使用率の点グラフ？があります。
複数ターミナルを開いてやったので、使用率がほぼ100％になってます。

テストだからいいもののリアルだったら恐怖ものですね・・・。
![スクリーンショット 2021-10-02 17.45.47.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/d8344abe-a0b6-0f83-17dd-7f7a8d3832eb.jpeg)

しばらく時間をおいてから、インスタンスの数が増えているか確認した結果、
2つだったインスタンスが4つに増えていました。

CPU使用率が増えた（アクセス量が多くなった）時に、
インスタンスの数が増えるような流れが、これで確認できました。
![スクリーンショット 2021-10-02 17.50.21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/ec2908e7-b71f-a944-bba3-f7eec50b3deb.jpeg)

###スケールインの確認
次にCPU使用率が減った時にインスタンスの数が減るのかを確認していきます。
先ほどの`yes > /dev/null`コマンドを、`control + c`で中止します。

少し時間を置いてから確認したところCPU使用率が下がっておりました。
![スクリーンショット 2021-10-02 18.18.33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/898efc1f-a5f9-382e-98db-02a9b5d000a3.jpeg)

CPU使用率が下がっているということは、インスタンスが減っていることが期待値です。
EC2インスタンスの個数を確認したところ、最小個数の2つになっていました。
![スクリーンショット 2021-10-02 18.18.13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/873371b4-720d-86c2-4c4c-414718e9ba0d.jpeg)

以上で一通りの動作確認も完了しました！

#さいごに

かなり長くなってしまいました・・・。
作成したインスタンスやセキュリティグループ、ELBなどは削除して大丈夫です。

というよりも、削除しないと無駄に料金がかかる可能性があります！

以上、最後までご覧いただきありがとうございました！