VPCピアリング接続の設定:同一アカウント・同一リージョンの2つのVPCをプライベートIPで通信させる

同一AWSアカウント・同一リージョンに2つのVPCがあり、EC2インスタンス間をプライベートIPで通信させたい場面は頻繁に起きる。マイクロサービスの分割、共有サービスVPCとの接続、レガシーVPCからの段階移行など、理由は様々だ。VPCピアリングはその最もシンプルな解決策だが、接続リクエストの承認とルートテーブルの更新という2段階の操作を両方のVPCに対して行わないと通信は一切成立しない。片方だけ設定して「なぜ繋がらないのか」と悩むケースが多い。

TL;DR:VPCピアリング設定の全体像

ステップ操作対象内容
1VPC-A(リクエスター)ピアリング接続リクエストを作成
2VPC-B(アクセプター)ピアリング接続リクエストを承認
3VPC-AのルートテーブルVPC-BのCIDRへのルートを追加
4VPC-BのルートテーブルVPC-AのCIDRへのルートを追加
5両VPCのセキュリティグループ相手VPCのCIDRからのインバウンドを許可

VPCピアリングの仕組みを理解する

VPCピアリングは、2つのVPC間にAWSのバックボーンネットワークを経由したプライベートルーティングパスを確立する機能だ。インターネットゲートウェイ、VPNゲートウェイ、NAT装置は一切介在しない。トラフィックはAWSネットワーク内に留まる。

重要な制約として、VPCピアリングは推移的ルーティング(Transitive Routing)をサポートしない。VPC-AがVPC-Bとピアリングし、VPC-BがVPC-Cとピアリングしていても、VPC-AからVPC-Cへは直接通信できない。A-C間の通信が必要なら、別途A-C間のピアリングが必要になる。

また、ピアリングするVPC同士のCIDRブロックが重複していると接続は作成できない。事前にCIDRの重複がないことを確認すること。

graph LR A["VPC-A 10.0.0.0/16"] -->|"1. ピアリングリクエスト作成"| PCX["VPCピアリング接続 pcx-0123456789abcdef0"] PCX -->|"2. 承認 → active"| B["VPC-B 10.1.0.0/16"] A -->|"3. ルートテーブル更新 10.1.0.0/16 → pcx"| RTA["VPC-Aの ルートテーブル"] B -->|"4. ルートテーブル更新 10.0.0.0/16 → pcx"| RTB["VPC-Bの ルートテーブル"] A -->|"5. SGでCIDR許可"| SGA["VPC-Aの セキュリティグループ"] B -->|"5. SGでCIDR許可"| SGB["VPC-Bの セキュリティグループ"]
  1. ピアリング接続リクエスト: VPC-A(リクエスター)がVPC-Bに対して接続リクエストを送信する。
  2. 承認: VPC-B(アクセプター)がリクエストを明示的に承認することで接続が確立される。
  3. ルートテーブル更新: 両VPCのルートテーブルに相手のCIDRへのルートを追加する。この操作は自動では行われない。
  4. セキュリティグループ: ルートが通っていてもセキュリティグループが許可していなければパケットは届かない。両側の設定が必要。

VPCピアリングの設定手順

以下の例では次の構成を前提とする。AWS CLIのプロファイルや環境変数(AWS_DEFAULT_REGION)で対象リージョンを事前に設定しておくこと。

  • VPC-A: vpc-0a1b2c3d4e5f67890、CIDRブロック 10.0.0.0/16
  • VPC-B: vpc-0f9e8d7c6b5a43210、CIDRブロック 10.1.0.0/16

ステップ1:ピアリング接続リクエストを作成する

VPC-Aからリクエストを送信する。同一アカウント・同一リージョンの場合、--peer-owner-id--peer-regionは自アカウントIDと現在のリージョンを指定する。

aws ec2 create-vpc-peering-connection \
  --vpc-id vpc-0a1b2c3d4e5f67890 \
  --peer-vpc-id vpc-0f9e8d7c6b5a43210 \
  --peer-owner-id 123456789012

コマンドの出力から VpcPeeringConnectionId(例:pcx-0123456789abcdef0)を控えておく。以降のステップで使用する。

ステップ2:ピアリング接続リクエストを承認する

リクエストが送信されただけでは接続は確立されない。アクセプター側(ここでは同一アカウントなので同じ操作者)が明示的に承認する必要がある。承認しないと接続は pending-acceptance 状態のままになる。

