VPC 入門 — サブネット / ルートテーブル / IGW を図解で理解する
概要
AWS を触りはじめて最初にぶつかるのが VPC(Virtual Private Cloud)です。EC2 を1台立てるだけでも「どのサブネットに置くか」「インターネットに出られるか」を意識せざるを得ません。
この記事では、VPC を構成する主要パーツ(サブネット / ルートテーブル / Internet Gateway / NAT Gateway)が、それぞれ何のためにあり、どう繋がって「通信できる / できない」を決めているのかを、図とともに整理します。対象は「なんとなく VPC を作ったが、ルーティングの仕組みが腹落ちしていない」方です。
VPC とは何か
VPC は、AWS アカウント内に確保する論理的に隔離された自分専用のネットワークです。オンプレミスでいえば「自社データセンターの1棟」に相当し、その中に部屋(サブネット)を切り、部屋間・外部との通信経路(ルートテーブル)を自分で設計します。
VPC を作るとき最初に決めるのが CIDR ブロックです。
VPC CIDR: 10.0.0.0/16 → 10.0.0.0 〜 10.0.255.255(約 65,536 IP)
この /16 の中を、さらに小さなサブネットに分割していきます。
全体像(図解)
┌─────────────────────────────────────────────────────────┐
│ VPC 10.0.0.0/16 │
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ Public Subnet │ │ Private Subnet │ │
│ │ 10.0.1.0/24 │ │ 10.0.2.0/24 │ │
│ │ [EC2: Web] │ │ [EC2: DB / App] │ │
│ │ ▼ Route Table A │ │ ▼ Route Table B │ │
│ │ 0.0.0.0/0 → IGW │ │ 0.0.0.0/0 → NATGW │ │
│ └─────────┬─────────────┘ └──────────┬───────────┘ │
│ ┌───▼────┐ ┌────▼─────┐ │
│ │ IGW │ │ NAT GW │ │
│ └───┬────┘ └────┬─────┘ │
└─────────────┼─────────────────────────── ┼─────────────┘
▼ ▼
Internet ◄──────(NAT経由の戻り)────┘
ポイントは、「Public か Private か」を決めているのはサブネットそのものではなく、そのサブネットに紐づくルートテーブルの中身だという点です。ここが最初の落とし穴です。
サブネット
サブネットは VPC の CIDR をさらに分割した範囲で、必ず1つのアベイラビリティゾーン(AZ)に属します。VPC がリージョン単位なのに対し、サブネットは AZ 単位である、という粒度の違いを押さえてください。
VPC 10.0.0.0/16 ├─ Subnet 10.0.1.0/24 (ap-northeast-1a) ← Public にする予定 ├─ Subnet 10.0.2.0/24 (ap-northeast-1a) ← Private にする予定 ├─ Subnet 10.0.3.0/24 (ap-northeast-1c) ← 冗長化用 └─ Subnet 10.0.4.0/24 (ap-northeast-1c)
AWS が予約する 5 IP
/24(256 IP)を作っても、実際に使えるのは 251 個です。各サブネットの先頭4つと末尾1つは AWS が予約します。
10.0.1.0 ネットワークアドレス 10.0.1.1 VPC ルーター 10.0.1.2 Amazon が提供する DNS 10.0.1.3 将来利用のための予約 10.0.1.255 ブロードキャスト(AWSでは使わないが予約)
小さすぎる CIDR(/28 = 16 IP のうち使えるのは 11 個)を切ると、思ったより早く IP が枯渇します。
ルートテーブル
ルートテーブルは「宛先 IP レンジごとに、どこへパケットを送るか」を定義した道案内表です。各サブネットには必ず1つのルートテーブルが関連付きます。
Public サブネット用(Route Table A)
Destination Target 10.0.0.0/16 local ← VPC 内は常に local(削除不可) 0.0.0.0/0 igw-xxxxxxxx ← それ以外は Internet Gateway へ
0.0.0.0/0(=上のどの行にも当てはまらない全ての宛先)を IGW に向けているため、このサブネットの EC2 はインターネットへ出られます。この行があるサブネットが「Public サブネット」と呼ばれます。
Private サブネット用(Route Table B)
Destination Target 10.0.0.0/16 local 0.0.0.0/0 nat-xxxxxxxx ← 外向きは NAT Gateway 経由
0.0.0.0/0 を IGW ではなく NAT Gateway に向けています。これにより「こちらからは外へ出られる(パッケージ更新など)が、外から直接は入られない」構成になります。
ルート評価は「最長プレフィックス一致」
宛先が複数のルートにマッチする場合、AWS はより具体的(プレフィックスが長い)なルートを優先します。
宛先 10.0.2.50 の場合:10.0.0.0/16 が採用 → local(IGW には行かない) 宛先 8.8.8.8 の場合:0.0.0.0/0 が採用 → IGW へ
Internet Gateway(IGW)
IGW は VPC とインターネットを繋ぐ出入口です。
- VPC に1つだけアタッチできる
- 水平スケール・冗長化済みで、帯域ボトルネックにならない(マネージド)
- IGW 自体は無料(通信量課金はある)
IGW は「アタッチしただけ」では通信できません。次の3点が揃って初めてインターネット通信が成立します。
- IGW が VPC にアタッチされている
- サブネットのルートテーブルに
0.0.0.0/0 → igwがある - EC2 がパブリック IP(または EIP)を持っている
3 が抜けていて「ルートは通したのに繋がらない」というのが典型的なハマりどころです。
NAT Gateway(Private からの外向き通信)
Private サブネットの EC2 はパブリック IP を持たないため、そのままでは外部へアクセスできません。かといって IGW に向けると「外から入られる」経路も開いてしまう。そこで NAT Gateway を Public サブネットに置き、Private からの外向き通信を代理させます。
[Private EC2] --0.0.0.0/0--> [NAT GW (Public Subnet)] --> [IGW] --> Internet
▲ │
└──────────────── 戻りパケットのみ通す ─────────────────────────┘
- NAT Gateway 自身は Public サブネットに置く(IGW への経路が必要なため)
- Private サブネットのルートは
0.0.0.0/0 → nat-xxxx - 外部から NAT 経由で内部へ入る経路は存在しない(=インバウンド遮断)
なお NAT Gateway は起動している間ずっと課金され、通信量にも課金されます。学習用途では消し忘れに注意してください。
実装例(AWS CLI 最小構成)
# 1. VPC 作成 VPC_ID=$(aws ec2 create-vpc \ --cidr-block 10.0.0.0/16 \ --query 'Vpc.VpcId' --output text) # 2. Public サブネット作成 SUBNET_ID=$(aws ec2 create-subnet \ --vpc-id "$VPC_ID" \ --cidr-block 10.0.1.0/24 \ --availability-zone ap-northeast-1a \ --query 'Subnet.SubnetId' --output text) # 3. Internet Gateway を作成して VPC にアタッチ IGW_ID=$(aws ec2 create-internet-gateway \ --query 'InternetGateway.InternetGatewayId' --output text) aws ec2 attach-internet-gateway \ --vpc-id "$VPC_ID" --internet-gateway-id "$IGW_ID" # 4. ルートテーブルを作成しサブネットに関連付け RTB_ID=$(aws ec2 create-route-table \ --vpc-id "$VPC_ID" \ --query 'RouteTable.RouteTableId' --output text) aws ec2 associate-route-table \ --route-table-id "$RTB_ID" --subnet-id "$SUBNET_ID" # 5. 0.0.0.0/0 → IGW のルートを追加(ここで初めて外に出られる) aws ec2 create-route \ --route-table-id "$RTB_ID" \ --destination-cidr-block 0.0.0.0/0 \ --gateway-id "$IGW_ID" # 6. このサブネットで起動する EC2 に自動でパブリック IP を割り当てる aws ec2 modify-subnet-attribute \ --subnet-id "$SUBNET_ID" \ --map-public-ip-on-launch
確認方法
構成後、通信可否を切り分けるチェックポイントです。
- ルートテーブルの中身を確認する
``bash aws ec2 describe-route-tables --route-table-id "$RTB_ID" \ --query 'RouteTables[].Routes' ``
- EC2 にパブリック IP が付いているか
``bash aws ec2 describe-instances --instance-ids i-xxxx \ --query 'Reservations[].Instances[].PublicIpAddress' ``
- セキュリティグループ / ネットワーク ACL で該当ポートが許可されているか(ルーティングが正しくてもここで止まる)。
- 実際に EC2 から
curl https://checkip.amazonaws.comなどで外部到達を確認する。
注意点
- Public / Private を分けているのはルートテーブルであり、サブネットの名前ではない。
- IGW は「アタッチ + ルート + パブリック IP」の3点セットで初めて機能する。
- サブネットは AZ 単位。冗長構成にするなら最低2つの AZにサブネットを分ける。
- NAT Gateway は起動中ずっと課金される。検証後の削除を忘れない。
- IP レンジは後から広げにくい。最初に余裕を持った CIDR 設計にする。
まとめ
- VPC = 自分専用の隔離ネットワーク。まず CIDR を決める。
- サブネット = VPC を AZ 単位で分割した範囲。先頭4 + 末尾1 の 5 IP は予約される。
- ルートテーブル = 宛先ごとの道案内。
0.0.0.0/0の向き先が Public / Private を決める。 - IGW = インターネットの出入口。アタッチ + ルート + パブリック IP の3点で機能する。
- NAT Gateway = Private からの「外へは出るが外からは入られない」経路。
この4つの関係が腹落ちすると、「ルートは正しいのに繋がらない」系のトラブルを、どのレイヤーで切り分ければよいかが見えてきます。
