In this blog, we will create a Terraform script for setting up the VPC in aws. VPC enables us to launch the aws resources into a virtual network that we define. It is logically isolated from other virtual networks in the AWS Cloud. You can specify an IP address range for the VPC, add subnets, associate security groups, and configure route tables. Terraform scripts enables us to spin up the infrastructure at once and also check the current state of the system.

Creating the VPC script in Terraform
On Amazon AWS, we have a default VPC created to launch instances on. The best practice is to launch an instance in a VPC, either on a default VPC or in a custom made VPC. We will start by creating our own VPC, to deploy instances on. This VPC uses the 10.0.0.0/16 addressing space. Every available zone in a VPC has its own private and public subnet.
Terraform script to create a vpc:
vpc.tf
resource “aws_vpc” “terra-vpc” {
cidr_block = “10.0.0.0/16”
instance_tenancy = “default”
enable_dns_support = “true”
enable_dns_hostnames = “true”
enable_classiclink = “false”
tags = {
Name = “terra-vpc”
}
}
I have defined a cidr block address of 10.0.0.0/16. Instance tenancy means that every instance that we launch will have a default tenancy. You can change this according to your requirements. DNS support and DNS hostname would provide the internal domain name and host name. If you want to link your VPC to ec2 classic, then you can enable the classic link as true. I have kept it false.
Defining subnets
Now, we will create the subnets. I have created three public and 3 private subnets.
resource “aws_subnet” “terra-public-1” {
vpc_id = aws_vpc.terra-vpc.id
cidr_block = “10.0.1.0/24”
map_public_ip_on_launch = “true”
availability_zone = “us-east-1a”
tags = {
Name = “terra-public-1”
}
}
resource “aws_subnet” “terra-public-2” {
vpc_id = aws_vpc.terra-vpc.id
cidr_block = “10.0.2.0/24”
map_public_ip_on_launch = “true”
availability_zone = “us-east-1b”
tags = {
Name = “terra-public-2”
}
resource “aws_subnet” “terra-public-3” {
vpc_id = aws_vpc.terra-vpc.id
cidr_block = “10.0.3.0/24”
map_public_ip_on_launch = “true”
availability_zone = “us-east-1c”
tags = {
Name = “terra-public-3”
}
}
resource “aws_subnet” “terra-private-1” {
vpc_id = aws_vpc.terra-vpc.id
cidr_block = “10.0.4.0/24”
map_public_ip_on_launch = “false”
availability_zone = “us-east-1a”
tags = {
Name = “terra-private-1”
}
}
resource “aws_subnet” “terra-private-2” {
vpc_id = aws_vpc.terra-vpc.id
cidr_block = “10.0.5.0/24”
map_public_ip_on_launch = “false”
availability_zone = “us-east-1b”
tags = {
Name = “terra-private-2”
}
}
resource “aws_subnet” “terra-private-3” {
vpc_id = aws_vpc.terra-vpc.id
cidr_block = “10.0.6.0/24”
map_public_ip_on_launch = “false”
availability_zone = “us-east-1c”
tags = {
Name = “terra-private-3”
}
}
We refer to the vpc we have created earlier. In public subnets, map_public_ip_on_launch is set to true, because we would want our instances to have a public IP on launch. Whereas, in private subnets, we don’t want the instances to have a public IP so we have set map_public_ip_on_launch to false.
Internet gateway
resource “aws_internet_gateway” “tig-gw” {
vpc_id = aws_vpc.terra-vpc.id
tags = {
Name = “terra-ig”
}
}
The public subnets are only public when they connect to the internet gateway. So I have created an internet gateway in the same VPC.
Defining a route of traffic to internet gateway
resource “aws_route_table” “terra-public” {
vpc_id = aws_vpc.terra-vpc.id
route {
cidr_block = “0.0.0.0/0”
gateway_id = aws_internet_gateway.tig-gw.id
}
tags = {
Name = “rt-public-1”
}
}
Now, we will have to associate this route to the subnets.
resource “aws_route_table_association” “terra-public-1-a” {
subnet_id = aws_subnet.terra-public-1.id
route_table_id = aws_route_table.terra-public.id
}
resource “aws_route_table_association” “terra-public-2-a” {
subnet_id = aws_subnet.terra-public-2.id
route_table_id = aws_route_table.terra-public.id
}
resource “aws_route_table_association” “terra-public-3-a” {
subnet_id = aws_subnet.terra-public-3.id
route_table_id = aws_route_table.terra-public.id
}
Creating a NAT gateway for the instances to access the internet
To do this, we need a static IP address or elastic IP.
resource “aws_eip” “nat” {
vpc = true
}
With this ip address, we will create a NAT gateway.
resource “aws_nat_gateway” “nat-gw” {
allocation_id = aws_eip.nat.id
subnet_id = aws_subnet.terra-public-1.id
depends_on = [aws_internet_gateway.tig-gw]
}
Now we will create routes for the NAT
resource “aws_route_table” “terra-private” {
vpc_id = aws_vpc.terra-vpc.id
route {
cidr_block = “0.0.0.0/0”
nat_gateway_id = aws_nat_gateway.nat-gw.id
}
tags = {
Name = “terra-private-1”
}
}
Associate these routes with private subnets:
resource “aws_route_table_association” “terra-private-1-a” {
subnet_id = aws_subnet.terra-private-1.id
route_table_id = aws_route_table.terra-private.id
}
resource “aws_route_table_association” “terra-private-2-a” {
subnet_id = aws_subnet.terra-private-2.id
route_table_id = aws_route_table.terra-private.id
}
resource “aws_route_table_association” “terra-private-3-a” {
subnet_id = aws_subnet.terra-private-3.id
route_table_id = aws_route_table.terra-private.id
}
So now we have created the required configurations for VPC. You can also check the code here. In the next blog, we will create an instance in the same vpc.
References:
https://docs.aws.amazon.com/vpc/index.html