クラウドインフラの構築において、VPC(Virtual Private Cloud)の設計はシステムの命運を握るファーストステップです。なかでも「パブリックサブネット」と「インターネットゲートウェイ(IGW)」のルーティング設計は、一見すると教科書通りに作れば動くシンプルな領域に見えます。
しかし、現場のSREとして数々の本番障害や通信断のトラブルシュートを経験してくると、この基本の組み合わせこそが、ルーティングの競合、非対称ルーティング(Asymmetric Routing)、そして暗黙のステートフル制御の理解度を試す「最初の関所」であることに気づかされます。
今回は、パブリックサブネットがなぜインターネットに直結できるのか、その裏側にあるパケットの旅路と、実務で絶対に外せないルーティング設計の勘所を、泥臭い実運用者の視点から徹底的に解説します。
—
1. パブリックサブネットとIGWの本質的な関係
「パブリックサブネット」という言葉は、AWSをはじめとするメガクラウドのコンソール画面で日常的に使われますが、実はクラウドベンダーの内部実装において、サブネット自体に「パブリック」という特別なフラグがハードコードされているわけではありません。
サブネットがパブリックであるかプライベートであるかを決定づけている唯一の要素、それは「ルートテーブル(Route Table)のルーティング先(Target)にインターネットゲートウェイ(IGW)が設定されているかどうか」、これに尽きます。
IGWはルーターではなく「ソフトウェア定義のエッジプロキシ」だ
物理ネットワークの世界で育ったエンジニアほど、ゲートウェイと聞くとハードウェアのルーターを想像しがちです。しかし、AWSなどのパブリッククラウドにおけるIGWは、VPCのエッジに水平分散配置された、可用性とスケーラビリティが無限に担保された仮想的なソフトウェアモジュールです。
IGWの最大の役割は、VPC内のインスタンス(EC2やコンテナノードなど)が持つプライベートIPアドレスと、インターネット上のグローバルIPアドレス(パブリックIPv4アドレスやElastic IP)との間のNAT(Network Address Translation)、およびパケットの転送制御です。
—
2. パケットの往復を追う:IGW連携の通信フロー
外部のクライアントや外部APIサーバーから、パブリックサブネット上に配置されたWebサーバーへの通信がどのように流れるのか、そのパケットのライフサイクルをシーケンスとして追ってみましょう。
ここでは、AWS環境を例に、リクエストが到達し、レスポンスが返るまでの流れを紐解きます。
[外部クライアント]
│ (インターネット経由 / グローバルIP宛て)
▼
[インターネットゲートウェイ (IGW)]
│ (宛先IPをプライベートIPにNAT変換)
▼
[パブリックサブネットのルートテーブル]
│ ( 0.0.0.0/0 -> igw-xxxxxxxx )
▼
[EC2インスタンス (Webサーバー / プライベートIP)]
1. インバウンド(外から中へ):
外部からグローバルIP宛てに送られたパケットがIGWに到達します。IGWは、自身が保持するNATマッピングテーブルを参照し、宛先IPアドレスをEC2インスタンスのプライベートIPアドレスに書き換えます(DNAT)。
2. ルートテーブルの参照:
サブネットのルートテーブルには、デフォルトルートとして 0.0.0.0/0 のターゲットにIGWが指定されています。しかし、インバウンドパケットの視点では、すでにVPC内に入ってきているため、次はインスタンス自身のENI(Elastic Network Interface)へとパケットが配送されます。
3. アウトバウンド(中から外へ):
サーバー側が処理を終え、レスポンスを返す際、送信元はプライベートIP、宛先は外部のグローバルIPとなります。
4. IGWでの逆変換(SNAT):
パブリックサブネット内のルートテーブルに従い、宛先不明のパケットはすべて 0.0.0.0/0 を通じてIGWに送り出されます。IGWはパケットの送信元プライベートIPを元のパブリックIP/EIPに書き換え(SNAT)、インターネットへ放流します。
この仕組みの肝は、パブリックサブネットに属するインスタンス自身がグローバルIPを直接インターフェースにバインドしているわけではなく、AWSのエッジ(IGW)が代理でNATを行っているという点です。
—
3. 実務で遭遇するエッジケースとハマりどころ
現場で設計・運用をしていると、教科書通りにいかないケースに直面します。特に注意すべき2つのエッジケースを共有します。
エッジケース①:パブリックサブネットなのにアウトバウンド通信ができない?
「パブリックサブネットなのだから、配置したインスタンスは当然外のAPIを叩けるはずだ」と思っていませんか?
ここで問題になるのが、インスタンス自体がパブリックIPv4アドレスまたはElastic IP(EIP)を持っているか、あるいはAWSの機能であるENIレベルでのパブリックIP割当が有効になっているかという点です。
パブリックサブネットのルートテーブルに 0.0.0.0/0 -> IGW が設定されていても、インスタンス自身に紐づくグローバルIPが存在しない場合、IGWは「どのパブリックIPにNATしていいか分からない」ため、アウトバウンドパケットをドロップします。
エッジケース②:非対称ルーティング(Asymmetric Routing)の罠
Kubernetesクラスター(EKSや自前構築のK8s)をパブリックサブネットとプライベートサブネットにまたがって構築したり、複数のENIを1つのインスタンスにアタッチしたりする高度な設計では、非対称ルーティングの罠に陥りがちです。
パケットの往路と復路で異なるゲートウェイやルートを通ると、ステートフルなファイアウォール(AWSのセキュリティグループやネットワークACL)によって「不正なパケット」とみなされ、接続がランダムに切断されるという、原因特定が非常に困難な障害を引き起こします。
—
4. 実装例:IaCとアプリケーションコードの確認
ここからは、実際にTerraformでのルートテーブル構築設定と、パブリックサブネット上のアプリケーションから外部APIへ疎通確認を行うコードを見ていきます。
TerraformによるパブリックサブネットとIGWのルーティング定義
実務で最も一般的に使われるTerraformのコードスニペットです。
# インターネットゲートウェイの作成
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "production-igw"
}
}
# パブリックサブネット用ルートテーブルの作成
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
# すべての外部トラフィック(0.0.0.0/0)をIGWに向けるデフォルトルート
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "production-public-rt"
}
}
# パブリックサブネットとルートテーブルの関連付け
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
Pythonによる外部Web APIへの疎通テストコード
パブリックサブネット上のコンテナやEC2から、外部の決済APIやSaaSへ正しくリクエストが飛ぶかを検証するためのPython(requestsライブラリ)スクリプトです。タイムアウト設定と例外処理を明記し、本番の死活監視にも耐える実装にしています。
import requests
import sys
def check_external_connectivity():
target_url = "https://api.ipify.org?format=json" # 自身のグローバルIPを返すパブリックAPI
try:
# 接続タイムアウトを3秒、読み込みタイムアウトを5秒に設定
response = requests.get(target_url, timeout=(3.0, 5.0))
# HTTPステータスコードが200番台以外の場合は例外を発生させる
response.raise_for_status()
data = response.json()
print(f"[SUCCESS] 外部ネットワークへの疎通に成功しました。")
print(f"[INFO] IGWを通過したグローバルIPアドレス: {data.get('ip')}")
except requests.exceptions.Timeout:
print("[ERROR] 外部APIへの接続がタイムアウトしました。ルートテーブルのIGW設定やセキュリティグループを確認してください。", file=sys.stderr)
sys.exit(1)
except requests.exceptions.RequestException as e:
print(f"[ERROR] 予期せぬネットワークエラーが発生しました: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
check_external_connectivity()
—
5. まとめ:シニアSREからの実務的アドバイス
パブリックサブネットとIGWのルーティング設計は、クラウドネットワークの基本中の基本ですが、それゆえに「動いて当たり前」として見落とされがちなポイントでもあります。
トラブルシューティングの現場では、まず以下のチェックリストを上から順に確認してください。
1. ルートテーブルの存在確認: サブネットに関連付けられているルートテーブルに 0.0.0.0/0 -> igw-xxxxxxxx が正しく記述されているか。
2. IGWのVPCアタッチ確認: インターネットゲートウェイ自体が、対象のVPCにアタッチ(Attached)されているか。
3. グローバルIPの有無: インスタンスやENIにパブリックIPv4/EIPが正しく付与されているか(アウトバウンド時)。
4. セキュリティグループとNACL: アウトバウンド(送信)のトラフィックが 0.0.0.0/0 に対して許可されているか。
これら一つひとつの要素が噛み合ってはじめて、安全でスムーズなインターネット通信が実現します。ネットワークのパケットの挙動を頭の中でイメージできるようになれば、どんな複雑なマルチVPC環境であっても恐れることはありません。日々のインフラ運用・設計の精度を高めていきましょう。
コメント