1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【図解】AWS VPCとは。5つの部品と、外から繋がらない原因を全部まとめた

1
Last updated at Posted at 2026-08-18

対象読者: AWSをこれから触る人。 AWS勉強シリーズの6本目で、今回はVPCです。全体の地図は索引記事にあります。

EC2を立てたのに、こういう症状で止まった人向けに書きます。

  • 「サーバーは起動しているのに、外からアクセスできない」
  • 「サブネットって何個作ればいいのか、そもそも何なのか分からない」

このどちらも、VPCの5つの部品(建物・部屋・玄関・案内板・警備員)のどれかが欠けているか、繋がっていないのが原因です。

VPCは、クラウドの中に建てる自分専用のマンション
VPCの部品をマンションに例えた図(筆者作成)。この記事の全部がこの1枚に入っています。

VPCとは何か

Amazon VPC(Virtual Private Cloud)は、AWSの中に自分専用のネットワークを区切って作るサービスです。EC2やRDSといったサーバー系のサービスは、必ずどこかのVPCの中に置きます。上の図でいうとVPCは「マンションの建物全体」で、その中に部屋(サブネット)を作り、玄関(インターネットゲートウェイ)を付け、案内板(ルートテーブル)で通り道を決め、各部屋のドアに警備員(セキュリティグループ)を立てます。VPC自体の料金は無料です(中に置くEC2やNATゲートウェイには料金がかかります)。

何に使うか

  • 外に見せる部分と隠す部分を分ける: Webサーバーは外から見える部屋に、データベースは外から見えない部屋に置く。DBに直接インターネットから届かない構造にする
  • 自分のIPアドレスの範囲を決める: 10.0.0.0/16 のように、社内ネットワークと被らない範囲を自分で選ぶ
  • 通信の入口・出口を1か所に絞る: 玄関(インターネットゲートウェイ)を通らないと外に出られない、という構造で守る
  • オンプレミスや別VPCと繋ぐ: VPN・Direct Connect・VPCピアリングの土台になる(この記事では扱いません)

重要用語

用語 マンションで言うと 意味
VPC 建物全体 自分専用のネットワークの範囲。IPの範囲(CIDR)を1つ持つ
サブネット 部屋 VPCの中をさらに区切った小さな範囲。1つのアベイラビリティゾーン(データセンター群)に属する
インターネットゲートウェイ(IGW) 外への玄関 VPCとインターネットを繋ぐ出入口。1つのVPCに1つ
ルートテーブル 案内板 「この宛先はどこへ送るか」の表。サブネットごとにどの案内板を見るか決める
セキュリティグループ(SG) 部屋のドアの警備員 サーバー単位で「どのポートを誰に開けるか」を決める
パブリックサブネット 外に面した部屋 ルートテーブルにIGW向けの経路がある部屋
プライベートサブネット 内側の部屋 IGW向けの経路がない部屋。外から直接届かない
CIDR 部屋番号の範囲 10.0.0.0/16 のようなIP範囲の書き方。/16 は約65,000個、/24 は256個

仕組みの要点

初心者が一番つまずくのがここです。パブリックとプライベートの違いは、サブネットの種類ではなく、ルートテーブルの中身で決まります。 サブネットを作った時点では全部同じで、そのサブネットが見ている案内板に「0.0.0.0/0(全部の外)→IGW」という行があれば外に出られる部屋、無ければ出られない部屋になります。

実際に、ルートを何も設定していないサブネットが見ているルートテーブルの中身を取ると、こうなっています。

10.0.0.0/16 -> local

「VPCの中同士は通じる」の1行だけで、外への経路がありません。だからこの部屋のサーバーは、起動していてもインターネットから届きません。「サーバーは動いているのに外から繋がらない」の正体の一つがこれです。

もう一つ、警備員(セキュリティグループ)は通したいものだけを書く方式です。何も書かなければ全部止めます。443を開ける行を書いて初めてHTTPSが通ります。

このコードを動かす前提

この記事のコードはPython(boto3)です。動かす方法は2通りあります。

A. AWSアカウント無しで試す(おすすめ): motoというAWSのそっくりさんを使うと、課金もサインアップもなしでPCの中だけで動きます。

python3 -m venv venv
./venv/bin/pip install boto3 moto
from moto import mock_aws

@mock_aws            # この中のboto3呼び出しは全部ローカルの偽AWSに行く
def main() -> None:
    ...              # 以下の記事のコードをここに入れる

main()

