ELBを使ってEC2インスタンスをプライベートサブネットに配置してみた。

# はじめに

ELBのベストプラクティスとして、EC2のプライベートサブネットへの配置が推奨されていたので試してみました。

![ELBベストプラクティス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/432cd321-5004-f1f1-aee6-00b5a3faea42.png)
（画像引用：[【AWS Black Belt Online Seminar】Elastic Load Balancing (ELB)](https://www.youtube.com/watch?v=4laAoK-zXko)）

# やってみること

この構成図の形で作成します。

![ALBpub,EC2pri.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/e3f7eda0-87c8-3777-987d-4517e05f4a42.png)

パブリックサブネットにALBを1つ、プライベートサブネットにEC2を1つのシンプルな構成です。
ALBはシングルAZでの構成ができないため、マルチAZでの構成となります。
また、ALBからのアクセスのみ許可する設定を行ってみます（この設定を行わないと意味がないため）。

ベストプラクティスを厳密に言うと、"ELB自体をVPC内の2つのAZに配置"することが必要なのですが、練習が目的かつ作成後はすぐさま削除するのでシンプルな構成図としました。

# 何故NATゲートウェイ（インスタンス）ではなくELBを用いるのか

作成に入る前に、ALBを用いた構成の利点を押さえておきます。
以下、プライベートサブネットに配置したインスタンスとの通信を行う他の方法である、NATゲートウェイ、NATインスタンスと比較します。

|名称|内容|料金|  
|:---|:--|:--|
|NATゲートウェイ|AWSのマネージドサービス。"動的NAPT"なので、インスタンスからインターネットへの通信は可能だが、逆方向は不可能。複数AZで1つのNATゲートウェイを共有する構成は非推奨。1AZ当たりに1つのNATゲートウェイが推奨。|時間単位とGB単位での請求。東京リージョンでは、どちらも1単位当たり0.062USD（2022.1現在）。|
|NATインスタンス|ユーザーが管理する。NATインスタンス用のAMIが提供されているので、それを用いて作成する。NATゲートウェイでは不可能な踏み台やポート転送としての利用が可能。|EC2と同様の料金体系。NATゲートウェイと比べて安価で使用可能。|
|ELB|ユーザーが管理するが、スケーリングは自動で行われる。ALBとNLBで利用可能な機能が異なる。冗長化、可用性、負荷分散、スケールがELB本来の目的。上記2つの方法と組み合わせて利用することも可能。|ロードバランサー毎の時間単位とLCU時間単位の料金での請求。東京リージョンのALB場合、ALBの時間当たり0.0243USD、LCU時間当たり0.008USD（2022.1現在）。|

ELBを用いる最大の利点は**料金の安さ**だと思います。
NATゲートウェイはELBの倍以上の料金体系です。また、管理の手間もEC2インスタンスの一種であるNATインスタンスと比べて、容易に行うことができます。

他にも、こちらの記事のようにACLを活用した方法も可能なようです。
[NATゲートウェイを使わずにプライベートサブネットをインターネットにつなぐ](https://qiita.com/SSMU3/items/5ed5792e74266b54ff8b)

>料金参考
>[Amazon VPC の料金](https://aws.amazon.com/jp/vpc/pricing/)
>[Elastic Load Balancing 料金表](https://aws.amazon.com/jp/elasticloadbalancing/pricing/)


# 何故NLBではなくALBを用いるのか

今回はALBを用いての構成を行います。
ALBには、セキュリティ上の以下のような特徴があるからです。

```
・セキュリティグループの設定が可能。
・ルーティングのルール設定で、認証を挟むことが可能（AWS CognitoやOIDCなど）。
・AWS WAFに対応。
```

一方でNLBとは異なり、

```
・急激なアクセスの増加に耐えられない（暖機申請が必要）。
・固定IPを持っていない（AWS Global Acceleratorと連携すれば別）。
・IPアドレスの取得に、x-forwad-forヘッダーの使用が必要。
```

などの短所もあるため、一概にALBの方が良いというわけでもありません。

::: note info
2021年9月より、NLBのターゲットにALBが指定可能となったようです。
NLBとALBを組み合わせた構成も可能ということですね。
:::
>参考
>[Application Load Balancer が、ネットワークロードバランサーとの直接統合で、AWS PrivateLink および静的 IP アドレスを有効に](https://aws.amazon.com/jp/about-aws/whats-new/2021/09/application-load-balancer-aws-privatelink-static-ip-addresses-network-load-balancer/)

# 作成手順

ここからは実際に作成してみます。
手順は以下の通りです。

|順番|内容|  
|:---|:--|
|1.|VPC、パブリックサブネット、プライベートサブネットの作成|
|2.|EC2インスタンスの作成|
|3.|ALB用のセキュリティグループの作成|
|4.|EC2インスタンス用のセキュリティグループの編集|
|5.|ALBの作成|

EC2インスタンスへのアクセスをALBからのみに制限します。
そのため、EC2インスタンス用のセキュリティグループのインバウンドルールの編集を後から行います。

では早速やってみましょう。

# 1. VPC、パブリックサブネット、プライベートサブネットの作成


```
# 作成するもの
VPC：1つ
ALBを配置するパブリックサブネット：2つ
EC2を配置するプライベートサブネット：1つ(EC2を2つ作成する場合は、プライベートも2つ作成します）
```

**例**
VPC
名前：`VPC-Qiita-ALBtest`
Cidr:`10.0.0.0/16`

パブリックサブネット（1a）
名前：`pub1a-Qiita-ALBtest`
Cidr:`10.0.0.0/24`

パブリックサブネット（1c）
名前：`pub1c-Qiita-ALBtest`
Cidr:`10.0.1.0/24`

プライベートサブネット
名前：`pri1a-Qiita-ALBtest`
Cidr:`10.0.2.0/24`


>VPCの詳細な作成方法はこちらの記事に書いています。ご参考にされる方は。
>[[初心者向け]VPC作成からRDS接続までをそこそこ丁寧にまとめてみる。①VPC作成まで](https://qiita.com/kmmz/items/53b4fbd64ccbfcaf9ee0)

# 2. EC2インスタンスの作成

```
# 作成するもの
プライベートサブネットに配置するEC2インスタンス：1つ
# 2つ作成する場合は、ここで2つ作成します。
```

無料利用枠の範囲での最低限の機能で大丈夫です。
1.で作成した**VPC**と**プライベートサブネット**と関連づけて作成します。
基本的にデフォルト設定のままです。

`自動割り当てパブリックIP`だけは、`サブネット設定を使用（無効）`にすることを忘れないように注意します。


タグ付けもしておきましょう。
**例**
`Name`キー:`EC2-1a-Qiita-ALBtest`

最後にセキュリティグループの設定がありますが、こちらはALBのセキュリティグループと一緒に後で設定します。現段階では特に設定を変えなくても大丈夫です。
セキュリティグループ名と説明だけ入力しておきます。

**例**
セキュリティグループ名：`EC2-sg-Qiita-ALBtest`
説明：`セキュリティグループ名と同様。`

キーペアに関しては、EC2インスタンスへ直接SSH接続は行わないため、使用しなくても大丈夫です。

入力を終えたら「インスタンスを作成」をクリックします。

2台作成する場合は、プライベートサブネット以外は同様の構成で、続けてもう一台作成します。

>EC2の詳細な作成方法はこちらの記事に書いています。ご参考にされる方は。
>[[初心者向け]VPC作成からRDS接続までをそこそこ丁寧にまとめてみる。②EC2作成～SSH接続まで](https://qiita.com/kmmz/items/2920659fbe7ad2b0ef5f)

# 3. ALB用のセキュリティグループの作成 

ALB用のセキュリティグループを作成します。
EC2のコンソールから「セキュリティグループ」を選択し、「セキュリティグループを作成」をクリックします。

![ALB_SG入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/3baa95c2-1ebc-620b-c98f-4b84c4b17df9.png)

必要な項目を入力します。

**例**
セキュリティグループ名：`ALB-sg-Qiita-ALBtest`
説明：`セキュリティグループ名と同様。`

VPCは先程作成したものを選択します。

次にインバウンドルールの設定を行います。

![インバウンドルールの編集.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/543ebeca-cb74-dcd0-0aec-ea8c176c4f9b.png)

(後から取ったスクショなので、左端にセキュリティグループルールIDが既にくっついていますが、気にしないでください。。。)

HTTP（80）とHTTPS（443）の許可を、IPv4とIPv6のそれぞれで設定します。
ALBへのアクセス自体は、全て許可する形にします。

|タイプ|ソース|説明（任意）|  
|:---|:--|:--|
|HTTP|0.0.0.0/0|for http IPv4|
|HTTPS|0.0.0.0/0|for https IPv4|
|HTTP|::/0|for http IPv6|
|HTTPS|::/0|for https IPv6|

セキュリティグループはステートフルなので、アウトバウンドルールはデフォルトのままにします。

最後にタグ付けをします。
**例**
`Name`キー：`ALB-sg-Qiita-ALBtest`

ここまで入力を終えたら、「セキュリティグループを作成」をクリックします。

# 4. EC2インスタンス用のセキュリティグループの編集

EC2インスタンスへのアクセスをALBからのみに制限したいので、EC2インスタンスと同時に作成したセキュリティグループの、インバウンドルールの編集を行います。

その前に、識別のためにタグ付けを行います。
作成したEC2インスタンスのセキュリティグループを選択後、`アクション`もしくは`タグ`から`タグを管理`をクリックします。

**例**
`Name`キー：`EC2-sg-Qiita-ALBtest（セキュリティグループ名と同様）`

タグ付けも完了したので、インバウンドルールの編集を行います。
作成したEC2インスタンスのセキュリティグループの`アクション`もしくは`インバウンドルール`から`インバウンドのルールを編集`をクリックします。

![EC2-SG-ALB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/228d4a32-2c45-0ba1-1b6b-9b1731f5acef.png)

|タイプ|ソース|説明（任意）|  
|:---|:--|:--|
|HTTP|作成したALB用のセキュリティグループ|for http alb|
|HTTPS|作成したALB用のセキュリティグループ|for https alb|

また、`SSH`の項目は`削除`をクリックして、削除しておきます。

入力を終えたら、「ルールを保存」をクリックします。

これで、EC2インスタンスへのアクセスがALBからのみに制限されました。

# 5. ALBの作成

これで準備が整ったので、ALBを作成します。

EC2のコンソールから「ロードバランサー」を選択し、「ロードバランサーを作成」をクリックします。
 
![ALB選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/402071fa-ecb6-694f-05f1-c7c8bda691b9.png)

ALBの「Create」をクリックします。

![ALB1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/ae45d32d-91d3-5d37-5063-40138d256e00.png)

ロードバランサー名を入力します。
**例**
名前：`ALB-Qiita-ALBtest`

![ALB2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/c9363def-f6da-6f8e-bb94-0b0f08a922dd.png)

次に、作成したVPCと2つのパブリックサブネットを選択します。
プライベートサブネットと選択を間違えないようにしましょう。

![ALB3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/4e43cacf-5b5e-919f-0814-038774bffa4d.png)

作成したALB用のセキュリティグループを選択します。EC2用と間違えないようにします。

次に、「ターゲットグループ」を選択します。
こちらはまだ作成していないので、`Create target group`をクリックして新たに作成します。

![ALB4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/c24a4cd3-225c-4da7-08de-c3d0e43a35a0.png)

ターゲットを選択します。
EC2インスタンスが対象なので、「Instances」のままです。

![ALB5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/b5bd4c8c-f4d9-1593-48de-2cd15f9c8743.png)

ターゲットグループ名を入力します。
**例**
ターゲットグループ名：`ALB-tg-Qiita-ALBtest`

次に、作成したVPCを選択します。
他の項目はデフォルトのままで大丈夫です。

![ALB6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/f6b498d1-9834-f10d-c944-a5a072559aef.png)

タグ付けも行います。
**例**
`Name`キー：`ALB-tg-Qiita-ALBtest（ターゲットグループ名と同様）`

タグ付けを終えたら、「Next」 をクリックします。

![ALB7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/c93244b5-46a7-99d5-9ac8-afce26b92942.png)

ターゲットの指定をします。
作成したEC2を選択しましょう。2台作成した場合は、もう1台の方も指定します。

![ALB8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/df1b4380-29fa-a931-e834-9a1a4622d3e0.png)

「Create target group」をクリックします。
これでターゲットグループの作成が完了しました。
ALBの作成に戻ります。

![ALB9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/c73ecd7b-9df1-5d71-005a-9fab7781e193.png)

リロードをして、先程作成したターゲットグループを選択します。

![ALB10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/3eac66c5-80e3-676c-3787-8caeefcfba25.png)

最後に、タグ付けを行います。
**例**
`Name`キー：`ALB-Qiita-ALBtest（ALB名と同様）`

![ALB11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/fd13baab-2c66-1e07-20c6-70b0a6e82f76.png)

「Create load balancer」をクリックします。

![ALB12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/ee941b2b-7e54-a3f6-78e1-617d912f4454.png)

これでALBの作成が完了しました。
本記事の構成もこれで完了です。

ここまでお疲れさまでした。

# おわりに

ELBを活用して、ロードバランシング、セキュア、安価という、一挙両得どころか一挙三得な構築を行いました。
ですが、あくまで手段の1つに過ぎないので、必要な要件を見極めて活用していきたいところです。

この記事が少しでもお役に立てば幸いです。

>参考
>[EC2 インスタンスでウェブサイトをホストしています。ユーザーに HTTP (80) または HTTPS (443) での接続を許可するにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/connect-http-https-ec2/)
>[NAT ゲートウェイ冗長性に関する通知を受けたけど、どうしたら良いでしょうか？](https://dev.classmethod.jp/articles/tsnote-nat-gateway-notification-redundancy/)
>[NAT ゲートウェイと NAT インスタンスの比較](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-nat-comparison.html)
>[【図解/AWS】インターネットGWとNAT-GWの違い〜各メリット、パブリックサブネットとは〜](https://milestone-of-se.nesuke.com/sv-advanced/aws/internet-nat-gateway/)
>[AWSでNATインスタンスを構築してみよう！](https://qiita.com/tu-kun/items/b3e82cc6e3cbf812a233#nat%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E4%BD%9C%E6%88%90)
>[EC2へのアクセスをALBからのみに制限する方法](https://tomokazu-kozuma.com/how-to-restrict-access-to-ec-2-only-from-alb/)
>[Application Load Balancerで設定する4種類のポート番号の意味を理解しよう](https://dev.classmethod.jp/articles/aws-alb-port/)



















`