Setting Up AWS VPC Peering with Terraform


Introduction

AWS VPC Peering is a feature that allows you to connect one VPC to another in a private and low-latency manner. It can be established across different VPCs within the same AWS account, or even between VPCs in different AWS accounts and regions.

In this article, we’ll guide you on how to set up VPC Peering using Terraform, a popular Infrastructure as Code tool.

What is AWS VPC Peering?

VPC Peering enables a direct network connection between two VPCs, allowing them to communicate as if they are in the same network. Some of its characteristics include:

  • Direct Connection: No intermediary gateways or VPNs.
  • Non-transitive: Direct peering only between the two connected VPCs.
  • Same or Different AWS Accounts: Can be set up within the same account or across different accounts.
  • Cross-region: VPCs in different regions can be peered.

A basic rundown of how AWS VPC Peering works:

  • Setup: You can create a VPC peering connection by specifying the source VPC (requester) and the target VPC (accepter).
  • Connection: Once the peering connection is requested, the owner of the target VPC must accept the peering request for the connection to be established.
  • Routing: After the connection is established, you must update the route tables of each VPC to ensure that traffic can flow between them. You specify the CIDR block of the peered VPC as the destination and the peering connection as the target.
  • Direct Connection: It’s essential to understand that VPC Peering is a direct network connection. There’s no intermediary gateway, no VPN, and no separate network appliances required. It’s a straightforward, direct connection between two VPCs.
  • Non-transitive: VPC Peering is non-transitive. This means that if VPC A is peered with VPC B, and VPC B is peered with VPC C, VPC A will not be able to communicate with VPC C unless there is a direct peering connection between them.
  • Limitations: It’s worth noting that there are some limitations. For example, you cannot have overlapping CIDR blocks between peered VPCs.
  • Cross-region Peering: Originally, VPC Peering was only available within the same AWS region. However, AWS later introduced the ability to establish peering connections between VPCs in different regions, which is known as cross-region VPC Peering.
  • Use Cases:
    • Shared Services: A common pattern is to have a centralized VPC containing shared services (e.g., logging, monitoring, security tools) that other VPCs can access.
    • Data Replication: For databases or other systems that require data replication across regions.
    • Migration: If you’re migrating resources from one VPC to another, perhaps as part of an AWS account consolidation.

Terraform Implementation

Terraform provides a declarative way to define infrastructure components and their relationships. Let’s look at how we can define AWS VPC Peering using Terraform.

The folder organization would look like:

terraform-vpc-peering/
│
├── main.tf              # Contains the AWS provider and VPC Peering module definition.
│
├── variables.tf         # Contains variable definitions at the root level.
│
├── outputs.tf           # Outputs from the root level, mainly the peering connection ID.
│
└── vpc_peering_module/  # A folder/module dedicated to VPC peering-related resources.
    │
    ├── main.tf          # Contains the resources related to VPC peering.
    │
    ├── outputs.tf       # Outputs specific to the VPC Peering module.
    │
    └── variables.tf     # Contains variable definitions specific to the VPC peering module.

This structure allows for a clear separation between the main configuration and the module-specific configurations. If you decide to use more modules in the future or want to reuse the vpc_peering_module elsewhere, this organization makes it convenient.

Always ensure you run terraform init in the root directory (terraform-vpc-peering/ in this case) before executing any other Terraform commands, as it will initialize the directory and download necessary providers.

1. main.tf:

provider "aws" {
  region = var.aws_region
}

module "vpc_peering" {
  source   = "./vpc_peering_module"
  
  requester_vpc_id = var.requester_vpc_id
  peer_vpc_id      = var.peer_vpc_id
  requester_vpc_rt_id = var.requester_vpc_rt_id
  peer_vpc_rt_id      = var.peer_vpc_rt_id
  requester_vpc_cidr  = var.requester_vpc_cidr
  peer_vpc_cidr       = var.peer_vpc_cidr

  tags = {
    Name = "MyVPCPeeringConnection"
  }
}

2. variables.tf:

variable "aws_region" {
  description = "AWS region"
  default     = "us-west-1"
}

variable "requester_vpc_id" {
  description = "Requester VPC ID"
}

variable "peer_vpc_id" {
  description = "Peer VPC ID"
}

variable "requester_vpc_rt_id" {
  description = "Route table ID for the requester VPC"
}

variable "peer_vpc_rt_id" {
  description = "Route table ID for the peer VPC"
}

variable "requester_vpc_cidr" {
  description = "CIDR block for the requester VPC"
}

variable "peer_vpc_cidr" {
  description = "CIDR block for the peer VPC"
}

3. outputs.tf:

output "peering_connection_id" {
  description = "The ID of the VPC Peering Connection"
  value       = module.vpc_peering.connection_id
}

4. vpc_peering_module/main.tf:

resource "aws_vpc_peering_connection" "example" {
  peer_vpc_id = var.peer_vpc_id
  vpc_id      = var.requester_vpc_id
  auto_accept = true

  tags = var.tags
}

resource "aws_route" "requester_route" {
  route_table_id             = var.requester_vpc_rt_id
  destination_cidr_block     = var.peer_vpc_cidr
  vpc_peering_connection_id  = aws_vpc_peering_connection.example.id
}

resource "aws_route" "peer_route" {
  route_table_id             = var.peer_vpc_rt_id
  destination_cidr_block     = var.requester_vpc_cidr
  vpc_peering_connection_id  = aws_vpc_peering_connection.example.id
}

5. vpc_peering_module/outputs.tf:

output "peering_connection_id" {
  description = "The ID of the VPC Peering Connection"
  value       = module.vpc_peering.connection_id
}

6. vpc_peering_module/variables.tf:

variable "requester_vpc_id" {}
variable "peer_vpc_id" {}
variable "requester_vpc_rt_id" {}
variable "peer_vpc_rt_id" {}
variable "requester_vpc_cidr" {}
variable "peer_vpc_cidr" {}
variable "tags" {
  type    = map(string)
  default = {}
}

Conclusion

VPC Peering is a powerful feature in AWS for private networking across VPCs. With Terraform, the setup, management, and scaling of such infrastructure become a lot more streamlined and manageable. Adopting Infrastructure as Code practices, like those offered by Terraform, not only ensures repeatability but also versioning, collaboration, and automation for your cloud infrastructure.

References:

What is VPC peering?

,