How to Create, configure and peer two VPC on AWS using Terraform!!

Gaurav Kaushik
6 min readDec 23, 2020

--

AWS is one of the most stable and talked about Cloud IaaS(Infrastructure as a Service) as of today. Managing Cloud resources manually on IaaS platform can be a tedious task.
Automation and Orchestration comes handy while creating Cloud Infrastructure resources & this is where Terraform comes into picture.

HashiCorp’s Terraform is a tool for creating and managing Cloud Infrastructure for various Cloud Iaas vendors like AWS, Azure, Google Cloud to name a few.

Hereby, this post demonstrates a Virtual Private Cloud(VPC) Peering example & will cover all the necessary components of VPC Peering configuration as this is one of the most important & widespread use-case in AWS Cloud Networking.

I will be showing the configurations directly as I suppose the readers are well-versed with basics and willing to look for Terraform in action:

VPC Peering Objective:
1) Create two VPCs
2) Create 5 subnets in VPC-1: 4 subnets should be Private(names: app1, app2, DB, DBCache) and 1 public subnet(web1) for sending Internet requests
3) Create 2 subnets in VPC-2: 1 Private subnet(DB2) and 1 Public subnet(web2)
4) DBCache and app1 subnets should be able to send Internet requests
5) DB Instance from each VPC should be able to access each other

VPC-1 Configuration:

File: variables.tf

variable "aws_region" {
description = "Default AWS Region"
default = "us-east-1"
}
variable "vpc_cidr1" {
description = "VPC CIDR by default"
default = "10.20.0.0/16"
}
variable "vpc_cidr2" {
description = "VPC CIDR by default"
default = "11.20.0.0/16"
}

File: main.tf starts

# Providerprovider "aws" {
profile = "default"
region = var.aws_region
}

Create VPCs

# VPC-1resource “aws_vpc” “main” {cidr_block = var.vpc_cidr1
instance_tenancy = “default”
tags = {
Name = “vpc_production”
}
}
#VPC-2resource “aws_vpc” “dev” {cidr_block = var.vpc_cidr2
instance_tenancy = “default”
tags = {Name = “vpc_development”
}
}

Create Internet Gateway & attach it to VPC: This is going to provide Internet Connectivity to the instances in the ‘web’ subnet

resource "aws_internet_gateway" "gw1" {
vpc_id = aws_vpc.main.id
tags = {
Name = "IGW_production"
}
depends_on = [aws_internet_gateway.gw1]
}

Create & Attach NAT Gateway to the VPC: NAT Gateway will provide Internet connectivity to the instances which are in a private subnet but needs to send Internet requests:- “app1” & “DBCache”

resource "aws_eip" "nat_eip" {
vpc = true
}
resource "aws_nat_gateway" "nat_gateway" {
allocation_id = aws_eip.nat_eip.id
subnet_id = aws_subnet.web1.id
tags = {
"Name" = "NatGateway"
}
}

Create Subnets:

resource "aws_subnet" "web1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.20.1.0/24"
map_public_ip_on_launch = true
tags = {
Name = "web-production"
}
}
resource "aws_subnet" "app1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.20.2.0/24"
tags = {
Name = "app1"
}
}
resource "aws_subnet" "app2" {
vpc_id = aws_vpc.main.id
cidr_block = "10.20.3.0/24"
tags = {
Name = "app2"
}
}
resource "aws_subnet" "DB1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.20.4.0/24"
tags = {
Name = "DB-production"
}
}
resource "aws_subnet" "DBCache" {
vpc_id = aws_vpc.main.id
cidr_block = "10.20.5.0/24"
tags = {
Name = "DBCache"
}
}

Create Route tables and associate it to subnets: Route Table contains entry to specific networks & gateways

resource "aws_route_table" "r1" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw1.id
}
tags = {
Name = "Public Route Table"
}
depends_on = [aws_internet_gateway.gw1]
}
resource "aws_route_table" "r3" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_nat_gateway.nat_gateway.id
}
tags = {
Name = "Private Route Table with Internet Requests"
}
depends_on = [aws_internet_gateway.gw1]
}

Associate subnet to Route Table

resource "aws_route_table_association" "a" {
subnet_id = aws_subnet.web1.id
route_table_id = aws_route_table.r1.id
}
resource "aws_route_table_association" "b" {
subnet_id = aws_subnet.app2.id
route_table_id = aws_route_table.r2.id
}
resource "aws_route_table_association" "c" {
subnet_id = aws_subnet.DB1.id
route_table_id = aws_route_table.r2.id
}
resource "aws_route_table_association" "e" {
subnet_id = aws_subnet.app1.id
route_table_id = aws_route_table.r3.id
}
resource "aws_route_table_association" "f" {
subnet_id = aws_subnet.DBCache.id
route_table_id = aws_route_table.r3.id
}

VPC Peering: This is our main goal. VPC Peering connects two VPCs

resource "aws_vpc_peering_connection" "Prod-Dev" {
peer_vpc_id = aws_vpc.main.id
vpc_id = aws_vpc.dev.id
auto_accept = true
}

VPC-2 Configuration: Mostly same as config. for VPC-1

Create Internet Gateway & attach it to VPC

resource "aws_internet_gateway" "gw2" {
vpc_id = aws_vpc.dev.id
tags = {
Name = "IGW_development"
}
depends_on = [aws_internet_gateway.gw2]
}

Create Subnets

