AWS勉強会(2) / ELB + プライベートサブネットのwebサーバ

社内の初心者向けAWS勉強会で実施している最初のテーマ「LAMP環境を構築しよう」のほぼ前段にあたるネットワークとアクセス中継用の踏み台サーバの構築が済んで、じゃあwebサーバを立てよう、という手順について。

「これが正解」というものでなく、「私はこうやって構築した」という手順です。

前のページ: [AWS勉強会(1) / 踏み台サーバとネットワークの作成](https://qiita.com/zaki-lknr/items/4586cc2f992908068bd2)

# プライベートサブネット内のEC2にwebサーバを立ててELBでロードバランスさせる

## EC2にwebサーバを作る

まず大前提として、プライベートサブネット内のEC2はインターネットにアクセスできない。
つまり、yumやaptといったパッケージ管理ソフトが使えないので各種アプリケーションをインストールもできない。

### yumを使えるようにするには

- NATインスタンスを使う(有料？)
- NATゲートウェイを使う(有料？)
- 自力でルーティングする(iptablesとか使えばなんとかなる？)
- VPC内にproxyサーバを立てる
- VPC内にミラーサーバを立てる(時間とストレージを食うので微妙)
- VPCのエンドポイント経由でリポジトリ(S3)へアクセス

いろいろあると思うけど

[【小ネタ】えっ、Private SubnetからNATサーバを経由せずにyum updateができるって！？ ｜ Developers.IO](https://dev.classmethod.jp/cloud/aws/yum-update-in-private-subnet/)
[【新機能】S3がVPCのプライベートサブネットからアクセス可能になりました！ ｜ Developers.IO](https://dev.classmethod.jp/cloud/vpc-endpoint-for-s3/)

今回はAmazon Linuxを使っているのでS3を使ってみましょう

追記: 確かにubuntuのEC2の`/etc/apt/sources.list`やRHELのEC2の`/etc/yum.repos.d`のファイルはS3を見ていないので、Amazon Linux専用設定の模様。

### VPCエンドポイントの作成(Amazon Linuxの場合限定)

|項目|値|
|---|---|
|サービスカテゴリ|AWSサービス|
|サービス名|com.amazonaws.ap-northeast-1.s3|
|VPC|対象のVPC|
|ルートテーブルの設定|S3へルーティングしたいプライベートサブネットを選択|

サービス名の選択

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/5956fa9a-cc3d-a560-3ab4-814404c8c46c.png)


ルートテーブルの設定で、プライベートサブネットを全て追加する。
(つまりプライベートサブネットのデフォルトゲートウェイがここで作成したエンドポイント行きになる)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/50d13f70-8134-7aaa-0bbb-f0b0eb26e250.png)


ポリシーはまだカスタムしていないためデフォルト(フルアクセス)で。

### プライベートサブネットのEC2で動作確認

```
[ec2-user@ip-172-26-30-108 ~]$ sudo su -
Last login: Sat Aug 18 05:36:17 UTC 2018 on pts/1
[root@ip-172-26-30-108 ~]# yum update
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main                                                | 2.1 kB     00:00     amzn-updates                                             | 2.5 kB     00:00     (1/5): amzn-main/latest/group_gz                           | 4.4 kB   00:00     (2/5): amzn-updates/latest/group_gz                        | 4.4 kB   00:00     amzn-main/latest/primary_db    FAILED                                          
http://packages.ap-northeast-2.amazonaws.com/2018.03/main/c31535f74c6e/x86_64/repodata/primary.sqlite.bz2?instance_id=i-07b106202d030ffaf&region=ap-northeast-1: [Errno 12] Timeout on http://packages.ap-northeast-2.amazonaws.com/2018.03/main/c31535f74c6e/x86_64/repodata/primary.sqlite.bz2?instance_id=i-07b106202d030ffaf&region=ap-northeast-1: (28, 'Connection timed out after 5001 milliseconds')
Trying other mirror.
amzn-updates/latest/updateinfo FAILED                                          
http://packages.ap-northeast-2.amazonaws.com/2018.03/updates/db85d4430b02/x86_64/repodata/updateinfo.xml.gz?instance_id=i-07b106202d030ffaf&region=ap-northeast-1: [Errno 12] Timeout on http://packages.ap-northeast-2.amazonaws.com/2018.03/updates/db85d4430b02/x86_64/repodata/updateinfo.xml.gz?instance_id=i-07b106202d030ffaf&region=ap-northeast-1: (28, 'Connection timed out after 5001 milliseconds')Trying other mirror.
amzn-updates/latest/primary_db FAILED                                          
http://packages.ap-southeast-1.amazonaws.com/2018.03/updates/db85d4430b02/x86_64/repodata/primary.sqlite.bz2?instance_id=i-07b106202d030ffaf&region=ap-northeast-1: [Errno 12] Timeout on http://packages.ap-southeast-1.amazonaws.com/2018.03/updates/db85d4430b02/x86_64/repodata/primary.sqlite.bz2?instance_id=i-07b106202d030ffaf&region=ap-northeast-1: (28, 'Connection timed out after 5004 milliseconds')
Trying other mirror.
(3/5): amzn-main/latest/primary_db                         | 4.0 MB   00:00     (4/5): amzn-updates/latest/updateinfo                      | 506 kB   00:00     amzn-updates/latest/primary_db FAILED                                          
http://packages.us-west-1.amazonaws.com/2018.03/updates/db85d4430b02/x86_64/repodata/primary.sqlite.bz2?instance_id=i-07b106202d030ffaf&region=ap-northeast-1: [Errno 12] Timeout on http://packages.us-west-1.amazonaws.com/2018.03/updates/db85d4430b02/x86_64/repodata/primary.sqlite.bz2?instance_id=i-07b106202d030ffaf&region=ap-northeast-1: (28, 'Connection timed out after 5001 milliseconds')
Trying other mirror.
(5/5): amzn-updates/latest/primary_db                      | 427 kB   00:00     No packages marked for update
[root@ip-172-26-30-108 ~]# 
```

動いているといえば動いている？

### Apacheインストール

ここからはまあ普通に

```
[root@ip-172-26-30-108 ~]# yum install httpd
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main                                                | 2.1 kB     00:00     amzn-updates                                             | 2.5 kB     00:00     Resolving Dependencies
--> Running transaction check
---> Package httpd.x86_64 0:2.2.34-1.16.amzn1 will be installed
--> Processing Dependency: httpd-tools = 2.2.34-1.16.amzn1 for package: httpd-2.2.34-1.16.amzn1.x86_64
--> Processing Dependency: apr-util-ldap for package: httpd-2.2.34-1.16.amzn1.x86_64
--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.2.34-1.16.amzn1.x86_64
--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.2.34-1.16.amzn1.x86_64
--> Running transaction check
---> Package apr.x86_64 0:1.5.2-5.13.amzn1 will be installed
---> Package apr-util.x86_64 0:1.5.4-6.18.amzn1 will be installed
---> Package apr-util-ldap.x86_64 0:1.5.4-6.18.amzn1 will be installed
---> Package httpd-tools.x86_64 0:2.2.34-1.16.amzn1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================ Package             Arch         Version                 Repository       Size
================================================================================Installing:
 httpd               x86_64       2.2.34-1.16.amzn1       amzn-main       1.2 M
Installing for dependencies:
 apr                 x86_64       1.5.2-5.13.amzn1        amzn-main       118 k
 apr-util            x86_64       1.5.4-6.18.amzn1        amzn-main        99 k
 apr-util-ldap       x86_64       1.5.4-6.18.amzn1        amzn-main        19 k
 httpd-tools         x86_64       2.2.34-1.16.amzn1       amzn-main        80 k

Transaction Summary
================================================================================Install  1 Package (+4 Dependent packages)

Total download size: 1.5 M
Installed size: 3.6 M
Is this ok [y/d/N]: y
Downloading packages:
(1/5): apr-util-1.5.4-6.18.amzn1.x86_64.rpm                |  99 kB   00:00     (2/5): apr-util-ldap-1.5.4-6.18.amzn1.x86_64.rpm           |  19 kB   00:00     (3/5): apr-1.5.2-5.13.amzn1.x86_64.rpm                     | 118 kB   00:00     (4/5): httpd-tools-2.2.34-1.16.amzn1.x86_64.rpm            |  80 kB   00:00     (5/5): httpd-2.2.34-1.16.amzn1.x86_64.rpm                  | 1.2 MB   00:00     --------------------------------------------------------------------------------Total                                              5.4 MB/s | 1.5 MB  00:00     Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : apr-1.5.2-5.13.amzn1.x86_64                                  1/5   Installing : apr-util-1.5.4-6.18.amzn1.x86_64                             2/5   Installing : httpd-tools-2.2.34-1.16.amzn1.x86_64                         3/5   Installing : apr-util-ldap-1.5.4-6.18.amzn1.x86_64                        4/5   Installing : httpd-2.2.34-1.16.amzn1.x86_64                               5/5   Verifying  : httpd-tools-2.2.34-1.16.amzn1.x86_64                         1/5   Verifying  : apr-util-1.5.4-6.18.amzn1.x86_64                             2/5   Verifying  : httpd-2.2.34-1.16.amzn1.x86_64                               3/5   Verifying  : apr-1.5.2-5.13.amzn1.x86_64                                  4/5   Verifying  : apr-util-ldap-1.5.4-6.18.amzn1.x86_64                        5/5 
Installed:
  httpd.x86_64 0:2.2.34-1.16.amzn1                                              
Dependency Installed:
  apr.x86_64 0:1.5.2-5.13.amzn1                                                   apr-util.x86_64 0:1.5.4-6.18.amzn1                                              apr-util-ldap.x86_64 0:1.5.4-6.18.amzn1                                         httpd-tools.x86_64 0:2.2.34-1.16.amzn1                                        
Complete!
[root@ip-172-26-30-108 ~]# 
```

```
[root@ip-172-26-30-108 ~]# /etc/init.d/httpd status
httpd is stopped
[root@ip-172-26-30-108 ~]# /etc/init.d/httpd start
Starting httpd:                                            [  OK  ]
[root@ip-172-26-30-108 ~]# 
```

なぜsystemctlじゃないんだ←

```
[root@ip-172-26-30-108 ~]# curl --head http://localhost/
HTTP/1.1 403 Forbidden
Date: Sat, 18 Aug 2018 06:21:25 GMT
Server: Apache/2.2.34 (Amazon)
Accept-Ranges: bytes
Content-Length: 3839
Connection: close
Content-Type: text/html; charset=UTF-8

```

403？まぁ動いてはいる。(追記: `/var/www/html`に何もファイルがなく、`Indexes`が無効になっているから)

当然、この状態でこのApacheへはインターネットからはアクセスできないが。

## ロードバランサの処理対象にするため、もう片方のAZにもwebサーバを立てる。

EC2を異なるAZに作成し、同じ要領でhttpdをインストールする(手順省略)

また、200を返すコンテンツを適当に配置する(ロードバランスされることが分かりやすいように、ホストごとに異なるものを作成)

```
[root@ip-172-26-30-108 html]# echo "test (30)" > /var/www/html/index.html 
[root@ip-172-26-30-108 html]# cat /var/www/html/index.html 
test (30)
```

もう一台は

```
[root@ip-172-26-20-132 ~]# echo "test (20)" > /var/www/html/index.html 
[root@ip-172-26-20-132 ~]# cat /var/www/html/index.html 
test (20)
```


今こんな感じ。

![踏み台+ネットワーク+EC2x2.png](https://qiita-image-store.s3.amazonaws.com/0/256859/ad630347-c00f-b19c-b2a6-135f8f02e79a.png)


## ELBの作成

### プライベートサブネットのEC2へアクセスさせるためパブリックサブネットを追加

[プライベートIPアドレスを持つEC2インスタンスにインターネット向けのロードバランサを接続するにはどうすればよいですか？](https://aws.amazon.com/jp/premiumsupport/knowledge-center/public-load-balancer-private-ec2/)

このパブリックサブネットを作らずに(EC2を設定しているプライベートサブネットを選択して)ELBを作成しても、インターネットからELB経由でプライベートサブネットのEC2へは接続できない。(ここがわからずにハマったｗ)

※ 無理やり作ろうとしても、こう↓なる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/25f6e537-944b-93e2-75db-0dee0875bf77.png)


ELBを配置するパブリックサブネットをAZ毎にまず作成しておく。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/71d63035-afb0-2bc3-bea8-437726d4f7ce.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/fdab5b08-b77f-e3bd-816c-c3ef5b1fcb08.png)

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

二つのセキュリティグループを作成

- インターネット～ELB間のhttp接続
    - このセキュリティグループをELBと対象EC2全てに設定

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/d120a1bb-6522-1d6d-25ff-9f1a0fe94e4e.png)

