はじめに
ALB(Application Load Balancer)を使って、EC2 上の Web サーバー(web01 / web02)にアクセスする構成を作っていました。
その中で、ターゲットグループのヘルスチェックは通っているのに、ALB の DNS 名にブラウザや curl でアクセスするとタイムアウトしました。
かなり時間を使ってハマったので、原因と解決策をまとめます。
前提
構成は以下のようなシンプルなものです。
- VPC
- パブリックサブネット ×2(異なる AZ)
- EC2(web01 / web02)
- ALB(Internet-facing)
- ターゲットグループ(ポート 3000)
EC2 では Python の簡易 HTTP サーバーを起動していました。
python3 -m http.server 3000 --bind 0.0.0.0
問題
ターゲットグループのヘルスチェックは正常。
しかし、ALB の DNS 名にアクセスすると以下のようにタイムアウトします。
curl http://sample-elb-xxxx.ap-southeast-2.elb.amazonaws.com
Connection timed out
ブラウザでも同様にアクセス不可。
一方で、踏み台サーバー経由で EC2 のローカルにアクセスすると正常に応答が返ってきます。
curl http://127.0.0.1:3000
解決方法
原因は ALB が配置されているサブネットのルートテーブル設定でした。
ALB が Internet-facing の場合、ALB が属するすべてのサブネットが以下を満たしている必要があります。
- 0.0.0.0/0 → Internet Gateway のルートがある
- 本当に public subnet になっていること
今回の構成では、
- sample-subnet-public01
- sample-subnet-public02
のうち、片方のサブネットが public 用ルートテーブルに関連付けられていませんでした。
確認・修正手順
- VPC → ルートテーブル を開く
- 0.0.0.0/0 → igw-xxxx を持つルートテーブルを確認
- 「サブネットの関連付け」タブを開く
- ALB が使っている すべてのサブネット が関連付けられているか確認
- 足りないサブネットを追加で関連付け
これを行った後、ALB へのアクセスが成功しました。
動作確認
ローカルから ALB に curl でアクセス。
curl -v http://sample-elb-xxxx.ap-southeast-2.elb.amazonaws.com/
HTTP/1.1 200 OK
hello from web02
何度か叩くと web01 / web02 が切り替わり、
ALB の負荷分散も確認できました。
学び
- ヘルスチェックが通っていても、ALB に外部からアクセスできるとは限らない
- ALB のサブネット = 本当に public かを必ず確認する
- どのリソースがどのサブネットに属しているかを意識するのが重要
おわりに
ヘルスチェックが通っていたのは、ALB から EC2 への通信自体は VPC 内で完結しており、インターネットへの経路を必要としなかったためです。
参考