AWS Network Load Balancerの内部LBはクライアントとターゲットが同一IPアドレスのトラフィックを扱うことができない
ども、大瀧です。
内部NLB(Network Load Balancer)でFluentd Aggregatorの負荷分散構成を組んでいたところ、タイトルの制約に気がついたので共有します。
どういう制約?
図で示すと以下になります。
NLBのターゲットグループがインスタンス単位で登録するタイプの場合、NLBはトラフィックの送信元IPアドレスをクライアントIPアドレスのままターゲットに転送します。そうするとターゲットからの戻りのトラフィックの宛先IPアドレスがターゲット自身に向き、行きと戻りで経路がちぐはぐになってしまうわけです。
こんな構成にすることあるの?と思われるかもしれませんが、ECSタスク(Dockerコンテナ)のログをNLB経由でFluentd Aggregatorに送るというケースだと十分ありえるわけです。
で、本ケースについてはドキュメントに記載があり、さらに回避方法も案内されています。
- ターゲットからそのロードバランサーへのリクエストが接続タイムアウトになる
- インスタンス ID でターゲットが登録されている内部ロードバランサーがあるかどうかを確認します。内部ロードバランサーはヘアピニングまたはループバックをサポートしていません。インスタンス ID でターゲットを登録すると、クライアントの送信元 IP アドレスが維持されます。インスタンスが、インスタンス ID で登録されている内部ロードバランサーのクライアントである場合、リクエストが別のインスタンスにルーティングされる場合のみ接続が成功します。それ以外の場合は、送信元と送信先の IP アドレスが同じであるため、接続がタイムアウトします。 インスタンスが、それが登録されているロードバランサーにリクエストを送信する必要がある場合は、次のいずれかを実行します。
- インスタンス ID ではなく IP アドレスでインスタンスを登録するAmazon Elastic Container Service を使用している場合は、タスクで awsvpc ネットワークモードを使用して、ターゲットグループが IP アドレスで登録されるようにします。
- 通信する必要があるコンテナが異なるコンテナインスタンスにあることを確認します。
- インターネット向けロードバランサーを使用します。
ECSのawsvpcネットワークモードはENI数の上限など別の制約もあると思うので、ECSで内部向トラフィックを扱うのであればクライアントとターゲットを別のECSクラスタで構成する、サービスディスカバリでNLBを構成から取り除く、などが素直な対応かなと思いました。
まとめ
内部NLBのちょっとした制約、同一IPアドレスが扱えない話をご紹介しました。CLBおよびALBにはこのような制約はないので、これらからNLBへの移行時に気を付けていただければ。