こんにちは、シニアSREの私です。
クラウドインフラの設計をしていると、必ずと言っていいほどぶつかる壁があります。それが「プライベートサブネットに配置したワーカーノードやコンテナから、どうやって安全に外の世界(外部APIやパッケージリポジトリ)へパケットを届けるか」という問題です。
教科書を開けば「NATゲートウェイを置きましょう」と一言で片付けられますが、AWSの請求書を見て「このマネージドNAT、毎月地味に高いな……自作のNATインスタンスに置き換えたらどれくらい浮くだろう?」と悪魔の囁きが聞こえてくるのは、インフラエンジニアの性(さが)というものでしょう。
今回は、フルマネージドな「NATゲートウェイ」と、EC2で自作する「NATインスタンス」の機能差、パケットの挙動、そして実務で直面するトレードオフについて、現場の泥臭い知見を交えて徹底的に解説します。
—
1. そもそもNATの裏側で何が起きているのか?
プライベートサブネットのインスタンス(例: 10.0.1.100)から、パブリックなWeb API(例: 8.8.8.8:443)へ通信を送る際、パケットはRFC 1918で定められたプライベートIPアドレスのままインターネットに出ることはできません(ルーターに捨てられます)。
ここで登場するのが、SNAT(Source Network Address Translation)です。
1. プライベートIPのパケットが送信元からルーター(NATデバイス)に届く。
2. NATデバイスは、送信元IPアドレスを自身の持つパブリックIPアドレス(例: 203.0.113.50)に書き換える。
3. 同時に、どの内部ホストからの通信かを識別するため、TCP/UDPの送信元ポート番号(Ephemeral Port)を動的に変換・記録する(NAPT / Port Address Translation)。
4. 宛先からのレスポンスが返ってくると、NATデバイスは接続追跡テーブル(Conntrack)を参照し、ポート番号を元に戻してプライベートインスタンスへ返す。
この一連の処理を、AWSが黒魔術のように裏側でオートスケーリングさせながら全自動でやってくれるのが「NATゲートウェイ」であり、Linuxの iptables と ip_forward を使って自前で構築するのが「NATインスタンス」です。
—
2. フルマネージドNATゲートウェイ vs 自作NATインスタンスの徹底比較
実務で選定する際に見るべきポイントは、大きく分けて「コスト」「スケーリング・可用性」「メンテナンス性」の3つです。
| 評価軸 | AWS NAT Gateway (マネージド) | 自作 NAT インスタンス (EC2) |
| :— | :— | :— |
| 初期・ランニングコスト | 比較的高価(時間課金 + 処理データ量課金) | 安価(EC2インスタンス代 + EIP代のみ。データ量課金なし) |
| 可用性 (HA) | アベイラビリティゾーン (AZ) ごとに配置しマルチAZ化可能 | 追加のフェイルオーバー構成(Auto Scaling + Route53/ENI付け替え等)が必要 |
| スループット上限 | 最大 45 Gbps(自動スケールアップ) | 選択した EC2 インスタンスタイプ(ENI)のネットワーク性能に依存 |
| メンテナンス | ゼロ(AWSがパッチ適用・ハードウェア保守を実施) | OSのセキュリティパッチ適用、カーネルチューニングが自己責任 |
| 可観測性 (Metrics) | CloudWatchメトリクスで詳細に追える | 自前で CloudWatch Agent や Prometheus を入れる必要あり |
コストと運用の隠れた罠
「自作NATの方が安い」というのは紛れもない事実ですが、SREの視点では「障害時の人件費(TCO)」を忘れてはいけません。
深夜2時に自作NATインスタンスのカーネルパニックやスループット飽和でプライベートサブネット全体が外通信断になったとき、あなたがその対応に追われるコストは、マネージドサービスの利用料を優に超えます。
—
3. スループットとポート枯渇のトラブルシューティング
外部APIやマイクロサービス群へ大量のリクエストを短時間に投げまくるシステム(例えば、Pythonの requests や Node.js の fetch を使ったクローラーやバッチ処理)において、NAT環境で最も頻発するのが「ポート枯渇(Port Exhaustion)」です。
ポート枯渇メカニズムの背景
TCPコネクションは (送信元IP, 送信元ポート, 宛先IP, 宛先ポート) の4タプルで一意に識別されます。
NATデバイス経由で同一の宛先IP/ポートへ大量のセッションを同時に張る場合、NATデバイス側で割り当てられるエフェメラルポート(通常 1024 から 65535 までの約6万ポート)が枯渇すると、新規のTCPコネクション確立に失敗し、EAGAIN や Connection refused、タイムアウトエラーが頻発します。
具体的なエラーの発生例(Pythonの例)
import requests
import time
# 外部APIへのリクエストを大量に投げるスクリプト
url = "https://api.example.com/v1/data"
for i in range(100000):
try:
# Keep-Aliveが無効、または接続が毎回切断される設定だと、
# 短時間でNATのポート(エフェメラルポート)が枯渇する。
response = requests.get(url, timeout=2)
print(f"Request {i}: Status {response.status_code}")
except requests.exceptions.RequestException as e:
print(f"Request {i} Failed: {e}")
マネージドNATゲートウェイとポート管理
AWSのNATゲートウェイは、1つのパブリックIPにつき最大 64,000 ポートを各宛先IPに対して保持できます。さらに、最大8つのパブリックIPをアタッチして、ポートプールを拡張(ポートアロケーション)することが可能です。
自作NATインスタンスでのカーネルチューニング
一方、自作NATインスタンス(Linux)を使う場合、OSデフォルトのままだとコネクションの再利用効率が悪く、すぐにポートが枯渇します。そのため、/etc/sysctl.conf などでネットワークスタックを適切にチューニングする必要があります。
# /etc/sysctl.conf に記述する推奨パラメータの一例
# TIME_WAIT状態のソケットを素早く再利用できるようにする(セキュリティリスクを理解の上で有効化)
net.ipv4.tcp_tw_reuse = 1
# エフェメラルポートの範囲を広げる
net.ipv4.ip_local_port_range = 1024 65535
# コネクション追跡テーブル(Conntrack)の最大サイズを増やす
# デフォルト値はメモリ容量に応じて小さいため、大規模トラフィックでは必ず溢れる
net.netfilter.ip_conntrack_max = 262144
net.nf_conntrack_max = 262144
# 輻輳制御アルゴリズムにBBRを使用し、高遅延・高スループット回線でのスループットを最適化
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
設定を反映させるには、以下のコマンドを実行します。
sudo sysctl -p
—
4. アーキテクチャ選定のベストプラクティス
では、実際の現場でどちらを選ぶべきでしょうか。私のアーキテクチャ設計における判断基準を共有します。
1. 本番環境(Production):
迷わず AWS NAT Gateway(マネージド) を選択します。障害時の影響範囲が広すぎるため、可用性・スケーラビリティ・保守性を金で買うべきです。マルチAZ構成にしておけば、万が一のAZ障害にも耐えられます。
2. 検証・開発環境(Staging / Dev) / 閉域網の小規模検証:
コストを極限まで抑えたい場合は EC2による自作NATインスタンス が有効です。ただし、t3.micro のようなバースト系インスタンスを選ぶと、CPUクレジット枯渇によるパケットロス地獄を見るため、最低でも t3.medium やネットワーク最適化されたインスタンスを選び、CloudWatchでCPU使用率とネットワークパケット数を監視してください。
3. HTTP/HTTPS通信における根本対策(コネクションプーリング):
NATのポート枯渇対策として、NAT側のスペックを上げる前に、アプリケーション側でHTTP Keep-Aliveを有効にし、コネクションプールを適切に実装することが最もコストパフォーマンスの高いアプローチです。毎回TCPハンドシェイクからやり直す実装を直すだけで、NATへの負荷は劇的に下がります。
—
まとめ
パケットがプライベートサブネットからNATを抜けてインターネットへ飛び出す一連のフローは、クラウドネットワークの醍醐味の一つです。
「安さ」に釣られて自作NATインスタンスを導入し、深夜のポート枯渇やカーネルチューニングの沼にハマる若手エンジニアを何人も見てきました。インフラの総保有コスト(TCO)を見極め、ビジネスの規模と信頼性要件にマッチした正しいNATアーキテクチャを選択してください。あなたのシステムが、今日もスムーズに外の世界と通信できることを祈っています。
コメント