Understanding AWS VPC and implementation through Terraform

Hamza Naeem
3 min readMay 8, 2023

--

Amazon Virtual Private Cloud (VPC) is a virtual network that lets you launch Amazon Web Services (AWS) resources into a predefined virtual network. It’s your personal network within the AWS cloud. You have complete control over your VPC, including the ability to choose your own IP address range, create subnets, and configure routing and security. You can also use VPC to construct a virtual private network (VPN) between your on-premises data center and AWS services, known as a site-to-site VPN.

A VPC consists of several components, including:

Subnets: A VPC can be subdivided into many subnets, which are used to break the network into smaller, more manageable chunks. Each subnet is assigned to an Availability Zone and can have one or more instances or resources.

Route tables: Route tables are used to establish the paths that traffic is supposed to take between subnets and to the internet. A route table must be associated with each subnet, and a route table can be associated with several subnets.

Internet Gateway: An internet gateway is a VPC component that enables communication between instances in the VPC and the internet. It is horizontally scaled, redundant, and highly available. It serves as a bridge between the VPC and the public internet, allowing instances within the VPC to access and be accessible from the internet.

NAT Gateway: A NAT Gateway allows instances in a private subnet to access to the internet or other AWS services while blocking the internet from connecting to those instances. It allows instances on the private subnet to communicate with other resources on the internet or other AWS services while ensuring security by not allowing the internet to communicate directly with the private subnet.

Elastic IP: The Elastic IP is attached to the NAT Gateway, allowing the instance to keep its static public IP address even if the NAT Gateway is stopped and restarted. This is significant because the private instances require a static IP address to interact with the NAT Gateway, and if the IP address of the NAT Gateway changes, the private instances will be unable to communicate with it.

provider "aws" {
region = "region"
access_key = ""
secret_key = ""
}

# VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}

# Create internet gateway and attach to VPC
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
}

# public subnet in the VPC
resource "aws_subnet" "public1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
availability_zone = "AZ-1"
}

# public subnet in the VPC
resource "aws_subnet" "public2" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
map_public_ip_on_launch = true
availability_zone = "AZ-2"
}

# private subnet in the VPC
resource "aws_subnet" "private1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.3.0/24"
availability_zone = "AZ-1"
}

# private subnet in the VPC
resource "aws_subnet" "private2" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.4.0/24"
availability_zone = "AZ-2"
}

# route table for the public subnet
resource "aws_route_table" "public1" {
vpc_id = aws_vpc.main.id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}

tags = {
Name = "public1"
}
}

# Associate the public subnet with public route table
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public1.id
route_table_id = aws_route_table.public1.id
}

# route table for the public subnet
resource "aws_route_table" "public2" {
vpc_id = aws_vpc.main.id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}

tags = {
Name = "public2"
}
}

# Associate the public subnet with public route table
resource "aws_route_table_association" "public2" {
subnet_id = aws_subnet.public2.id
route_table_id = aws_route_table.public2.id
}

# route table for the private subnet
resource "aws_route_table" "private1" {
vpc_id = aws_vpc.main.id

route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.main.id
}

tags = {
Name = "private1"
}
}

# Associate the private subnet with private route table
resource "aws_route_table_association" "private" {
subnet_id = aws_subnet.private1.id
route_table_id = aws_route_table.private1.id
}

# route table for the private subnet
resource "aws_route_table" "private2" {
vpc_id = aws_vpc.main.id

route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.main.id
}

tags = {
Name = "private2"
}
}

# Associate the private subnet with private route table
resource "aws_route_table_association" "private2" {
subnet_id = aws_subnet.private2.id
route_table_id = aws_route_table.private2.id
}

# NAT gateway in the public subnet
resource "aws_nat_gateway" "main" {
allocation_id = aws_eip.main.id
subnet_id = aws_subnet.public.id
}

# Allocate an Elastic IP address for the NAT gateway
resource "aws_eip" "main" {
vpc = true
}

--

--