Navigating Terraform for VPC peering across multiple CIDRs and regions can be daunting at first, but with a structured approach, it becomes manageable:
#accepter
variable "accepter_vpc_id" {
default = "vpc-xxx"
}
variable "accepter_region" {
default = "xxx"
}
#requester
variable "requester_vpc_id" {
default = "xxx"
}
variable "requester_region" {
default = "xx"
}
#### providers ####
#requester
provider "aws" {
alias = "requester"
region = var.requester_region
}
provider "aws" {
alias = "peer"
region = var.requester_region
}
## accepter
provider "aws" {
alias = "accepter"
region = var.accepter_region
}
data "aws_vpc" "accepter" {
id = var.accepter_vpc_id
provider = aws.accepter
}
Typically, we filter routes, but I’m adjusting the data for experimentation. If you need all routes, feel free to remove the filters. My routes are tagged as private and local, so I’m filtering them accordingly.
data "aws_route_tables" "accepter_local_routes" {
vpc_id = var.accepter_vpc_id
provider = aws.accepter
filter {
name = "tag:Name"
values = ["*local*"]
}
}
data "aws_route_tables" "accepter_priv_routes" {
vpc_id = var.accepter_vpc_id
provider = aws.accepter
filter {
name = "tag:Name"
values = ["*priv*"]
}
}
data "aws_vpc" "requester" {
id = var.requester_vpc_id
provider = aws.requester
}
data "aws_route_tables" "requester_local_routes" {
vpc_id = var.requester_vpc_id
provider = aws.requester
filter {
name = "tag:Name"
values = ["*local*"]
}
}
data "aws_route_tables" "requester_priv_routes" {
vpc_id = var.requester_vpc_id
provider = aws.requester
filter {
name = "tag:Name"
values = ["*priv*"]
}
}
#### peering configuration ####
data "aws_availability_zones" "available" {
provider = aws.peer
}
resource "aws_vpc_peering_connection" "this" {
vpc_id = var.requester_vpc_id
peer_vpc_id = var.accepter_vpc_id
peer_region = var.accepter_region
auto_accept = false
provider = aws.peer
}
resource "aws_vpc_peering_connection_accepter" "this" {
provider = aws.accepter
vpc_peering_connection_id = aws_vpc_peering_connection.this.id
auto_accept = true
}
resource "aws_vpc_peering_connection_options" "this" {
vpc_peering_connection_id = aws_vpc_peering_connection.this.id
accepter {
allow_remote_vpc_dns_resolution = true
}
provider = aws.accepter
}
locals {
accepter_cidr_block = data.aws_vpc.accepter.cidr_block_associations[*].cidr_block
requester_cidr_block = data.aws_vpc.requester.cidr_block_associations[*].cidr_block
routes_requester_local_cidrblocks = setproduct(data.aws_route_tables.requester_local_routes.ids,local.accepter_cidr_block)
routes_requester_priv_cidrblocks = setproduct(data.aws_route_tables.requester_priv_routes.ids,local.accepter_cidr_block)
routes_accepter_local_cidrblocks = setproduct(data.aws_route_tables.accepter_local_routes.ids,local.requester_cidr_block)
routes_accepter_priv_cidrblocks = setproduct(data.aws_route_tables.accepter_priv_routes.ids,local.requester_cidr_block)
}
#### route tables ####
resource "aws_route" "requester_local_routes" {
count = length(local.routes_requester_local_cidrblocks)
route_table_id = local.routes_requester_local_cidrblocks[count.index][0]
destination_cidr_block = local.routes_requester_local_cidrblocks[count.index][1]
vpc_peering_connection_id = aws_vpc_peering_connection.this.id
provider = aws.peer
}
resource "aws_route" "requester_priv_routes" {
count = length(local.routes_requester_priv_cidrblocks)
route_table_id = local.routes_requester_priv_cidrblocks[count.index][0]
destination_cidr_block = local.routes_requester_priv_cidrblocks[count.index][1]
vpc_peering_connection_id = aws_vpc_peering_connection.this.id
provider = aws.peer
}
resource "aws_route" "accepter_local_routes" {
count = length(local.routes_accepter_local_cidrblocks)
route_table_id = local.routes_accepter_local_cidrblocks[count.index][0]
destination_cidr_block = local.routes_accepter_local_cidrblocks[count.index][1]
vpc_peering_connection_id = aws_vpc_peering_connection.this.id
provider = aws.accepter
}
resource "aws_route" "accepter_priv_routes" {
count = length(local.routes_accepter_priv_cidrblocks)
route_table_id = local.routes_accepter_priv_cidrblocks[count.index][0]
destination_cidr_block = local.routes_accepter_priv_cidrblocks[count.index][1]
vpc_peering_connection_id = aws_vpc_peering_connection.this.id
provider = aws.accepter
}
terraform init
terraform fmt
terraform plan
terraform apply