B. 本物のAWSで動かす: 先にIAMユーザーとアクセスキーを作って aws configure で登録しておく必要があります。手順はIAMの記事にあります。

使い方

「建物→部屋→玄関→案内板→警備員」の順に作ります。Python(boto3)での最小の形です。

import boto3
ec2 = boto3.client("ec2", region_name="ap-northeast-1")

# ① 建物: VPCを作る(IPの範囲を決める)
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]

# ② 部屋: サブネットを作る(VPCの範囲の中から切り出す)
sub = ec2.create_subnet(VpcId=vpc, CidrBlock="10.0.1.0/24",
                        AvailabilityZone="ap-northeast-1a")["Subnet"]["SubnetId"]

# ③ 玄関: インターネットゲートウェイを作ってVPCに付ける
igw = ec2.create_internet_gateway()["InternetGateway"]["InternetGatewayId"]
ec2.attach_internet_gateway(InternetGatewayId=igw, VpcId=vpc)

# ④ 案内板: 「全部の外→玄関」の行を書いて、部屋に紐付ける
rt = ec2.create_route_table(VpcId=vpc)["RouteTable"]["RouteTableId"]
ec2.create_route(RouteTableId=rt, DestinationCidrBlock="0.0.0.0/0", GatewayId=igw)
ec2.associate_route_table(RouteTableId=rt, SubnetId=sub)

# ⑤ 警備員: 443番だけ通す
sg = ec2.create_security_group(GroupName="web", Description="web", VpcId=vpc)["GroupId"]
ec2.authorize_security_group_ingress(
    GroupId=sg,
    IpPermissions=[{"IpProtocol": "tcp", "FromPort": 443, "ToPort": 443,
                    "IpRanges": [{"CidrIp": "0.0.0.0/0"}]}])

④まで終わった時点で、この部屋はパブリックサブネットになっています。④をやらなければ、同じ部屋がプライベートサブネットのままです。違いはコード1行(create_route)だけです。

実際に叩くと止まるところ

作り方を間違えたときにどんなエラーが返るかを、5パターン実際に叩きました。エラー文を読めれば、どの部品が悪いか分かります。

やったこと 返ってきたエラー 意味
VPCの範囲(10.0.0.0/16)の外にサブネット(10.1.0.0/24)を作る InvalidSubnet.Range: The CIDR '10.1.0.0/24' is invalid. 部屋は建物の中にしか作れない
同じ範囲(10.0.1.0/24)のサブネットをもう1つ作る InvalidSubnet.Conflict: conflicts with another subnet 部屋番号の範囲は重ねられない
1つのIGWを2つ目のVPCにも付ける Resource.AlreadyAssociated 玄関は1つのVPC専用。VPCごとに作る
サブネットが残っているVPCを消す DependencyViolation: has dependencies and cannot be deleted. 部屋を全部消してからでないと建物は壊せない
存在しないSGにルール追加 InvalidGroup.NotFound IDの打ち間違いや、別リージョンのSGを指している

エラー名の頭(InvalidSubnet / DependencyViolation)がそのまま原因を言っている。まずエラー名で当たりを付けるのが早い。

サブネットは256個ぶんでも251個しか使えない

10.0.1.0/24 は計算上256個のIPを含みますが、実際に使えるのは251個でした。

10.0.1.0/24 の AvailableIpAddressCount = 251

AWSが各サブネットの先頭4つと末尾1つ、計5個を予約しているためです(ネットワークアドレス、VPCルーター、DNS、将来用、ブロードキャスト)。小さいサブネットを切るときは、この5個ぶん少なく見積もる。/28(16個)だと使えるのは11個しかない。

CIDRの決め方。/16から/28まで

建物(VPC)の広さと部屋(サブネット)の広さは、CIDRの後ろの数字で決まります。数字が小さいほど広い。実測で、VPCに許される範囲は /16〜/28 でした。

create_vpc(CidrBlock="10.0.0.0/8")   → InvalidVpc.Range: The CIDR '10.0.0.0/8' is invalid.
create_vpc(CidrBlock="10.0.0.0/29")  → InvalidVpc.Range: The CIDR '10.0.0.0/29' is invalid.
CIDR 計算上のIP数 実際に使える数(実測) 用途の目安
/16 65,536 65,531 VPC本体。迷ったらこれ
/24 256 251 サブネット1部屋。入門はこれで足りる
/28 16 11 最小。踏み台や小さな検証用