- ~~ELB～EC2間のhttp接続~~
    - ~~※ ELB-EC2をhttpのみに制限したかったけど、うまく動作しなかった。とりあえず`default`(VPC内制限なし)も追加すれば動作したけど…~~
        - プライベートサブネットのEC2のセキュリティーグループは、ELBとだけ通信できればいいかと思ったが、`0.0.0.0/0`の80/TCP通信が必要そう(つまり↑のセキュリティグループを使う)


### ロードバランサの作成

外部接続用のロードバランサを作る。
EC2ダッシュボードの「ロードバランサー」から。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/40d780ba-b5c3-ed51-03a1-322ac834916f.png)

3種類のロードバランサを選択できる。
今回はwebサーバなのでHTTP/HTTPSを選択

![2018-08-18_15h27_38.png](https://qiita-image-store.s3.amazonaws.com/0/256859/ded271e9-a28b-73f4-e72d-b91d34703673.png)

名前を入力し、外部からの接続を処理するのでスキームは「インターネット向け」を選択。
リスナーはデフォルトでHTTPが登録されているのでそのまま。
(ついでにHTTPSを追加してもいいが、ELB作成中に証明書の登録などが必要になってくるのでとりあえずスルー)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/d7f82c6c-27b7-b7bd-cf3b-e76608349ee9.png)


