📝

パブリックなALBからプライベートなEC2にアクセスしてみた

2021/11/09に公開
2

「なんだかEC2をプライベートに置きたいなあ」
なんてことないですか?
僕はよくあります。
今回はALBを使用してプライベートなEC2にアクセスしてみたいと思います。

構成図

  • パブリックサブネットにALBを設置
  • プライベートサブネットにEC2を設置
  • EC2にはALBからのアクセスを許可
  • せっかくなのでマルチAZにしてみる

前提

  • VPCは10.0.0.0/16で作成済み
  • パブリックサブネットは10.0.1.0/2410.0.2.0/24で作成済み
  • プライベートサブネットは10.0.10.0/2410.0.11.0/24で作成済み
  • 「AmazonSSMManagedInstanceCore」ポリシーをアタッチしたEC2用IAMロール作成済み
    作成方法はこちらをご覧ください。

1. EC2インスタンスを構築する

まずはEC2インスタンスを2つのプライベートサブネットに1つずつ構築していきます。
マネジメントコンソールからEC2コンソールに移動します。

EC2ダッシュボードからインスタンスを起動します。

今回はAmazon Linux 2 AMI (HVM)を選択します。

インスタンスタイプはt2.microにしておきます。

詳細設定は以下の通りです。
・ネットワーク:作成済みのVPC
・サブネット:作成済みのプライベートサブネットのどちらか
・キャパシティーの予約:余計な課金を抑えるためになし
・IAMロール:作成済みのIAMロール

今回はユーザーデータでApacheをインストールします。

#!/bin/bash
sudo su
yum update -y
yum -y install httpd
chkconfig httpd on
service httpd start

ストレージはデフォルトのまま次に進みます。

タグは任意で付けてください。
今回はNameキーにWeb-1とつけました。

セキュリティグループは既存のものでもよいですが、今回は新しく作成します。
設定はあとで変えるのでこの時点ではデフォルトでOKです。

設定を確認して「起動」をクリックします。

キーペアはなしで起動します。

これで片方のプライベートサブネットに1台のEC2インスタンスが起動しました。

同様の手順で、もう片方のプライベートサブネットにも起動しましょう。
・AMI、インスタンスタイプは同じ
・サブネットはもう片方のプライベートサブネットを選択
・IAMロールやユーザーデータは同じ
・ストレージはデフォルト
・タグはわかりやすいように別の名前をつける
・セキュリティグループは1つ目で作成したグループ
・キーペアは不要

これで2つのAZ(1aと1c)に1つずつEC2インスタンスを起動しました。

2. セキュリティグループの設定

ALBを作成する前に、セキュリティグループの設定を行います。
EC2コンソールから行いましょう。

とりあえずわかりやすいように、1で作成したセキュリティグループのNameタグを編集します。

次にALB用のセキュリティグループを作成します。

任意の名前と説明を入力し、作成済みのVPCを選択します。

インバウンドのHTTPを全許可に設定し、アウトバウンドはデフォルトのままにしておきます。
わかりやすいように、タグもつけておきます。

続いてEC2用のセキュリティグループのインバウンドルールを編集します。

既存のルールは削除します。

「ルールを追加」をクリックします。

HTTPで先ほど作成したALBのセキュリティグループからの通信を許可します。

これで、ALBはどこからでもアクセス可能、EC2はALBからのみアクセス可能となるセキュリティグループの設定ができました。

3. ALBを作成する

次はALBを作成します。
EC2コンソールのサイドバーから「ロードバランサー」をクリックしましょう。

「ロードバランサーの作成」をクリックします。

Application Load Balancerの「Create」をクリックします。

任意の名前を入力します。

VPCは作成済みのVPCを選択します。
サブネットはEC2を配置したAZと同じAZのパブリックサブネットを選択します。
今回は1aと1cにEC2を構築したので、こちらでも1aと1cを選択しています。
ただし、こちらで使用するサブネットはEC2とは異なり、パブリックサブネットである点に注意してください。

セキュリティグループは作成済みのALB用のグループを選択します。

ターゲットグループは新規に作成しましょう。

target typeはInstancesのままにしておき、任意の名前を入力します。

プロトコルはHTTPのままにしておき、VPCが作成済みのものになっているかを確認します。

その他はデフォルトのまま次に進みます。

起動済みの2台のインスタンスをターゲットに登録します。

ターゲットグループを作成します。

ターゲットグループを作成したらALBの作成画面に戻り、ターゲットグループのリロードボタンを押して、グループを選択しましょう。

設定を確認して、ロードバランサーを作成します。

状態が「プロビジョニング」から「Active」になれば作成完了です。

