Hi, Welcome to the first in the VPC Peering Series.
In this edition, you will learn how to create and peer VPCs together that are in the same region. This shows how to create VPC peering on AWS using terraform.
What is AWS VPC Peering?
Amazon Web Services (AWS) Virtual Private Cloud (VPC) peering is a networking feature that allows you to connect two VPCs together, enabling communication between them as if they were on the same network. VPC peering is a private and secure connection, which means traffic between the peered VPCs stays within the AWS network and does not traverse the public internet.
Requester VPC - This is the VPC from which we are initiating a request to establish a peering connection with another VPC.
Accepter VPC - This refers to the VPC that will receive and accept the peering request from the requester VPC.
Terraform Script
Terraform is an infrastructure as code (IaC) tool used to define and provision the creation of infrastructure resources.
- Provider.tf - This shows the specific provider used for this script and in this case we are using AWS.
provider "aws" {
access_key = var.access_key
secret_key = var.secret_key
region = var.region
}
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
- Vpc.tf - This shows the creation of the respective vpcs (Requester Vpc and Accepter Vpc) and the Vpc peering connection.
# Create VPC for Requester
resource "aws_vpc" "requester_vpc" {
cidr_block = var.vpc_cidr_block
# enable_dns_hostnames = true
tags = {
Name = "requester_vpc"
}
}
# Create VPC for Accepter
resource "aws_vpc" "accepter_vpc" {
cidr_block = var.peer_vpc_cidr_block
# enable_dns_hostnames = true
tags = {
Name = "accepter_vpc"
}
}
# Create VPC peering connection between both vpcs
resource "aws_vpc_peering_connection" "vpc_peering_connection" {
vpc_id = aws_vpc.requester_vpc.id
peer_vpc_id = aws_vpc.accepter_vpc.id
auto_accept = true
tags = {
Name = "peering_connection"
}
depends_on = [
aws_vpc.requester_vpc,
aws_vpc.accepter_vpc
]
}
# Create Internet Gateway for Requester
resource "aws_internet_gateway" "requester-igw" {
vpc_id = aws_vpc.requester_vpc.id
tags = {
Name = "requester-igw"
}
}
# Create Route Table for Requester
resource "aws_route_table" "route_table_requester" {
vpc_id = aws_vpc.requester_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.requester-igw.id
}
route {
cidr_block = "10.1.5.0/24"
vpc_peering_connection_id = aws_vpc_peering_connection.vpc_peering_connection.id
}
}
# Create Route Table for Accepter
resource "aws_route_table" "route_table_accepter" {
vpc_id = aws_vpc.accepter_vpc.id
route {
cidr_block = "10.0.5.0/24"
vpc_peering_connection_id = aws_vpc_peering_connection.vpc_peering_connection.id
}
}
# Data for availability Zones
data "aws_availability_zones" "availability_zones" {}
# Create Subnet for Requester
resource "aws_subnet" "subnet_requester" {
vpc_id = aws_vpc.requester_vpc.id
cidr_block = var.requester_subnet_cidr_block
map_public_ip_on_launch = true # This makes public subnet
availability_zone = data.aws_availability_zones.availability_zones.names[0]
tags = {
Name = "requester-subnet"
}
}
# Create Subnet for Accepter
resource "aws_subnet" "subnet_accepter" {
vpc_id = aws_vpc.accepter_vpc.id
cidr_block = var.accepter_subnet_cidr_block
map_public_ip_on_launch = false # This makes private subnet
availability_zone = data.aws_availability_zones.availability_zones.names[1]
tags = {
Name = "accepter-subnet"
}
}
# Associate Requester Subnet to Requester Route Table
resource "aws_route_table_association" "route_table_requester" {
subnet_id = aws_subnet.subnet_requester.id
route_table_id = aws_route_table.route_table_requester.id
}
# Associate Accepter Subnet to Accepter Route Table
resource "aws_route_table_association" "route_table_accepter" {
subnet_id = aws_subnet.subnet_accepter.id
route_table_id = aws_route_table.route_table_accepter.id
}
- Variables.tf - This shows the variables declared.
variable "access_key" {
description = "The Access Key"
default = [{}]
}
variable "secret_key" {
description = "The Secret Key"
default = [{}]
}
variable "region" {
type = string
default = "eu-west-1"
}
variable "vpc_cidr_block" {
description = "VPC Cidr Block"
default = "10.0.0.0/16"
}
variable "peer_vpc_cidr_block" {
description = "Peer VPC Cidr Block"
default = "10.1.0.0/16"
}
variable "requester_subnet_cidr_block" {
description = "Requester Subnet Cidr Block"
default = "10.0.5.0/24"
}
variable "accepter_subnet_cidr_block" {
description = "Accepter Subnet Cidr Block"
default = "10.1.5.0/24"
}
variable "instance_type" {
type = string
default = "t2.micro"
}
variable "ami_id" {
type = string
default = "ami-0136ddddd07f0584f"
}
variable "ami_key_pair_name" {
type = string
default = "peering" #key pair has been created in this case
}
- Security.tf - This shows how any EC2 instance created in the different vpcs communicate with each other. Security groups for both Requester Vpc and Accepter Vpc are created. Here we are testing the vpc peering created above.
# Create Security Group for EC2 Instance for Requester
resource "aws_security_group" "requester_security_group" {
name = "requester_security_group"
description = "requester security group"
vpc_id = aws_vpc.requester_vpc.id
# Allow inbound traffic from Accepter CIDR block
ingress {
from_port = 0
to_port = 65535
protocol = "tcp"
cidr_blocks = [aws_vpc.accepter_vpc.cidr_block]
}
# Allow inbound traffic from Accepter CIDR block
ingress {
from_port = 0
to_port = 65535
protocol = "udp"
cidr_blocks = [aws_vpc.accepter_vpc.cidr_block]
}
# Allow inbound ICMP traffic from Accepter CIDR block
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = [aws_vpc.accepter_vpc.cidr_block]
}
# Allow SSH for EC2 Connect or SSH from a terminal
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "requester_security_group"
}
}
# Create Security Group for EC2 Instance for Accepter
resource "aws_security_group" "accepter_security_group" {
name = "accepter_security_group"
description = "accepter security group"
vpc_id = aws_vpc.accepter_vpc.id
# Allow inbound traffic from Requester CIDR block
ingress {
from_port = 0
to_port = 65535
protocol = "tcp"
cidr_blocks = [aws_vpc.requester_vpc.cidr_block]
}
# Allow inbound traffic from Requester CIDR block
ingress {
from_port = 0
to_port = 65535
protocol = "udp"
cidr_blocks = [aws_vpc.requester_vpc.cidr_block]
}
# Allow inbound ICMP traffic from Requester CIDR block
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = [aws_vpc.requester_vpc.cidr_block]
}
# Allow SSH from Requester EC2 Instance
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [aws_vpc.requester_vpc.cidr_block]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "accepter_security_group"
}
}
- Ec2.tf - This shows the EC2 instances created to test the vpc peering connection associated with the different vpcs created. Ec2 instances for both Requester Vpc and Accepter Vpc are created. Here we are testing the vpc peering created above. Note: Requester-server has both public and private ip and Accepter-server has a private ip only.
resource "aws_instance" "requester_server" {
ami = var.ami_id
instance_type = var.instance_type
key_name = var.ami_key_pair_name # This is an existing key pair that has already been created
security_groups = [aws_security_group.requester_security_group.id]
subnet_id = aws_subnet.subnet_requester.id
monitoring = false
tags = {
Name = "requester_server"
}
}
resource "aws_instance" "accepter_server" {
ami = var.ami_id
instance_type = var.instance_type
key_name = var.ami_key_pair_name # This is an existing key pair that has already been created
security_groups = [aws_security_group.accepter_security_group.id]
subnet_id = aws_subnet.subnet_accepter.id
monitoring = false
tags = {
Name = "accepter_server"
}
}
Testing
This shows the outcome of the terraform script and also shows the communication between the vpcs.
Requester-server Communicating with Accepter-server
Pinging the private ip of the Accepter instance.
Accepter-server Communicating with Requester-server
Pinging the private ip of the Requester instance.
Conclusion
VPC peering is useful for scenarios where you want to share resources, services, or data securely between separate VPCs, such as connecting development and production environments, sharing databases, or integrating different applications within your AWS infrastructure. It provides a convenient way to build complex multi-tier architectures in a scalable and isolated manner. As shown above, its shows the connection between 2 ec2 instances on different VPCs connecting with each other via the VPC Peering.
Top comments (0)