使える数が5個少ないのは前の節の通りです。IPの頭は、社内ネットワークと被らないプライベート用の3系統(10.0.0.0/8172.16.0.0/12192.168.0.0/16)から選びます。デフォルトVPCが 172.31.0.0/16 を使っているので、自作は 10.0.0.0/16 にしておくと被りません。

サブネットはVPCの範囲の中から切り出すので、入れ子になります。10.0.0.0/16 の中に 10.0.1.0/2410.0.2.0/24、…と部屋を並べる形で、/16の中には/24が256部屋まで入ります。

デフォルトVPCの中身

AWSアカウントには最初からデフォルトVPCがあります。中身を取るとこうなっています(東京リージョン)。

VPC:      172.31.0.0/16  (IsDefault=True)
サブネット: ap-northeast-1a 172.31.0.0/20   MapPublicIpOnLaunch=True
          ap-northeast-1c 172.31.16.0/20  MapPublicIpOnLaunch=True
          ap-northeast-1d 172.31.32.0/20  MapPublicIpOnLaunch=True

部屋はAZごとに1つ、全部パブリック(起動したEC2に自動でパブリックIPが付く設定がON)で、案内板には外への行き先(0.0.0.0/0→IGW)が入っています。「EC2を立てたら何も設定していないのに外から繋がった」のはこれが理由です。逆に言うと、デフォルトVPCには「外から見えない部屋」が無いので、DBを置く練習には向きません。自分でVPCを作る意味はここにあります。

案内板は2種類ある。メインとサブネット用

VPCを作った瞬間に、案内板(ルートテーブル)は1枚だけ自動で付いてきます。これがメインルートテーブルで、中身は 10.0.0.0/16 -> local の1行だけ。どの案内板にも紐付けていないサブネットは、自動でこのメインを見ます。

create_vpc直後のルートテーブル: 1枚 (Main=True)  10.0.0.0/16 -> local

「使い方」の④で作ったのはサブネット用のルートテーブルで、それをパブリックにしたい部屋にだけ紐付けました。紐付けなかった部屋はメインを見続けるので、プライベートのままです。メインに0.0.0.0/0→IGWを書くと全部屋がパブリックになるので、メインは触らず、外に出したい部屋にだけ専用の案内板を付けるのが定石です。

プライベートの部屋から外に出る。NATゲートウェイ

外から届かない部屋(プライベート)のサーバーでも、パッケージの更新などで外に「出る」必要はあります。そのための出口がNATゲートウェイです。パブリックの部屋に置いて、プライベートの案内板を「0.0.0.0/0→NAT」にします。

# ⑥ Elastic IP(固定の公開IP)を1つ確保してNATゲートウェイに付ける。NATはパブリックの部屋に置く
eip = ec2.allocate_address(Domain="vpc")
nat = ec2.create_nat_gateway(SubnetId=sub, AllocationId=eip["AllocationId"])["NatGateway"]["NatGatewayId"]

# ⑦ プライベートの部屋用の案内板。「全部の外→NAT」
prv = ec2.create_subnet(VpcId=vpc, CidrBlock="10.0.2.0/24",
                        AvailabilityZone="ap-northeast-1a")["Subnet"]["SubnetId"]
prt = ec2.create_route_table(VpcId=vpc)["RouteTable"]["RouteTableId"]
ec2.create_route(RouteTableId=prt, DestinationCidrBlock="0.0.0.0/0", NatGatewayId=nat)
ec2.associate_route_table(RouteTableId=prt, SubnetId=prv)

できあがった2枚の案内板を並べると、違いは行き先の1語だけです。

パブリックの案内板:   10.0.0.0/16 -> local,  0.0.0.0/0 -> igw-xxxx
プライベートの案内板: 10.0.0.0/16 -> local,  0.0.0.0/0 -> nat-xxxx

矢印の向きに注意してください。IGWは双方向(外から入れるし、中から出られる)、NATは中から外への一方通行(外から中には入れない)。この違いが「DBは外から見えないが、DB自身はアップデートを取りに行ける」を作っています。NATゲートウェイは時間課金で、作ったまま忘れると月数千円かかります。検証が終わったら消す。

セキュリティグループの後ろにもう1枚。ネットワークACL

部屋のドアの警備員(SG)とは別に、部屋の入口にネットワークACLという門番がいます。作ったVPCの既定のACLを取ると、全部通す設定です。

