DEV Community

Cover image for AWS Networking with Terraform: VPC Peering Connection between VPCs
Chinmay Tonape
Chinmay Tonape

Posted on • Updated on

AWS Networking with Terraform: VPC Peering Connection between VPCs

In our previous post, we started learning AWS networking concepts, culminating in the creation of a bastion host to access private hosts securely.

Now, let's explore how to establish connectivity between two Virtual Private Clouds (VPCs) using VPC peering connections, leveraging Terraform modules for streamlined deployment.

A VPC peering connection is a networking connection between two VPCs that enables you to route traffic between them using private IPv4 addresses or IPv6 addresses. Instances in either VPC can communicate with each other as if they are within the same network. You can create a VPC peering connection between your own VPCs, or with a VPC in another AWS account. The VPCs can be in different Regions (also known as an inter-Region VPC peering connection).

Architecture Overview:

Before diving into implementation, let's grasp the architecture we're about to construct:

VPC Peering Diagram

Step 1: Create two VPCs with non-overlapping CIDRs.

Create vpc_a and vpc_b with non-overlapping cidrs. Please refer to my github repo in resources section below.

####################################################
# Create two VPC and components
####################################################

module "vpc_a" {
  source               = "./modules/vpc"
  name                 = "VPC-A"
  aws_region           = var.aws_region
  vpc_cidr_block       = var.vpc_cidr_block_a #"10.1.0.0/16"
  public_subnets_cidrs = [cidrsubnet(var.vpc_cidr_block_a, 8, 1)]
  enable_dns_hostnames = var.enable_dns_hostnames
  aws_azs              = var.aws_azs
  common_tags          = local.common_tags
  naming_prefix        = local.naming_prefix
}


module "vpc_b" {
  source               = "./modules/vpc"
  name                 = "VPC-B"
  aws_region           = var.aws_region
  vpc_cidr_block       = var.vpc_cidr_block_b #"10.2.0.0/16"
  public_subnets_cidrs = [cidrsubnet(var.vpc_cidr_block_b, 8, 1)]
  enable_dns_hostnames = var.enable_dns_hostnames
  aws_azs              = var.aws_azs
  common_tags          = local.common_tags
  naming_prefix        = local.naming_prefix
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Deploy EC2 instances within each VPC.

Create an EC2 instance in each VPC. Please refer to my github repo in resources section below.

####################################################
# Create EC2 Server Instances
####################################################

module "vpc_a_public_host" {
  source        = "./modules/web"
  instance_type = var.instance_type
  instance_key  = var.instance_key
  subnet_id     = module.vpc_a.public_subnets[0]
  vpc_id        = module.vpc_a.vpc_id
  ec2_name      = "Public Host A"
  common_tags   = local.common_tags
  naming_prefix = local.naming_prefix
}

module "vpc_b_public_host" {
  source        = "./modules/web"
  instance_type = var.instance_type
  instance_key  = var.instance_key
  subnet_id     = module.vpc_b.public_subnets[0]
  vpc_id        = module.vpc_b.vpc_id
  ec2_name      = "Public Host B"
  common_tags   = local.common_tags
  naming_prefix = local.naming_prefix
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Establish a peering connection to enable communication between the two VPCs.

Create a VPC peering connection and add a route in route table of each VPC.

####################################################
# Create VPC Peering Connection
####################################################
resource "aws_vpc_peering_connection" "vpc_to_vpc" {
  vpc_id      = module.vpc_a.vpc_id
  peer_vpc_id = module.vpc_b.vpc_id
  auto_accept = true
  tags = merge(local.common_tags, {
    Name = "${local.naming_prefix}-vpc-peering"
  })
}

resource "aws_route" "peering_routes_a" {
  route_table_id            = module.vpc_a.public_route_table_id
  destination_cidr_block    = var.vpc_cidr_block_b
  vpc_peering_connection_id = aws_vpc_peering_connection.vpc_to_vpc.id
}

resource "aws_route" "peering_routes_b" {
  route_table_id            = module.vpc_b.public_route_table_id
  destination_cidr_block    = var.vpc_cidr_block_a
  vpc_peering_connection_id = aws_vpc_peering_connection.vpc_to_vpc.id
}
Enter fullscreen mode Exit fullscreen mode

Steps to Run Terraform

Follow these steps to execute the Terraform configuration:

terraform init
terraform plan 
terraform apply -auto-approve
Enter fullscreen mode Exit fullscreen mode

Upon successful completion, Terraform will provide relevant outputs.

Apply complete! Resources: 17 added, 0 changed, 0 destroyed.

Outputs:

vpc_a_public_host_IP = "18.212.2.189"
vpc_b_public_host_IP = "3.84.14.236"
Enter fullscreen mode Exit fullscreen mode

Testing the outcome

VPCs Created with exclusive CIDRs
VPCs

Peering connections with route tables
VPC Peering Connection

Route Tables showing rote to peering connection:

Rote Table A

Route Table B

Connecting to EC2 in VPC-B from VPC-A
VPC A to B

Connecting to EC2 in VPC-A from VPC-B
VPC B to A

Cleanup:

Remember to stop AWS components to avoid large bills.

terraform destroy -auto-approve
Enter fullscreen mode Exit fullscreen mode

In our upcoming module, we'll dive deeper into AWS networking, extending our setup to establish transit gateway VPC connections.

Resources:

Github Link: https://github.com/chinmayto/terraform-aws-networking-vpc-peering
VPC Peering Documentation: https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html

Top comments (0)