You can find source code in our repo
VPC Peering in AWS gives you opportunity to connect VPC. It is common used practise, in this article we will use terraform to connect our separate VPCs
Prerequisites:
- AWS Account: You must have an active AWS account. If you don't have one, you can sign up for an AWS account on the AWS website. You can create it here
- IAM User or Role: Create an IAM (Identity and Access Management) user or role in your AWS account with the necessary permissions to create and manage EC2 Instances. At a minimum, the user or role should have permissions to create EC2 instances, VPCs, and related resources.
- Terraform Installed: Install Terraform on your local machine. You can download Terraform from the official Terraform website and follow the installation instructions for your operating system here
Peering
What is VPC Peering? Connecting two different Virtual Networks in a cloud environment
In our example we will create 2 EC2 Instances in two different VPCs(A and B). First instance will be in Public subnet with a Public IP. Second instance will be in a private subnet, without allocated Public Ip, so we can only use it's private address.
VPC creation
module "vpc-a"{
source = "terraform-aws-modules/vpc/aws"
version = "5.1.2"
name = "vpc-a"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
}
module "vpc-b"{
source = "terraform-aws-modules/vpc/aws"
version = "5.1.2"
name = "vpc-b"
cidr = "10.1.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.1.1.0/24", "10.1.2.0/24"]
public_subnets = ["10.1.3.0/24", "10.1.4.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
}
Note: To connect two VPCs with perring conection your Cird Blocks should not overlap, so we will use 10.0.0.0/16
and 10.1.0.0/16
For each VPC we will attach security groups allowing ingress traffic on HTTP port and SSH
Creating EC2
resource "tls_private_key" "ssh_key" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "local_file" "private_key" {
content = tls_private_key.ssh_key.private_key_pem
filename = "ssh/ec2_key.pem"
file_permission = "0600"
}
resource "aws_key_pair" "public_key" {
key_name = "EC2_key"
public_key = tls_private_key.ssh_key.public_key_openssh
}
module "ec2-instance-a" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "5.5.0"
name = "Instance-a"
instance_type = "t3.small"
subnet_id = module.vpc-a.public_subnets[0]
associate_public_ip_address = true
key_name = aws_key_pair.public_key.key_name
vpc_security_group_ids = [aws_security_group.ssh-a.id]
}
module "ec2-instance-b" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "5.5.0"
name = "Instance-b"
instance_type = "t3.small"
subnet_id = module.vpc-b.private_subnets[0]
associate_public_ip_address = false
user_data = file("shell.sh")
vpc_security_group_ids = [aws_security_group.ssh-b.id]
}
- We will create Instance A with a Public Ip address in a public subnet
- We will create a new SSH key to connect to Instance A
- Instance B would be created in VPC B in a private subnet
- We will use user data to provide script for installing httpd server so we can check if we can get response from it using private ip
AWS VPC Peering Resources
Now we need to connect those two VPCs using the following code:
resource "aws_vpc_peering_connection" "foo" {
peer_vpc_id = module.vpc-a.vpc_id
vpc_id = module.vpc-b.vpc_id
auto_accept = true
tags = {
Name = "VPC Peering between vpc-a and vpc-b"
}
}
resource "aws_route" "peering_routes-ab" {
count = length(module.vpc-a.public_route_table_ids)
route_table_id = tolist(module.vpc-a.public_route_table_ids)[count.index]
destination_cidr_block = module.vpc-b.vpc_cidr_block
vpc_peering_connection_id = aws_vpc_peering_connection.foo.id
}
resource "aws_route" "peering_routes-ba" {
count = length(module.vpc-b.private_route_table_ids)
route_table_id = tolist(module.vpc-b.private_route_table_ids)[count.index]
destination_cidr_block = module.vpc-a.vpc_cidr_block
vpc_peering_connection_id = aws_vpc_peering_connection.foo.id
}
output "Connect_to_instance_a" {
description = "The public IP address assigned to the instance"
value = "ssh -i ${local_file.private_key.filename} ec2-user@${module.ec2-instance-a.public_ip}"
}
output "Private_ip_instance_b" {
description = "The public IP address assigned to the instance"
value = module.ec2-instance-b.private_ip
}
aws_vpc_peering_connection
- is used to create peering for both VPC. Need to provide both VPC ids
aws_route
- after peering is created we need to update our Route Tables, in order to forward traffic. Since we will use VPC A Public Subnet and VPC B Private subnet in our example we would we would update only those.
Connect_to_instance
- We will use this output to connect to our Public Instance A
Private_ip_instance_b
- we will use to ssh to Instance A
Testing
After applying terraform code, connect to your EC2 Instance A, using command in your output:
ssh -i <PATH_TO_THE_KEY> ec2-user@<PUBLIC_IP>
After connected to Instance A use your second output to check connection:
curl <Private_ip_Instance_B>
You should get the following output:
<h1> Welcome to server B</h1>
You can find source code in our repo