悪魔は「設計の美学」に潜む:Transit GatewayによるNAT集約の罠と処方箋
こんにちは、SREの現場で日々パケットと格闘しているエンジニアです。
今日は、クラウドアーキテクチャの設計で一度は夢見る「NATゲートウェイ(NAT GW)の集約」というトピックについて話をしましょう。AWS Transit Gateway(TGW)を使い、各VPCのアウトバウンド通信を「インスペクション用VPC」にあるNAT GWへ流し込む構成。一見すると、NAT GWのコスト削減やセキュリティ統制の観点から非常にスマートな設計に見えますよね。
しかし、現場でこの構成を構築したエンジニアが、リリース直後のトラフィック急増時にパニックに陥るケースを何度も見てきました。今日は、なぜこの構成が「諸刃の剣」なのか、そしてどう立ち回るべきかを徹底解説します。
—
NAT GW集約構成の通信フローと「非対称」の影
このアーキテクチャでは、各VPCのルートテーブルで 0.0.0.0/0 のターゲットをTGWに設定し、TGW経由でNAT GW VPCへパケットを転送します。
1. 通信のシーケンス(パケットの旅路)
1. Source VPC: EC2から外部API(例: https://api.example.com)へリクエスト送信。ルートテーブルに従いTGWへ。
2. Transit Gateway: ルーティングテーブルに従い、NAT GW VPCへパケットを転送。
3. NAT Gateway: 送信元IPを自身のEIP(Elastic IP)に書き換え、インターネットゲートウェイへ送出。
4. Internet: 宛先のサーバーがレスポンスを返す。
5. Return Path: パケットはNAT GWへ戻り、NAT変換を経てTGWへ、そしてSource VPCへ戻る。
ここで注意すべきは、TGWはステートレスなL3ルーターであるという点です。パケットは往路と復路でTGWを通りますが、NAT GWまでのルーティングが正しく非対称にならないように設計しないと、戻りのパケットが迷子になり、接続タイムアウトが頻発します。
—
避けては通れない「ボトルネック」の正体
多くのエンジニアが躓くのは、「NAT GWのスループット制限」と「TGWのPPS(パケット毎秒)制限」のバランスです。
NAT GWの限界値
NAT GWは1つあたり 最大45Gbps のスループットをサポートしていますが、それは「接続数」や「ポート枯渇」が起きない前提の話です。特に、複数のVPCからのトラフィックを1つのNAT GWに集約すると、SNAT変換時のポート枯渇(Port Allocation Error)が真っ先に発生します。
解決のための実戦的Tips:Pythonによる接続検証コード
NAT GW経由の通信でポートが枯渇しているか、あるいはTGWでドロップしていないかを切り分けるために、以下のような疎通テスト用スクリプトを準備しておくと非常に有用です。
import requests
import time
# 接続先APIエンドポイント
URL = "https://api.example.com/v1/health"
def test_connection(count):
# NAT GWのポート枯渇を確認するため、短時間に大量のコネクションを張る
for i in range(count):
try:
response = requests.get(URL, timeout=2)
if response.status_code == 200:
print(f"[{i}] Success")
except requests.exceptions.ConnectionError:
# ここで発生するエラーをログに詳細に出すのが肝
print(f"[{i}] Connection Failed - Check NAT GW Port Exhaustion")
time.sleep(0.1)
if __name__ == "__main__":
test_connection(100)
—
運用の現場で意識すべき設計の掟
1. 冗長化とスケーラビリティの確保
NAT GWを1つに絞るのは、単一障害点(SPOF)を作るのと同じです。複数のアベイラビリティゾーン(AZ)にまたがってNAT GWを配置し、TGWのルートテーブルで各AZ宛のトラフィックを振り分けるのが定石です。
2. AWS CLIでトラフィックパターンを可視化する
TGWのトラフィックがボトルネックになっているかを確認するには、CloudWatch Metrics を見るのが一番ですが、CLIで設定のミスをチェックすることも重要です。
# 特定のTGWルートテーブルの伝播状況を確認
aws ec2 get-transit-gateway-route-table-associations \
--transit-gateway-route-table-id tgw-rtb-0123456789abcdef
# NAT GWのネットワークインターフェース(ENI)のメトリクスを確認
# PortAllocationErrorが発生していないかを確認するのがポイント
aws cloudwatch get-metric-statistics \
--namespace AWS/NATGateway \
--metric-name ErrorPortAllocation \
--dimensions Name=NatGatewayId,Value=nat-0123456789abcdef \
--start-time 2023-10-01T00:00:00Z --end-time 2023-10-02T00:00:00Z \
--period 3600 --statistics Sum
—
まとめ:アーキテクトとしての心得
NAT GWの集約は、管理コストを減らすという「甘い誘惑」がありますが、その裏には「スループットの限界」と「ルーティングの複雑化」というリスクが確実に存在します。
- 非対称ルーティング: TGWのルートテーブルはAZごとに独立して管理すること。
- ポート枯渇: NAT GWが複数ある場合、ソースVPCのサブネットとNAT GWのAZを一致(アフィニティ)させることで、無駄なAZ間トラフィックを減らし、かつポート効率を最大化できます。
- 監視:
ErrorPortAllocationメトリクスには必ずアラートを設定しておくこと。
ネットワークは一度組んで終わりではありません。パケットがどこを通り、どこで滞留しているのか、その「流れ」を常に可視化する準備をしておくことこそが、真のSREとしての矜持です。
皆さんのインフラが、今日も安定してパケットを運び続けますように。それでは、また。
コメント