【実務・中級編】 NATインスタンスとNATゲートウェイの機能比較と運用上のトレードオフ – クラウド&コンテナネットワーク実践ガイド

こんにちは、シニア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アーキテクチャを選択してください。あなたのシステムが、今日もスムーズに外の世界と通信できることを祈っています。

コメント

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