【入門編】 NATゲートウェイのSNAT/DNAT処理とエフェメラルポート(49152〜65535)の枯渇対策 – クラウド&コンテナネットワーク実践ガイド

郵便局の「窓口」が足りない!NATゲートウェイとポート枯渇の切ない関係

クラウドのインフラ設計をしていると、一度は必ずぶつかる壁が「NATゲートウェイ(NAT GW)」です。プライベートな環境にあるサーバーたちに、インターネットへの「お使い」に行かせてあげるための重要な中継地点ですね。

しかし、このNAT GW、実は意外と「キャパシティ不足」になりやすい繊細なやつなんです。今回は、なぜか突然通信ができなくなる「エフェメラルポートの枯渇」という現象を、身近な郵便局の仕組みに例えて紐解いていきましょう。

—

NATゲートウェイは「敏腕な郵便局員」

まず、NATゲートウェイの役割をイメージしてみてください。

プライベートサブネットにあるサーバーは、いわば「住所を持たない隠れ家」です。ここから外の世界(インターネット)へ手紙(リクエスト)を送るには、必ずNAT GWという「郵便局」を経由しなければなりません。

1. プライベートサーバー(差出人)が手紙を出す。
2. NAT GW(郵便局)が手紙を受け取る。
3. NAT GWは、自分の住所に書き換えて、宛先に手紙を送る。
4. 返事が届くと、NAT GWは元の差出人を探して手紙を渡す。

ここで重要なのが、「どの手紙に対する返事なのか」を識別するための番号(ポート番号)です。

なぜ「ポート」が足りなくなるの?

NAT GWが外と通信するとき、送信元ポートとして使われるのが「エフェメラルポート(49152〜65535)」という範囲です。

ここがポイントなのですが、NAT GWは1つの宛先(IPとポートの組み合わせ)に対して1つのポートを割り当てます。そして、通信が終わった後もしばらくの間、「念のため」そのポートを使い回さずにキープしておくというルールがあります。

もし、サーバーが短時間に何千、何万というリクエストを外部に投げ続けるとどうなるでしょうか?

  • 郵便局の窓口(ポート)が全部埋まってしまう。
  • 窓口が空くのを待っている間に、新しい手紙が溜まっていく。
  • 最終的に「今は窓口がいっぱいで受け付けられません!」というエラー(接続タイムアウト)が発生する。

これが、現場で恐れられている「エフェメラルポートの枯渇」の正体です。

—

枯渇を防ぐための「現場の知恵」

この問題に直面したとき、僕たちエンジニアができる対策はいくつかあります。代表的なものを紹介しますね。

1. 接続を「使い回す(コネクションプーリング)」

毎回新しい手紙を出していると、窓口がすぐパンクします。一度確立した接続を閉じずに使い回すのが一番の解決策です。

例えば、Pythonで外部APIを叩く際、requestsライブラリを使うなら、Sessionオブジェクトを使いましょう。

import requests

# セッションを使うことで、コネクションを再利用(Keep-Alive)できます
session = requests.Session()

# これを繰り返しても、裏側では同じ窓口を使い回すのでポートが節約されます
for i in range(1000):
    session.get('https://api.example.com/data')

2. NATゲートウェイを増やす

もしアプリケーションの仕様上、どうしても接続数が多いなら、NAT GWをサブネットごとに分けて並列化しましょう。郵便局が1つで混雑するなら、隣の町にも郵便局を建てるイメージです。

3. 宛先を分散させる

「特定の外部サービスへの大量アクセス」が原因なら、そのサービス側にキャッシュサーバーを置くか、そもそもNAT GWを経由せずに済む方法(VPCエンドポイントなど)がないか検討しましょう。

—

トラブルシューティングのヒント

もし、「特定の時間帯だけ通信が遅い」「エラーが出る」という現象が起きたら、まずはAWSであれば CloudWatch Metrics で ErrorPortAllocation というメトリクスを確認してみてください。

# AWS CLIでNATゲートウェイのメトリクスを確認する例
aws cloudwatch get-metric-statistics \
    --namespace AWS/NATGateway \
    --metric-name ErrorPortAllocation \
    --dimensions Name=NatGatewayId,Value=nat-0123456789abcdef0 \
    --start-time 2023-10-01T00:00:00Z \
    --end-time 2023-10-02T00:00:00Z \
    --period 3600 \
    --statistics Sum

もしこの値が0より大きければ、間違いなく「窓口不足」です。

まとめ:インフラは「流れ」を意識しよう

インフラエンジニアの仕事は、単にサーバーを立てることではありません。パケットという「手紙」が、どのルートを通って、どの窓口で捌かれ、どうやって戻ってくるのか。その「流れ」を想像することが、トラブルを未然に防ぐ第一歩になります。

ポートが枯渇してパニックになる前に、ぜひ皆さんのアプリケーションが「窓口」を適切に使い回せているか、一度コードを見直してみてくださいね。応援しています!

コメント

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