初めての設計では誰もが同じ図を描きます。VPC に VPN を終端し、NAT gateway からインターネットへ出る、という形です。しかし VPN が virtual private gateway で終端する場合、AWS はこの経路をサポートしません。しかも失敗は静かなので、チームは何度も作り直します。動作する設計には transit gateway が必要で、これにより両側の gateway とルートテーブルが変わります。描く前に二つの形を比較してください。

明白に見えてサポートされないトポロジー

AWS の NAT gateway のドキュメント は、単一 VPC の設計しか作ったことのない人を驚かせる一線を引いています。Site-to-Site VPN 接続からのトラフィックは、virtual private gateway を経由して NAT gateway にルーティングできません。VPN を終端する gateway の種類が、変換経路が存在するかどうか自体を決めます。この誤りが残るのは、トンネル状態が UP で、同じ subnet の EC2 インスタンスが問題なくインターネットに到達するからです。どちらの観察も壊れた方向を検証していません。

実際には、パケットはオンプレミス側の送信元アドレスで到着し、変換してくれるサポート対象のネクストホップが見つかりません。テーブルによっては egress 境界で破棄され、トンネルは UP のまま同じ subnet のインスタンスはインターネットに出られるため、障害はオンプレミスの firewall 問題として報告されます。

virtual private gateway と transit gateway

virtual private gateway は一つの VPC に属します。VPN を終端し、その VPC のルートテーブルにルートを入れ、そこで止まります。attachment モデルがないため、別の VPC や共有 egress セグメントにトラフィックを渡せません。この単一 VPC の範囲が制約のすべてで、VPC 内に追加したルートでは変わりません。

transit gateway はリージョンのハブで、VPN、各 spoke VPC、共有サービスの VPC がすべて attachment として現れます。独自のルートテーブルを持ち、どの attachment がある prefix を受け取るかを決めます。

このハブが集中 egress を可能にします。VPN が一つの attachment として着地し、egress VPC がもう一つとして着地し、transit gateway のルートテーブルがインターネット向けの prefix を前者から後者へ送ります。virtual private gateway では送る先の二つ目の attachment がないため、後から設計を継ぎ足すことはできません。

サポートされる egress 経路を順にたどる

リファレンス設計は五つのホップで構成され、矢印の一つひとつが設定すべきルーティング判断です。トラフィックはオンプレミスネットワークから Site-to-Site VPN attachment へ出て、transit gateway のルートテーブルが egress VPC attachment へ転送し、そこで subnet テーブルがパブリック NAT gateway へ送ります。NAT gateway が送信元を変換し、internet gateway がパケットを外へ運びます。

On-premises network
  -> Site-to-Site VPN attachment on the transit gateway
  -> transit gateway route table
  -> egress VPC attachment
  -> public NAT gateway in that VPC
  -> internet gateway

最後のホップが機能するかは二つの点で決まります。NAT gateway はパブリックでなければならず、elastic IP と internet gateway へのルートが必要です。プライベート NAT gateway はネットワーク間の変換を行うもので、インターネットの出口にはならないからです。

サービス対象とする Availability Zone ごとに NAT gateway を一つ計画し、各 subnet テーブルはローカルのものを指すようにします。transit gateway のテーブルと VPC のテーブルはメモ上で別のオブジェクトとして扱ってください。一方は attachment を選び、他方は VPC 内のリソースを選ぶからです。片方にしかデフォルトルートがないと経路の半分が未定義になり、原因を特定しにくい部分障害が生じます。

こうした設計が破綻するのは戻りの経路です

NAT gateway は既に見たフローの状態を保持するため、外向き接続への応答は新しいインバウンドルールなしで戻ります。この性質はオンプレミスのサービスをインターネットに公開するものではなく、そう扱うとチームは決して成立しない接続のデバッグに一日を費やします。クライアント起点のトラフィックでは四つのルートが一致する必要があります。オンプレミスのポリシー、transit gateway のテーブル、egress subnet のテーブル、NAT subnet のテーブルです。最後を外すと、リクエストは建物を出るのに応答は AWS の中で死にます。

VPN の背後にある実際のクライアントで検証し、どのパブリックな送信元アドレスを提示するか確認します。それが NAT gateway の elastic IP なら変換が行われており、別のものなら別の出口を測っています。

この障害の非対称な形は早めに認識すべきです。ある Availability Zone の NAT subnet テーブルにクライアント prefix への戻りルートがあり、別のゾーンにない場合、新しい接続はフローが落ちるゾーンによって成功したり失敗したりし、そのパターンは不安定なインターネットと誤読されます。チケットが上がったゾーンを直すのではなく、サービス対象の全ゾーンの subnet テーブルを比較してください。欠けたルートが障害のすべてで、向こう側は何も変える必要がありません。

明示的な proxy が優れた設計となる場合

egress VPC のインスタンス上の HTTP proxy は正当な代替案で、しばしば安価です。クライアントはそれを使うよう設定され、proxy が自分で外向きの接続を開き、戻りの経路は対称ルーティングの難題ではなく proxy の問題になります。少数のアプリケーションなら transit gateway の作業の大半が不要になります。NAT gateway では作れないユーザー単位のログも得られます。

ただし透過的ではありません。proxy 設定を無視するもの、そして HTTP 以外のプロトコルは、この経路を通りません。

選択は、アプリケーションが実際に話すプロトコルと、ログにどれだけの識別情報が必要かで決まります。HTTP を話すなら proxy が適所です。任意のプロトコルに一般的な egress が必要なら、AWS がサポートするのは transit gateway の設計です。これを事前に決める方が、ルートテーブルを作った後に発見するより安く済みます。

関連記事