Easy Steps to Create AWS VPC with Terraform
HashiCorp Terraform is an infrastructure as code tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. Terraform can manage low-level components like compute, storage, and networking resources, as well as high-level components like DNS entries and SaaS features.
To know more about terraform checkout official Documentation : Link
In this article we’ll create AWS VPC with two private and public subnet along with Internet Gateway and NAT Gateway.
List of Resources will be created.
- AWS VPC with CIDR 10.0.0.0/16 (You can change CIDR range in vars.tf)
- subnets (public and private)
- Internet Gateway
- Route Table (for public and private)
- Elastic IP for NAT gateway
- NAT Gateway
- Associate route tables
- Default security group for VPC
You can find all the files in my git repository : Link
Prerequisites
- AWS ACCOUNT
- AWS Access keys
- AWS CLI
- Terrafrom CLI
Steps
- First let’s create a dir to keep our all terraform files.
mkdir terraform-vpc
2. Change dir and we’ll create 3 files. using touch command.
touch main.tf vars.tf output.tf
- main.tf (In this file we’ll define cloud provider and resources we want to create)
- output.tf (This file stores outputs from
terraform apply
) - vars.tf (we’ll use this file to store variables.)
3. Edit main.tf
and write below configuration and save it.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.6.0"
}
}
required_version = ">= 1.1.7"
}
provider "aws" {
region = var.region
}
#Creating VPC
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.environment}-vpc"
Environment = var.environment
}
}
#Creating Public subnet1
resource "aws_subnet" "public_subnet1" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.public_subnet_cidr1
availability_zone = var.availability_zone1
map_public_ip_on_launch = true
tags = {
Name = "${var.environment}-public-subnet-1"
Environment = "${var.environment}"
}
}
#Creating Public subnet2
resource "aws_subnet" "public_subnet2" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.public_subnet_cidr2
availability_zone = var.availability_zone2
map_public_ip_on_launch = true
tags = {
Name = "${var.environment}-public-subnet-2"
Environment = "${var.environment}"
}
}
#Creating Private subnet 1
resource "aws_subnet" "private_subnet1" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.private_subnet_cidr1
availability_zone = var.availability_zone1
map_public_ip_on_launch = false
tags = {
Name = "${var.environment}-private-subnet-1"
Environment = "${var.environment}"
}
}
#Creating Private subnet 2
resource "aws_subnet" "private_subnet2" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.private_subnet_cidr2
availability_zone = var.availability_zone2
map_public_ip_on_launch = false
tags = {
Name = "${var.environment}-private-subnet-2"
Environment = "${var.environment}"
}
}
# Creating Internet Gateway
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.environment}-igw"
Environment = var.environment
}
}
#Creating Route tables for Private Subnet
resource "aws_route_table" "private" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.environment}-private-route-table"
Environment = "${var.environment}"
}
}
#Creating Route table Public Subnet
resource "aws_route_table" "public" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.environment}-public-route-table"
Environment = "${var.environment}"
}
}
#Creating Elastic-IP (eip) for NAT Gateway
resource "aws_eip" "nat_eip" {
vpc = true
depends_on = [aws_internet_gateway.igw]
tags = {
Name = "${var.environment}-nat_eip"
Environment = "${var.environment}"
}
}
#Creating NAT Gateway
resource "aws_nat_gateway" "nat" {
allocation_id = aws_eip.nat_eip.id
subnet_id = aws_subnet.public_subnet1.id
tags = {
Name = "${var.environment}-nat_gateway"
Environment = "${var.environment}"
}
}
#Adding Route for Internet Gateway
resource "aws_route" "public_internet_gateway" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
#Adding Route for NAT
resource "aws_route" "private_nat_gateway" {
route_table_id = aws_route_table.private.id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat.id
}
#Associate route table with public subnet1
resource "aws_route_table_association" "public1" {
subnet_id = aws_subnet.public_subnet1.id
route_table_id = aws_route_table.public.id
}
#Associate route table with public subnet2
resource "aws_route_table_association" "public2" {
subnet_id = aws_subnet.public_subnet2.id
route_table_id = aws_route_table.public.id
}
#Associate route table with private subnet1
resource "aws_route_table_association" "private1" {
subnet_id = aws_subnet.private_subnet1.id
route_table_id = aws_route_table.private.id
}
#Associate route table with private subnet2
resource "aws_route_table_association" "private2" {
subnet_id = aws_subnet.private_subnet2.id
route_table_id = aws_route_table.private.id
}
#Creating default security group for VPC
resource "aws_security_group" "default" {
name = "${var.environment}-default-sg"
description = "Default SG to alllow traffic from the ${var.environment}-VPC"
vpc_id = aws_vpc.vpc.id
depends_on = [
aws_vpc.vpc
]
ingress {
from_port = "0"
to_port = "0"
protocol = "-1"
self = true
}
egress {
from_port = "0"
to_port = "0"
protocol = "-1"
self = "true"
}
tags = {
Name = "${var.environment}-default-sg"
Environment = "${var.environment}"
}
}
4. Edit vars.tf
and write below configuration and save it.
variable "region" {
default = "ap-south-1"
}
variable "environment" {
default = "demo"
description = "Deployment Environment"
}
variable "vpc_cidr" {
default = "10.0.0.0/16"
description = "CIDR block of the vpc"
}
variable "public_subnet_cidr1" {
default = "10.0.0.0/24"
description = "CIDR block of the public subnet"
}
variable "public_subnet_cidr2" {
default = "10.0.1.0/24"
description = "CIDR block of the public subnet"
}
variable "private_subnet_cidr1" {
default = "10.0.2.0/24"
description = "CIDR block of the private subnet"
}
variable "private_subnet_cidr2" {
default = "10.0.3.0/24"
description = "CIDR block of the private subnet"
}
variable "availability_zone1" {
default = "ap-south-1a"
description = "availability zones"
}
variable "availability_zone2" {
default = "ap-south-1b"
description = "availability zones"
}
5. Edit output.tf
and write below configuration and save it.
output "vpc_id" {
value = aws_vpc.vpc.id
description = "ID of VPC"
}
output "public_subnet_id1" {
value = aws_subnet.public_subnet1.id
description = "ID of public subnet"
}
output "public_subnet_id2" {
value = aws_subnet.public_subnet2.id
description = "ID of public subnet"
}
output "private_subnet_id1" {
value = aws_subnet.private_subnet1.id
description = "ID of private subnet"
}
output "private_subnet_id2" {
value = aws_subnet.private_subnet2.id
description = "ID of private subnet"
}
output "igw_id" {
value = aws_internet_gateway.igw.id
description = "ID of internet gateway"
}
output "public_route_table_id" {
value = aws_route_table.public.id
description = "ID of public route table"
}
output "private_route_table_id" {
value = aws_route_table.private.id
description = "ID of private route table"
}
output "nat_eip" {
value = aws_eip.nat_eip.public_ip
description = "Contains the public IP address"
}
output "nat_eip_id" {
value = aws_eip.nat_eip.id
description = "Contains the EIP allocation ID"
}
output "security_group_id" {
value = aws_security_group.default.id
description = "Conatins ID of security group"
}
We have create all the necessary files, Now It’s time to create resources in AWS.
6. Run terraform init
to initialize the dir.
7. Run terraform plan
to check resources before creating.
8. Run terraform apply
to create resources in your AWS.
To check output’s of terraform apply
run terraform output
It will give you the details like vpc id, nat gateway id, subnet id etc.
Now log into your AWS console and verify the resources.
Congratulations 🎉