aws ec2 accept-vpc-peering-connection \
  --vpc-peering-connection-id pcx-0123456789abcdef0

承認後、接続ステータスが active になったことを確認する。

aws ec2 describe-vpc-peering-connections \
  --vpc-peering-connection-ids pcx-0123456789abcdef0 \
  --query 'VpcPeeringConnections[0].Status.Code' \
  --output text

active が返れば接続レイヤーは完成だ。ただし、この時点ではまだトラフィックは流れない。

ステップ3:VPC-Aのルートテーブルを更新する

ピアリング接続が active になっても、ルートテーブルの更新は自動では行われない。これを忘れると「接続はあるのに通信できない」という状況になる。VPC-Aのルートテーブルに、VPC-BのCIDR(10.1.0.0/16)へのルートを追加する。

まずVPC-Aに関連付けられているルートテーブルIDを確認する。

aws ec2 describe-route-tables \
  --filters 'Name=vpc-id,Values=vpc-0a1b2c3d4e5f67890' \
  --query 'RouteTables[*].{RouteTableId:RouteTableId,Associations:Associations[*].SubnetId}' \
  --output table

対象のルートテーブルID(例:rtb-0aaabbbccc1112223)を確認したら、ルートを追加する。

aws ec2 create-route \
  --route-table-id rtb-0aaabbbccc1112223 \
  --destination-cidr-block 10.1.0.0/16 \
  --vpc-peering-connection-id pcx-0123456789abcdef0

ステップ4:VPC-Bのルートテーブルを更新する

ルーティングは双方向に設定する必要がある。VPC-Aにルートを追加しただけでは、戻りのパケットがVPC-Bから出ていかない。VPC-Bのルートテーブルに、VPC-AのCIDR(10.0.0.0/16)へのルートを追加する。

aws ec2 describe-route-tables \
  --filters 'Name=vpc-id,Values=vpc-0f9e8d7c6b5a43210' \
  --query 'RouteTables[*].{RouteTableId:RouteTableId,Associations:Associations[*].SubnetId}' \
  --output table
aws ec2 create-route \
  --route-table-id rtb-0dddeeefff4445556 \
  --destination-cidr-block 10.0.0.0/16 \
  --vpc-peering-connection-id pcx-0123456789abcdef0

ステップ5:セキュリティグループでトラフィックを許可する

ルートが正しく設定されていても、セキュリティグループがインバウンドトラフィックを拒否していれば通信は届かない。VPC-B上のEC2インスタンスのセキュリティグループに、VPC-AのCIDRからのアクセスを許可するルールを追加する。以下はTCPポート8080を許可する例だ。

aws ec2 authorize-security-group-ingress \
  --group-id sg-0bbbbbbbbbbbbbbbb \
  --protocol tcp \
  --port 8080 \
  --cidr 10.0.0.0/16

VPC-Aのインスタンスに対しても、VPC-BのCIDRからの応答トラフィックが必要な場合は同様に設定する。セキュリティグループはステートフルなので、アウトバウンドルールがデフォルト(全許可)のままであれば、戻りのトラフィックは自動的に許可される。

VPCピアリング設定の確認と疎通テスト

設定が完了したら、実際に通信できるかを確認する。EC2インスタンスにSSHまたはSystems Manager Session Managerで接続し、相手VPCのインスタンスのプライベートIPに対してpingやcurlを実行するのが最も直接的な確認方法だ。

ルートテーブルの設定が正しく反映されているかをCLIで確認する場合は以下を使う。

aws ec2 describe-route-tables \
  --route-table-ids rtb-0aaabbbccc1112223 \
  --query 'RouteTables[0].Routes[?VpcPeeringConnectionId==`pcx-0123456789abcdef0`]'
stateDiagram-v2 [*] --> pending_acceptance : create-vpc-peering-connection pending_acceptance --> active : accept-vpc-peering-connection active --> ルートテーブル更新済み : create-route(両VPC) ルートテーブル更新済み --> 通信可能 : セキュリティグループ許可 pending_acceptance --> deleted : リクエスト拒否 or 期限切れ active --> deleted : 接続削除
  1. ピアリング接続リクエスト作成: VPC-Aがリクエストを送信し、pending-acceptance 状態になる。
  2. 承認: 承認操作により active 状態に遷移する。
  3. ルートテーブル更新: 両VPCのルートテーブルにピアリング接続経由のルートを追加する。
  4. セキュリティグループ設定: インバウンドルールを追加して初めてトラフィックが通過できる。

