クラウドネットワークの罠:NATゲートウェイが「突然遅くなる」夜、SREはどうパケットを追いかけるか
夜中の2時。PagerDutyの鋭いアラート音で飛び起きたあなたを待ち受けているのは、「外部APIへのリクエストが突然タイムアウトし始めた」「バッチ処理の完了時間が3倍に膨れ上がった」というインシデントだ。
ダッシュボードを開くと、CPU負荷は正常、アプリケーションサーバーのメモリも枯渇していない。しかし、プライベートサブネットからインターネットへ向かうトラフィックの出口である、あの小さな黒衣――NATゲートウェイ(NAT Gateway)のメトリクスだけが、不気味な跳ね上がりを見せている。
「おいおい、パブリッククラウドなんだから勝手にスケールしてくれるんじゃないのかよ?」
そう、AWSのNAT GatewayなどをはじめとするマネージドなNATデバイスは、初期状態で5 Gbpsの帯域幅を持ち、必要に応じて最大45 Gbpsまで自動的にスケールアウトする。しかし、この「自動スケール」という言葉を鵜呑みにしていると、現場のエンジニア痛い目を見る。今回は、パケットがNATの壁を通過する際のリアルな挙動と、急激なトラフィック増大(バースト)時に何が起きているのか、そのメカニズムと実践的な対策を紐解いていこう。
—
1. NATゲートウェイの自動スケーリングメカニズム:5 Gbpsから45 Gbpsへの道のり
まず、クラウドのマネージドNAT Gatewayがどのように帯域幅を拡大させているのか、その裏側の物理的・論理的構造をイメージしてみよう。
多くのクラウドプロバイダーにおいて、NAT Gatewayは単一の仮想マシンではなく、高可用性を担保された分散ルーター群として実装されている。設計上、初期状態では 5 Gbps の帯域幅が割り当てられているが、トラフィックの増加に伴って動的にバックエンドのリソースが追加され、段階的に最大 45 Gbps まで拡張される。
ここで重要なのは、「トラフィックが急増した瞬間に、一瞬たりとも遅延なく45 Gbpsになるわけではない」という点だ。
スケールアウトのトリガーとラグ
NAT Gatewayのスケーリングは、トラフィックの増加量をモニタリングし、バックエンドのキャパシティを追加するまでにわずかな「タイムラグ」が存在する。
平時は数Mbpsで推移していたシステムが、キャンペーン開始や大規模なバッチ処理の起動によって、数秒の間に数十Gbps規模のトラフィック(いわゆるスパイク・バースト)を叩き込んだ場合、スケーリングの追従が間に合わない。
この瞬間、何が起きるか?
あふれたパケットはバッファに溜まり、やがてドロップ(破棄)される。TCPであれば再送制御(Retransmission)が走り、HTTPレベルではレイテンシーの劇的な悪化やコネクションプールの枯渇、ひいてはタイムアウトエラーへと直結するのだ。
—
2. ネットワークの深層:SNATとポート枯渇のジレンマ
帯域幅の制限と並んで、SREを最も悩ませるのが「ポート枯渇(Port Exhaustion)」だ。プライベートサブネットからインターネット上の単一の宛先(例えば外部の決済APIなど)へ大量のリクエストを投げる際、NAT Gatewayは自身のグローバルIPアドレスと、送信元ポート番号の組み合わせ(NAPT: Network Address Port Translation)を書き換えている。
TCP/IPの仕様上、利用可能なポート番号は最大で 65,535 番だが、システム予約ポートなどを除くと、1つのIPアドレスあたり実際に使えるエフェメラルポート(動的ポート)は約 60,000 個程度に制限される。
[Private Subnet] [NAT Gateway] [Internet / External API]
App Server (10.0.1.10:50000) ==> SNAT (203.0.113.5:10000) ==> Target API (80.80.80.80:443)
もし、ひとつのNAT Gatewayを経由して、同一の宛先IP・ポートに対して秒間数万件のリクエストを送り続けるとどうなるか?
TIME_WAIT状態のポートが解放される前に利用可能なポートが枯渇し、新規のTCPコネクション確立(SYNパケット)がNAT Gateway側で破棄されるようになる。これが「パケットロス」の正体だ。
—
3. 実践:バースト耐性を高めるアプリケーション設計とコード実装
では、このNATゲートウェイの特性を理解した上で、インフラ任せにするのではなく、アプリケーション側やクライアント側でどのようにハンドリングすべきだろうか。
Pythonの requests ライブラリや、Node.jsの Fetch API を用いる際、デフォルト設定のまま放置すると、毎回新しいTCPコネクションを張ろうとしてNATのポートと帯域を無駄に消費する。
事例A: Python (Requests) でのコネクションプーリングとリトライ設定
安全なWeb APIクライアントを実装する場合、urllib3 の HTTPAdapter を用いてコネクションを再利用(Keep-Alive)し、かつ指数バックオフ(Exponential Backoff)によるリトライを組み込むことが鉄則だ。
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
def create_robust_session():
session = requests.Session()
# リトライ戦略の定義(ステータスコード 502, 503, 504 や接続エラー時にリトライ)
retries = Retry(
total=5,
backoff_factor=0.5, # 0.5秒, 1.0秒, 2.0秒...とバックオフ
status_forcelist=[502, 503, 504],
raise_on_status=False
)
# コネクションプールのサイズを大きめに確保し、TCPセッションを再利用する
# これによりNATポートの急速な消費を防ぐ
adapter = HTTPAdapter(
pool_connections=50,
pool_maxsize=50,
max_retries=retries
)
session.mount("https://", adapter)
session.mount("http://", adapter)
return session
# 使用例
if __name__ == "__main__":
client = create_robust_session()
try:
response = client.get("https://api.example.com/v1/data", timeout=5.0)
print(f"Status: {response.status_code}, Body: {response.text[:100]}")
except requests.exceptions.RequestException as e:
print(f"Network or Timeout Error occurred: {e}")
事例B: 負荷テスト・ベンチマーク時の注意(curlやApacheBench)
インフラのキャパシティテストを行う際、よく ab コマンドや wrk が使われるが、これらもデフォルトでは毎回コネクションを新規作成する挙動になりやすい。NAT Gatewayの限界値テストを行う場合は、-k オプション(HTTP Keep-Alive)を必ず有効化し、意図しないポート枯渇を引き起こしていないかメトリクスを監視しながら実施すべきだ。
—
4. 現場のSREが実践するデバッグと監視のチェックリスト
もしあなたが現在進行形で「NAT起因と思われるレイテンシー悪化」に直面しているなら、以下の手順で切り分けを行ってほしい。
1. クラウドWatch/Metricsの確認
ErrorPortAllocation(ポート割り当てエラー)やPacketsDropCount(パケットドロップ数)のメトリクスが跳ね上がっていないか確認する。ここに数値が出ている場合、明らかなポート枯渇または帯域の急激な頭打ちが発生している。
2. NAT Gatewayの数とトラフィック分散の見直し
- 単一のNAT Gatewayにトラフィックが集中していないか? マルチAZ構成で複数のNAT Gatewayを配置し、ルートテーブルをサブネットごとに適切に分割しているか確認する。
3. TCP TIME_WAIT の確認(OS側)
- アプリケーションサーバー側で
ss -sやnetstat -an | grep TIME_WAITを実行し、コネクションが適切に閉じられているか、あるいは溜まりすぎていないかをチェックする。
—
まとめ
NATゲートウェイは、「プライベートなリソースを安全にインターネットに接続する黒衣」として非常に優秀だが、その裏側には 5 Gbps から 45 Gbps に至るスケーリングの物理的・論理的限界と、ポート番号という数的な制約が存在する。
「クラウドだから何もしなくても無限にスケールする」という幻想を捨て、アプリケーション層でのコネクションプーリング、適切なリトライとバックオフ、そしてマルチNATによる負荷分散設計を取り入れること。それこそが、深夜のインシデントアラートを静かにするための、我々シニアエンジニアの確かな処方箋なのである。
コメント