ALBのDNS名でアクセスし、Apacheのデフォルトページが表示されればOKです。

4. (おまけ)プライベートなEC2の中身を編集する

現状だと、ターゲットグループのヘルスチェックが失敗しています。

これは、Apacheはインストールしたけど、/var/www/html/にindex.htmlなどのファイルがないためです。
せっかくなので、プライベートなEC2にアクセスして、index.htmlを作成してみます。
プライベートなEC2にアクセスする方法については、
プライベートなEC2にSSMセッションマネージャーで接続してみた
をご覧ください。

必要なエンドポイントを3つ作りました。
・VPCはEC2を構築した時のVPC
・サブネットはEC2を構築したプライベートサブネット2つを選択
・セキュリティグループはエンドポイント用のグループを作成し、HTTPSを10.0.0.0/16で許可

EC2インスタンスを選択して「接続」をクリックします。

「セッションマネージャー」タブから接続します。

/var/www/html/にindex.htmlを適当に作ります。

同様にもう1つのインスタンスにも接続し、「Web-2」と記述したindex.htmlを作成します。

index.html作成後、しばらくするとターゲットグループでインスタンスが「healthy」になります。

これでヘルスチェックも正常になったので、再度ALBのDNS名でアクセスしてみましょう。
ページをリロードすると、ALBによる負荷分散で各インスタンスのindex.htmlが表示されると思います。

これでやりたいことはすべてできました!

まとめ

今回はパブリックなALBからプライベートなEC2にアクセスしてみました。
「なんだかEC2をプライベートに置きたいなあ」
という希望をかなえることができました。
この構成にCloudFrontを合わせて、CloudFront経由のアクセスのみ許可し、EC2、ALBの直接アクセスは禁止するということもできるので、別の機会に紹介したいと思います。
今回の内容がどなたかの参考になれば幸いです。

課金に関する注意

今回構築したリソースのうち、以下のリソースは放っておいても時間で課金されるので、不要になったらすぐに削除することをお勧めします。

  • EC2インスタンス×2
  • ALB
  • VPCエンドポイント×3

その他、VPC、サブネット、セキュリティグループ、IAMロールは課金対象ではありませんが、不要であれば削除して下さい。

追記

プライベートな EC2 からインターネットにアクセスしたい場合には NAT ゲートウェイが必要になりますのでご注意ください。
今回の内容はインターネットから EC2 にアクセスする「インバウンド」において、EC2 をプライベートに置く一例です。

Discussion

kinescokinesco

知りたいところを分かり易くまとめていただき、ありがとうございます。
private AZにEC2を置く場合に、EC2がApacheやWordpressなど以外のserviceでは、デフォルトはpingを使うと思うのですが、load balancer側とEC2側のinbound/outboundの設定(他も理由があるかもしれませんが)でトラブっています。アドバイスがあればお願いします。

mn87mn87

ご覧頂きありがとうございます。

load balancer側とEC2側のinbound/outboundの設定(他も理由があるかもしれませんが)でトラブっています。

load balancer - EC2 間で ICMP プロトコルは許可されておりますでしょうか。

セキュリティグループで TCP ですべてのポートを解放していますが ping が通らないのは何故か教えてください | DevelopersIO

ping は ICMP プロトコルを使用しています。
そのため、ICMP プロトコルの通信許可をインバウンドルールに追加してください。

状況を正確に把握できておりませんが、load balancer - EC2 間の接続ができない状況であるとお見受けしております。
また「pingを使う」というご連絡もありましたので、load balancer - EC2 間で ping 通信を実現されたい状況であると推測しております。

上記ブログに記載されております通り、ping 通信を実現するためにはセキュリティグループにおいて ICMP プロトコルを許可する必要がございます。
そのため、以下の点をご確認頂けますでしょうか。

  • EC2 側のセキュリティグループのインバウンドルールで load balancer 側のセキュリティグループからの ICMP プロトコルでの接続が許可されているか
  • load balancer 側のセキュリティグループのアウトバウンドルールで ICMP プロトコルでの接続が許可されているか
  • ネットワーク ACL で ICMP 接続に制限をかけていないか

なお、切り分け手順としては以下のような方法も有効でございます。

  • EC2, load balancer 双方のセキュリティグループですべての通信を許可する
    • 通信可能: セキュリティグループの問題
      • 徐々にプロトコルを制限し、どのプロトコルを制限すると通信不可能になるかを確認する
    • 通信不可能: セキュリティグループ以外の問題
      • ネットワーク ACL, EC2 インスタンス内のプロキシ設定など

その他、一般的なトラブルシューティングもご参照頂ければ幸いでございます。

上記内容で事象が解決できれば幸いでございます。