よくある失敗パターン:「接続はactiveなのに通信できない」

本番環境でVPCピアリングを設定した際に最もよく遭遇するのが、接続ステータスは active なのにEC2インスタンス間の通信が一切届かないケースだ。

症状: ping 10.1.0.5 がタイムアウトし続ける。VPCフローログには送信パケットが記録されているが、相手側に届いていない。

最初の誤診: セキュリティグループの設定を疑い、ICMPを全許可にしても変化なし。

実際の原因: VPC-Bのルートテーブルに 10.0.0.0/16 へのルートが追加されていなかった。VPC-Aからのパケットは届いているが、VPC-Bのインスタンスが応答を返す際にデフォルトゲートウェイ(インターネットゲートウェイ)にルーティングしようとして失敗していた。

確認方法: VPC-Bのルートテーブルを確認する。

aws ec2 describe-route-tables \
  --filters 'Name=vpc-id,Values=vpc-0f9e8d7c6b5a43210' \
  --query 'RouteTables[*].Routes' \
  --output table

出力に 10.0.0.0/16 向けのルートがなければ、それが原因だ。ルーティングは必ず双方向で設定する。

VPCピアリングは「ケーブルを繋いだだけ」の状態に近い。ルートテーブルの更新は、そのケーブルを使うための「経路表への記載」に相当する。ケーブルが繋がっていても経路表に載っていなければパケットは迷子になる。

IAM権限:VPCピアリング設定に必要な最小権限

VPCピアリングの作成・承認・ルートテーブル更新を行うIAMポリシーの例を示す。最小権限の原則に従い、必要な操作のみを許可する。

🔽 IAMポリシー例(クリックして展開)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateVpcPeeringConnection",
        "ec2:AcceptVpcPeeringConnection",
        "ec2:DescribeVpcPeeringConnections",
        "ec2:DescribeVpcs",
        "ec2:DescribeRouteTables",
        "ec2:CreateRoute",
        "ec2:DeleteRoute",
        "ec2:AuthorizeSecurityGroupIngress",
        "ec2:DescribeSecurityGroups"
      ],
      "Resource": "*"
    }
  ]
}

ec2:CreateRouteec2:DescribeRouteTables などのアクションはリソースレベルの制限をサポートしていないか、制限の粒度が限られる場合がある。AWS Service Authorization Referenceで各アクションのリソースレベルサポートを確認すること。

VPCピアリング設定のまとめと次のステップ

VPCピアリングによるプライベートIP通信の設定は、接続リクエストの作成と承認、そして両VPCのルートテーブル更新とセキュリティグループ設定という5つのステップで完結する。最も見落としやすいのはルートテーブルの双方向設定だ。片方のVPCにしかルートを追加していないと、接続は active でも通信は成立しない。

複数のVPCを相互接続する場合や、推移的ルーティングが必要な場合は、VPCピアリングではなくAWS Transit Gatewayの使用を検討すること。Transit Gatewayはハブアンドスポーク型のルーティングをサポートし、多数のVPCを管理する際のルートテーブル管理コストを大幅に削減できる。

用語集

用語説明
VPCピアリング接続2つのVPC間でプライベートIPトラフィックをルーティングするためのネットワーク接続。AWSバックボーンを経由し、インターネットを経由しない。
リクエスター / アクセプターピアリング接続を開始するVPCがリクエスター、承認するVPCがアクセプター。同一アカウントの場合は同一の操作者が両方の役割を担う。
推移的ルーティングA→B→Cという経路でBを中継してAとCが通信する形式。VPCピアリングはこれをサポートしない。
CIDRブロックVPCに割り当てられたIPアドレス範囲。ピアリングするVPC同士でCIDRが重複していると接続できない。
VPCフローログVPCのネットワークインターフェースを通過するIPトラフィックの情報をキャプチャする機能。疎通確認やトラブルシューティングに有用。

コメント

このブログの人気の投稿

EC2 SSH接続タイムアウトの原因と修正方法 — セキュリティグループのインバウンドルール完全ガイド

S3パブリックアクセス拒否の原因と解決策:バケットレベルの「Block Public Access」が優先される仕組み

EC2インスタンスIDをメタデータから取得する方法 — IMDSv2が安全な理由