You can see the power of Terraform when you provision infrastructure in the cloud environment. In this post, we will create VPC and subnets via Terraform step by step.
We will configure
- VPC
- 2 Subnets: public and private
- Internet Gateway
- NAT Gateway with an elastic IP
- 2 Route tables: public and private
Prerequisites
- Install Terraform CLI
- Install AWS CLI
- Setup the AWS Sandbox
- Configure AWS CLI with the credential
[Note] Let’s use the Windows machine for the examples in this post.
[Note] To install Terraform on Windows, you need to install chocolatey first. https://chocolatey.org/install
choco --version
choco install terraform
terraform --version
aws --version
aws configure
Prepare the Environment
- Create a working directory such as C:/Apps/Terraform/AWS-demo
Define Input Variables
- Create a variable definition file: variables.tf
variable "region" {
type = string
description = "AWS Region"
}
variable "vpc" {
type = object({
cidr_block = string
tag_name = string
})
description = "Custom VPC"
}
variable "subnets" {
type = object({
public_cidr_block = string
public_az = string
private_cidr_block = string
private_az = string
})
}
Create Terraform Configuration
- Create a main configuration file: main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
provider "aws" {
region = var.region
}
# VPC
resource "aws_vpc" "my_vpc" {
cidr_block = var.vpc.cidr_block
instance_tenancy = "default"
tags = {
Name = var.vpc.tag_name
}
}
# Internet Gateway
resource "aws_internet_gateway" "my_igw" {
vpc_id = aws_vpc.my_vpc.id
}
# Public Subnet
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = var.subnets.public_cidr_block
availability_zone = var.subnets.public_az
tags = {
Name = "public_subnet"
}
}
# Private Subnet
resource "aws_subnet" "private_subnet" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = var.subnets.private_cidr_block
availability_zone = var.subnets.private_az
tags = {
Name = "private_subnet"
}
}
# Route table - Public Subnet
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.my_igw.id
}
tags = {
Name = "public_route_table"
}
}
resource "aws_route_table_association" "public_subnet_rt" {
subnet_id = aws_subnet.public_subnet.id
route_table_id = aws_route_table.public_rt.id
}
# NAT Gateway in the public subnet
resource "aws_eip" "nat_ip" {
vpc = true
}
resource "aws_nat_gateway" "nat_gw" {
allocation_id = aws_eip.nat_ip.id
subnet_id = aws_subnet.public_subnet.id
}
# Route table - Private Subnet
resource "aws_route_table" "private_rt" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat_gw.id
}
tags = {
Name = "private_route_table"
}
}
resource "aws_route_table_association" "private_subnet_rt" {
subnet_id = aws_subnet.private_subnet.id
route_table_id = aws_route_table.private_rt.id
}
Set Input Values
- Create a variable value file: variables.tfvars
region = "us-east-1"
vpc = {
cidr_block = "172.31.0.0/16"
tag_name = "customVPC"
}
subnets = {
public_cidr_block = "172.31.0.0/20"
public_az = "us-east-1a"
private_cidr_block = "172.31.16.0/20"
private_az = "us-east-1b"
}
Run the terraform
terraform init
terraform validate
terraform plan -var-file="variables.tfvars"
terraform apply -var-file="variables.tfvars"
terraform show