既定のネットワークACL
  入ってくる: 100 allow 0.0.0.0/0 / 32767 deny 0.0.0.0/0
  出ていく:   100 allow 0.0.0.0/0 / 32767 deny 0.0.0.0/0

番号の小さい順に評価して、100番で全部許可、最後の32767番(触れない既定行)で全部拒否。つまり既定では素通しで、SGだけが効いている状態です。SGとの違いは3つ。

セキュリティグループ ネットワークACL
効く単位 サーバー(ENI)ごと サブネットごと
書くもの 許可だけ 許可と拒否の両方
戻りの通信 自動で通る(ステートフル) 戻りも書く必要がある(ステートレス)

入門の範囲ではACLは触らず、SGだけで組みます。「特定のIPをサブネット丸ごと締め出したい」が出てきたときに、ACLの拒否行を思い出してください。

外と繋ぐ部品の一覧

VPCの外と繋ぐ部品は他にもあります。入門で使うのは上2つだけです。

部品 繋ぐ相手 向き 料金
インターネットゲートウェイ インターネット 双方向 無料
NATゲートウェイ インターネット 中→外のみ 時間+データ量
VPCエンドポイント S3やDynamoDBなどAWSのサービス 中→サービス(インターネットを通らない) ゲートウェイ型(S3/DynamoDB)は無料
VPCピアリング 別のVPC 双方向 データ転送量
VPN / Direct Connect 会社のネットワーク 双方向 時間+転送量

VPCエンドポイントだけ補足すると、プライベートの部屋からS3を読みたいとき、NATを経由してインターネット越しに行くより、エンドポイントでAWS内を直接通した方が速くて安い。S3とDynamoDBのゲートウェイ型は無料なので、NATを立てる前にこれで足りないか確認する価値があります。

似た概念との使い分け

迷うところ 答え
セキュリティグループとネットワークACL SGはサーバー単位の警備員で、通したいものだけ書く(戻りの通信は自動で通る)。ネットワークACLはサブネット単位の門番で、許可と拒否を両方書く。最初はSGだけで足りる
パブリックとプライベート、どっちに置く 外から直接アクセスされるもの(Webサーバー、ロードバランサ)はパブリック。それ以外(DB、内部処理)はプライベート
プライベートの中から外に出たいとき NATゲートウェイをパブリック側に置いて、プライベート側の案内板を「0.0.0.0/0→NAT」にする。NATは有料
VPCは何個作る 最初は1つで十分。環境(本番/検証)を分けたくなったら分ける

料金の考え方

VPC・サブネット・ルートテーブル・IGW・SGは無料です。料金がかかるのは、中に置くEC2などのリソースと、NATゲートウェイ(時間課金+データ量課金)、VPN接続、VPCピアリングのデータ転送などです。「VPCを作ったら課金される」ことはありません。初心者がVPC周りで請求を食らう典型はNATゲートウェイの消し忘れなので、そこだけ覚えておいてください。

よくある注意点

  • デフォルトVPCがある。 AWSアカウントには最初からデフォルトVPCが1つ用意されていて、何も指定せずEC2を立てるとそこに入ります。学習用途ならそれで動きますが、中身を理解するには自分でVPCを1つ作ってみるのが早いです
  • サブネットはアベイラビリティゾーンをまたげない。 冗長化するなら、別のAZにもう1つサブネットを作ります
  • IGWを付けただけでは外に出られない。 案内板(ルートテーブル)に0.0.0.0/0→IGWの行を足して、それをサブネットに紐付けるまでがセットです
  • 消す順番は作った逆。 NATゲートウェイ→Elastic IPの解放→SG→ルート→IGWのデタッチ→サブネット→VPC。NATは消えるまで数十秒かかり、消える前にEIPを解放しようとすると失敗します。順番を間違えるとDependencyViolationで止まります

まとめ

冒頭の2つの症状に戻ります。

  • 「起動しているのに外からアクセスできない」→ ルートテーブルにIGW向けの行があるか、SGにそのポートの許可があるか。この2つで大半は決まります
  • 「サブネットが何なのか分からない」→ VPCの中の部屋で、パブリックかプライベートかは案内板(ルートテーブル)の1行で決まる。部屋自体に種類はない

覚えるのは5部品(VPC・サブネット・IGW・ルートテーブル・SG)の関係だけです。上の図に全部入っています。プライベートの部屋から外に出たくなったらNATゲートウェイ、S3に行くだけならVPCエンドポイント、を足します。

次回はLambda(サーバーレス)を予定しています。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?