[Terraform] AWS – VPC

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

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s