NLB(Network Load Balancer)から自分自身にアクセスする場合、気をつけたほうがいいという話です。NLB というのは、みんな大好きAWSのL4ロードバランサー。私はあれこれ調べているうちに、気づけば 2 時間近くを溶かしてしまいました。同じようにハマる人もいると思うので、記録として残しておきます。
現象:EC2 ローカルからNLB経由でアクセスできない
アプリが動いている その EC2 から、NLB 経由でアクセスすると反応がない。
curl -v http://internal-xxxxxxx.elb.ap-northeast-1.amazonaws.com:4000
構成ですが、次のようになんでもない構成です。
[NLB: TCP 80]
↓ forward
[Target Group: TCP → EC2 Instance:4000]
↓
[EC2: app listens on port 4000]
EC2 上でアプリを 4000/tcp で listen。この EC2 をターゲットグループに登録し、NLB は 80/tcp を Listen。リスナーは上記ターゲットグループへルーティング。
もちろん、以下のチェックはすでに済みです。
- curl localhost:4000 は OK(アプリ自体は動いてる)
- セキュリティグループ OK(4000/tcp、NLB の subnet CIDR 許可)
- NLB のターゲットも healthy
にもかかわらず、反応なし。
でも、別の EC2から NLB にcurlしてみると、問題なくレスポンスが返る。
原因:NLBのNATループバック(Hairpin NAT)の制限
これはNLBの制限によるものです。
こちらの公式ページに説明ありますが、NLBはNATループバック(Hairpin NAT)をサポートしていません。この制限により、送信元と送信先が同一のとき、つまりループバックアクセスのような経路になったとき、正常な通信が行えないのです。
以下の記事に、非常に分かりやすい図解と解説があります。
書かれたのは2018年。……2025年の自分がしっかりハマっていると思うと、なかなか切ないものがあります。
おわりに
以上、NLB 経由で自分自身にアクセスするとハマるという話でした。
NLB使う場合は、本番/検証問わずNLBを経由した自己アクセスには気をつけてください。NLBを使うならば、EC2 内部では直接localhostでアクセスして、本番想定での動作確認は、API Gateway経由で実施するなど、実際に使う構成でEnd-to-Endの通信を確認のがよいでしょう。なお、ALBではこのような制約はありません。
賢いみなさんは、私のようにハマらないことを祈ります。