AZの選択は、ELB用に作成したパブリックサブネットを選択する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/9c586ace-a87c-8fc4-5c4b-34ac78208c21.png)

「ステップ2: セキュリティ設定の構成」は、httpsを使用しないのでスキップ

「ステップ3: セキュリティグループの設定」は、インターネット用http ~~とVPC内容httpの両方~~を選択 ~~(追記: これだと`504 Gateway Time-out`になってしまった。とりあえず`default`も追加…)~~

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/68f0d1c7-445c-2414-a2ed-febf7097aa97.png)


「ステップ4: ルーティングの設定」はよくわからん。デフォルトで。名前だけ適当に入力。
ヘルスチェックは`/`へのアクセスで検知するようにデフォルトでなっているので変更しない。(要はドキュメントルートへアクセスできないようであればダウンと判定し、ロードバランスの振り先からハズすのだろう)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/4040638f-ca1d-1d8d-c36c-a1647ddfb462.png)

「ステップ5: ターゲットの登録」は、Apacheをインストールした各AZのプライベートサブネットにいるEC2インスタンスを登録する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/a3c47ea0-487d-5f97-3a4d-b69ea4e2331b.png)

登録するとこうなる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/a8d585e6-5798-16b9-3496-363e62b663ec.png)

最後に確認して「作成」

作成したらダッシュボードの一覧に表示され、アクセスに必要なDNS名がわかる(このDNS名は反映されるまでに少し時間がかかるっぽい)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/40265cdf-6506-2159-ca5d-76e88de808fc.png)

このDNS名にブラウザでhttpアクセスすればELB配下のどちらかのwebサーバへアクセスされる。
リロードすると内容が変わっていればOK

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256859/8032ae7d-1671-a221-4917-9dc9770c0376.png)

こんな感じの構成になっているはず。(ELBの書き方難しいね)

![踏み台+ネットワーク+EC2x2+elc.png](https://qiita-image-store.s3.amazonaws.com/0/256859/102e1848-66ae-6cad-40d5-c74fb71c58dd.png)