【実務・中級編】 NATゲートウェイのスケールアウトと複数NAT IPアドレスの割り当て – クラウド&コンテナネットワーク実践ガイド

NATゲートウェイの「壁」を突破せよ:複数IPアドレスによるスケーラビリティの最適化

「またか……」深夜のインシデントアラート。見慣れた Connection timed out のログがDatadogのダッシュボードを真っ赤に染めている。

Web APIの負荷が急増した際、多くのエンジニアが真っ先に疑うのはCPUやメモリ、あるいはDBのクエリだ。しかし、ネットワークの最前線で戦っていると、そのボトルネックが意外な場所――NATゲートウェイの「ポート枯渇」にあることに気づかされる。

今回は、AWSのマネージドNATゲートウェイを例に、なぜ単一のIPアドレスでは限界が来るのか、そしてそれを「複数IP」でどう華麗に回避するのか、現場の知見を交えて深掘りしていく。

—

1. なぜ「NATゲートウェイ」がボトルネックになるのか

TCP通信において、送信元IPアドレスと送信元ポート番号、宛先IPと宛先ポートの組み合わせは「5タプル」と呼ばれ、これによって接続が一意に識別される。

NATゲートウェイ(AWSの場合)は、プライベートサブネットからの通信をパブリックIPに変換してインターネットへ送り出す。このとき、ゲートウェイが保持できる送信元ポート数は、1つのIPアドレスあたり最大64,512個という物理的な制約がある。

ここが落とし穴だ。
APIサーバーが外部の決済APIやSaaSへ大量のリクエストを投げる際、もし通信先が同一であれば、5タプルのうち「宛先IP/ポート」と「送信元IP」が固定されるため、使い分けられるのは「送信元ポート」だけになる。

ポート枯渇のメカニズム

1. TIME_WAIT問題: HTTP接続が終了しても、OSはすぐにポートを解放せず TIME_WAIT 状態を維持する。
2. ポートの蒸発: 大量の接続を短時間で繰り返すと、解放待ちのポートが積み上がり、NATゲートウェイが「もう空きポートがない!」と悲鳴を上げる。
3. パケットドロップ: 結果、新規のコネクションはすべて Connection timeout となり、エンドユーザーには503エラーが返される。

—

2. 「複数IPアドレス」という解決策

この状況を打破する最も実務的かつ強力な手法が、NATゲートウェイに複数のパブリックIPアドレスを割り当てることだ。

AWSのNATゲートウェイは、複数のElastic IP(EIP)を付与することで、それらをラウンドロビン的に使い分け、理論上のポート数を「EIPの数 × 64,512」まで拡張できる。

設定の勘所

Terraform等で構成管理しているなら、以下のようにリソースを定義する。

# 複数のEIPを確保
resource "aws_eip" "nat_eip" {
  count = 2 # 2つのIPでポート数を倍増させる
  vpc   = true
}

# NATゲートウェイに複数のEIPを割り当て
resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat_eip[0].id
  subnet_id     = aws_subnet.public.id

  # 2つ目以降のIPを追加する場合の記述
  secondary_allocation_ids = [aws_eip.nat_eip[1].id]
}

これで、NATゲートウェイは通信を分散させ、ポートの枯渇を劇的に遅らせることができる。

—

3. 実践:クライアント側からの確認とデバッグ

インフラ側で対策を施した後、本当にIPが分散されているかを確認する術を知っておく必要がある。単純な curl を使った実験コードがこれだ。

import requests
import time

# 外部のグローバルIP確認用エンドポイント
url = "https://ifconfig.me"

def check_nat_ip():
    try:
        # セッションを張らずに毎回新しいコネクションを作成
        response = requests.get(url, timeout=5)
        print(f"Current Source IP: {response.text}")
    except Exception as e:
        print(f"Error: {e}")

# 連続でリクエストを投げてIPが切り替わるか確認
for _ in range(5):
    check_nat_ip()
    time.sleep(1)

このコードを実行し、出力されるIPアドレスが交互に変わるようであれば、NATゲートウェイの負荷分散が正しく機能している証拠だ。

—

4. SREからのアドバイス:根本治療を忘れるな

複数IPによるスケールアウトは非常に有効だが、あくまで「対症療法」であることを忘れてはならない。以下のチューニングを併せて行うことが、本当の意味での「強いインフラ」を作る。

  • HTTP Keep-Aliveの活用:

TCPコネクションを使い回すことで、ポートの消費を最小限に抑える。Node.jsやPythonの requests (Session) を使う際は、必ずコネクションプールを有効化すること。

  • 通信タイムアウトの短縮:

不要に長いコネクションを保持せず、サーバー側で適切に切断する。

  • VPCエンドポイントの利用:

もし通信先がS3やDynamoDBであれば、NATゲートウェイを通す必要はない。VPCエンドポイントを使えば、NATゲートウェイのポートを1つも消費せずに通信できる。

まとめ

NATゲートウェイのポート枯渇は、成長するサービスにとって必ず通る道だ。慌てず、まずはパケットの出口を増やし、次に通信の質(Keep-Alive)を見直す。この順序を守れば、急激なトラフィック増大も恐れることはない。

ネットワークの挙動を可視化し、論理的な裏付けを持ってインフラを組む。それが、僕らエンジニアが泥臭いトラブルを「過去の経験」へと変える唯一の方法だ。

コメント

タイトルとURLをコピーしました