
別のAWSアカウント間でVPCピアリングを、Terraformを使ってやってみました。
目次
構成
こんな感じの構成を作ってみます。

TerraformにおけるVPCピアリング
VPCピアリングでは、
- リクエスタ(ピアリング接続を依頼する側)
- アクセプタ(ピアリング接続の依頼を承諾する側)
という形で、ピアリング接続の依頼・承諾というプロセスを踏むことで、接続がアクティブになります。
TerraformでVPCピアリングを行う場合、"aws_vpc_peering_connection" を使います。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection
"aws_vpc_peering_connection" には "auto_accept" という、アクセプタ側で自動的に承諾許可を行うオプションがありますが、クロスアカウントの場合は使えないようです。よって、リクエスタ側のTerraformでピアリングを作成し、アクセプタ側はマネジメントコンソール(もしくはaws-cli)で手動で許可してあげることになります。
Terraformは以下のレポジトリに用意しました(そこまで作り込んでないので適宜設定が必要かもです)。
フォルダ構成はこんな感じです。
cross-account-vpc-peering
├── README.md
├── envs/
│ ├── accepter/
│ │ ├── backend.tf
│ │ ├── main.tf
│ │ └── variables.tf
│ └── requester/
│ ├── backend.tf
│ ├── main.tf
│ └── variables.tf
└── modules/
├── security-groups/
│ └── main.tf
├── ssm/
│ └── main.tf
└── vpc/
└── main.tf
モジュールを使って、リクエスタ・アクセプタともにVPC周りはほぼ同じものができます。
リクエスタ側にだけ、VPCピアリングの設定が入ってます。
envs/requester/variables.tf で アクセプタ側のアカウントID、VPCのCIDR、VPC IDを指定します。
variable "accepter_account" {
default = "123456789012"
}
variable "accepter_vpc_id" {
default = "vpc-12345678901234567"
}
上記を使って、main.tf で VPCピアリングコネクションの作成とルーティングの設定です。サンプルなのでここだけはモジュール使わずベタに書いてます。
resource "aws_vpc_peering_connection" "peer" {
peer_owner_id = var.accepter_account
peer_vpc_id = var.accepter_vpc_id
vpc_id = module.vpc.vpc_id
tags = {
Name = "vpc-peering-to-accepter"
}
}
resource "aws_route" "route_vpc_peering" {
route_table_id = module.vpc.private_route_table_id
destination_cidr_block = var.accepter_vpc_cidr
vpc_peering_connection_id = aws_vpc_peering_connection.peer.id
depends_on = [aws_vpc_peering_connection.peer]
}
aws_vpc_peering_connectionではピアリング先のアカウントIDとVPC ID、自身のVPC IDを設定するだけです。とてもかんたんですね。
では流してみましょう。VPCピアリングの承諾プロセスの関係上、アクセプタ側が先にできている必要があります。
$ cd envs/accepter
$ terraform init
$ terraform plan
$ terraform apply
アクセプタ側のVPC IDを確認します。

リクエスタ側のvariabls.tfのVPC IDを変更しておきます。ではリクエスタもterraform applyしましょう。
$ cd envs/requester
$ terraform init
$ terraform plan
$ terraform apply
ただし、この時点ではVPCピアリングはまだアクティブになっていません。アクセプタ側が承諾をする必要があるためですね。
リクエスタ側のマネジメントコンソールを見てみましょう。VPCの「ピアリング接続」を開きます。

「承諾の保留中」になっています。
では、アクセプタ側で承諾しましょう。同じようにVPCの「ピアリング接続」を開きます。こちらも「承諾の保留中」になっていますので、「アクション」をクリックします。

「リクエストの承諾」をクリックします。
確認画面が出るので「はい、承諾する」をクリックします。

ピアリングができました。では戻りのルーティングを設定しましょう。「ルートテーブルを今すぐ変更」をクリック。

今回の構成では、パブリックサブネットとプライベートサブネット、それぞれにルートテーブルを用意してます。VPCピアリングでつなぐのはプライベートサブネットのみとする想定なので、プライベートサブネットのルートテーブルに、リクエスタVPCのCIDRへはVPCピアリングを使うようにルーティングを設定します。

これでアクセプタ側はOKです。リクエスタ側のマネジメントコンソールに戻って、VPCピアリングの画面を見てみましょう。

こちらもアクティブになっていますね。リクエスタ側ではTerraformでVPCピアリングを使ったルーティングも設定してありますのでこれでOKです。
あとはEC2インスタンスをそれぞれに立ててping疎通などで確認してみてください。
- accepter/requester-VPCのプライベートサブネットに配置します。
- セッションマネージャが使えるようにエンドポイントを作成してあります。AmazonSSMRoleForInstancesQuickSetupなどのIAMロールを割り当ててください。
- セキュリティグループもaccepter/requester-private-sgを用意して、お互いにICMPを通すようにしています。
まとめ
TerraformのVPCピアリングはとても簡単です。同じアカウント内のVPCピアリングなら、アクセプタ側で"aws_vpc_peering_connection_accepter"を使って承諾プロセスの部分もコード化できるので、マネジメントコンソールが不要になります。
ただ、ピアリング先が常に自前だとは限らないですし、Organizationsの場合などアカウントが異なる場合は結局承諾プロセスが必要になるようなので、ベタなマネジメントコンソールでの承諾プロセスを知っておいてもいいのではないかと思います。