resource "aws_subnet" "web2" {
vpc_id = aws_vpc.dev.id
cidr_block = "11.20.1.0/24"
map_public_ip_on_launch = true
tags = {
Name = "web-development"
}
}
resource "aws_subnet" "DB2" {
vpc_id = aws_vpc.dev.id
cidr_block = "11.20.4.0/24"
tags = {
Name = "DB-development"
}
}

Create Route tables and associate it to subnets

resource "aws_route_table" "r2" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "11.20.4.0/24"
gateway_id = aws_vpc_peering_connection.Prod-Dev.id
}
tags = {
Name = "Private Route Table"
}
depends_on = [aws_vpc_peering_connection.Prod-Dev]
}
resource "aws_route_table" "r4" {
vpc_id = aws_vpc.dev.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw2.id
}
tags = {
Name = "Public Route Table Development"
}
depends_on = [aws_internet_gateway.gw2]
}
resource "aws_route_table" "r5" {
vpc_id = aws_vpc.dev.id
route {
cidr_block = "10.20.4.0/24"
gateway_id = aws_vpc_peering_connection.Prod-Dev.id
}
tags = {
Name = "Private Route Table Development"
}
depends_on = [aws_vpc_peering_connection.Prod-Dev]
}

Associate subnet to Route Table

resource "aws_route_table_association" "g" {
subnet_id = aws_subnet.web2.id
route_table_id = aws_route_table.r4.id
}
resource "aws_route_table_association" "h" {
subnet_id = aws_subnet.DB2.id
route_table_id = aws_route_table.r5.id
}

Create Security Groups

resource "aws_security_group" "all_traffic1" {
name = "SG_VPC"
description = "Allow inbound traffic"
vpc_id = aws_vpc.main.id
ingress {
description = "TLS from VPC"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [aws_vpc.main.cidr_block]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
depends_on = [aws_vpc.main]
tags = {
Name = "allow_ssh"
}
}
resource "aws_security_group_rule" "ssh_inbound_access1" {
from_port = 22
protocol = "tcp"
security_group_id = aws_security_group.all_traffic1.id
to_port = 22
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group" "all_traffic2" {
name = "SG_VPC"
description = "Allow inbound traffic"
vpc_id = aws_vpc.dev.id
ingress {
description = "TLS from VPC"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [aws_vpc.dev.cidr_block]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
depends_on = [aws_vpc.dev]
tags = {
Name = "allow_ssh"
}
}
resource "aws_security_group_rule" "ssh_inbound_access2" {
from_port = 22
protocol = "tcp"
security_group_id = aws_security_group.all_traffic2.id
to_port = 22
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
}

Create EC2 Instances in their respective VPCs

resource "aws_instance" "web1" {
ami = "ami-0885b1f6bd170450c"
instance_type = "t2.micro"
key_name = "vpc_prod"
vpc_security_group_ids = ["${aws_security_group.all_traffic1.id}"]
associate_public_ip_address = true
tags = {
Name = "web-production"
}
subnet_id = aws_subnet.web1.id
provisioner "file" {
source = "/home/ubuntu/terraform/vpc_prod.pem"
destination = "/home/ubuntu/vpc_prod.pem"
}
}

resource "aws_instance" "web2" {
ami = "ami-0885b1f6bd170450c"
instance_type = "t2.micro"
key_name = "vpc_prod"
vpc_security_group_ids = ["${aws_security_group.all_traffic2.id}"]
tags = {
Name = "web-development"
}
subnet_id = aws_subnet.web2.id
}
resource "aws_instance" "DB1" {
ami = "ami-0885b1f6bd170450c"
instance_type = "t2.micro"
key_name = "vpc_prod"
vpc_security_group_ids = ["${aws_security_group.all_traffic1.id}"]
tags = {
Name = "DB-production"
}
subnet_id = aws_subnet.DB1.id
}
resource "aws_instance" "DB2" {
ami = "ami-0885b1f6bd170450c"
instance_type = "t2.micro"
key_name = "vpc_prod"
vpc_security_group_ids = ["${aws_security_group.all_traffic2.id}"]
tags = {
Name = "DB-development"
}
subnet_id = aws_subnet.DB2.id
}
resource "aws_instance" "app1" {
ami = "ami-0885b1f6bd170450c"
instance_type = "t2.micro"
key_name = "vpc_prod"
vpc_security_group_ids = ["${aws_security_group.all_traffic1.id}"]
tags = {
Name = "app1-production"
}
subnet_id = aws_subnet.app1.id
}
resource "aws_instance" "app2" {
ami = "ami-0885b1f6bd170450c"
instance_type = "t2.micro"
key_name = "vpc_prod"
vpc_security_group_ids = ["${aws_security_group.all_traffic1.id}"]
tags = {
Name = "app2-production"
}
subnet_id = aws_subnet.app2.id
}
resource "aws_instance" "DBCache" {
ami = "ami-0885b1f6bd170450c"
instance_type = "t2.micro"
key_name = "vpc_prod"
vpc_security_group_ids = ["${aws_security_group.all_traffic1.id}"]
tags = {
Name = "DBCache"
}
subnet_id = aws_subnet.DBCache.id
}

At this stage all the Instances are properly Instantiated in their respective subnets :)

For VPC Full code visit my git repo:

https://github.com/gauravk29/full_vpc

--

--

Gaurav Kaushik
Gaurav Kaushik

No responses yet