Introduction
Terraform is an open-source infrastructure as code (IaC) tool developed by HashiCorp. It allows you to define and manage your infrastructure resources using a declarative configuration language. With Terraform, you can describe your desired infrastructure state in code, and Terraform will automatically provision and manage the resources needed to reach that state.
Here are some key reasons why you might need Terraform:
- Infrastructure Automation
- Cross-Platform Compatibility
- Infrastructure Versioning and Collaboration
- Infrastructure as Code (IaC) Best Practices
- Scalability and Consistency
Overall, Terraform simplifies infrastructure management, reduces manual effort, and provides a systematic approach to infrastructure provisioning. It is an essential tool for organizations adopting cloud computing, microservices architectures, or seeking to automate their infrastructure operations.
I'll write some Terraform codes for private AWS VPC creation in this article.
Requirements
Sample Code
I'll save all terraform states in an S3 bucket. If you will follow the article, please make sure you create the bucket just before the execution. Also, you need to make sure your AWS credentials are correct.
main.tf:
This is our main entry point for the terraform codes. The following code block provides 3 main things.
- s3 configuration for the state
- Terraform provider plugin
- Module source (All related tf files need to be in the VPC directory.)
terraform {
required_version = ">= 0.12.0"
backend "s3" {
bucket = "habil-dev-bucket"
key = "prod/vpc/habil-dev.tfstate"
region = "eu-central-1"
}
}
provider "aws" {
version = "~> 4.0"
region = "eu-central-1"
}
module "vpc" {
source = "./vpc"
}
vpc.tf:
This file contains the CIDR block and other DNS-specific settings.
resource "aws_vpc" "vpc" {
cidr_block = "10.20.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
assign_generated_ipv6_cidr_block = true
tags = {
Name = "habil-dev-vpc"
Environment = "dev"
}
}
vpc_subnets.tf
This file contains public and private subnets.
// Public Subnets
resource "aws_subnet" "sn-1a-public-xlb" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.20.96.0/24"
availability_zone = "eu-central-1a"
tags = {
Name = "habil-dev-1a-public-xlb"
CostCenter = "habil-dev-1a-public-xlb"
}
}
resource "aws_subnet" "sn-1b-public-xlb" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.20.97.0/24"
availability_zone = "eu-central-1b"
tags = {
Name = "habil-dev-1b-public-xlb"
CostCenter = "habil-dev-1b-public-xlb"
}
}
resource "aws_subnet" "sn-1c-public-xlb" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.20.98.0/24"
availability_zone = "eu-central-1c"
tags = {
Name = "habil-dev-1c-public-xlb"
CostCenter = "habil-dev-1c-public-xlb"
}
}
// Private Generic Subnets
resource "aws_subnet" "sn-1a-private-generic" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.20.104.0/21"
availability_zone = "eu-central-1a"
tags = {
Name = "habil-dev-1a-private-generic"
CostCenter = "habil-dev-1a-private-generic"
}
}
resource "aws_subnet" "sn-1b-private-generic" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.20.112.0/21"
availability_zone = "eu-central-1b"
tags = {
Name = "habil-dev-1b-private-generic"
CostCenter = "habil-dev-1b-private-generic"
}
}
resource "aws_subnet" "sn-1c-private-generic" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.20.120.0/21"
availability_zone = "eu-central-1c"
tags = {
Name = "habil-dev-1c-private-generic"
CostCenter = "habil-dev-1c-private-generic"
}
}
vpc_route_tables.tf:
This file contains public and generic route tables.
// Public Route Table
resource "aws_route_table" "rt-1a-public-xlb" {
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gateway.id
}
tags = {
Name = "habil-dev-1a-public-xlb-rt"
CostCenter = "habil-dev-1a-public-xlb-rt"
}
vpc_id = aws_vpc.vpc.id
}
resource "aws_route_table" "rt-1b-public-xlb" {
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gateway.id
}
tags = {
Name = "habil-dev-1b-public-xlb-rt"
CostCenter = "habil-dev-1b-public-xlb-rt"
}
vpc_id = aws_vpc.vpc.id
}
resource "aws_route_table" "rt-1c-public-xlb" {
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gateway.id
}
tags = {
Name = "habil-dev-1c-public-xlb-rt"
CostCenter = "habil-dev-1c-public-xlb-rt"
}
vpc_id = aws_vpc.vpc.id
}
// Private Generic Route Table
resource "aws_route_table" "rt-1a-private-generic" {
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat-1a.id
}
tags = {
Name = "habil-dev-1a-private-generic-rt"
CostCenter = "habil-dev-1a-private-generic-rt"
}
vpc_id = aws_vpc.vpc.id
}
resource "aws_route_table" "rt-1b-private-generic" {
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat-1b.id
}
tags = {
Name = "habil-dev-1b-private-generic-rt"
CostCenter = "habil-dev-1b-private-generic-rt"
}
vpc_id = aws_vpc.vpc.id
}
resource "aws_route_table" "rt-1c-private-generic" {
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat-1c.id
}
tags = {
Name = "habil-dev-1c-private-generic-rt"
CostCenter = "habil-dev-1c-private-generic-rt"
}
vpc_id = aws_vpc.vpc.id
}
vpc_route_table_associations.tf
resource "aws_route_table_association" "rta-1a-public-xlb" {
route_table_id = aws_route_table.rt-1a-public-xlb.id
subnet_id = aws_subnet.sn-1a-public-xlb.id
}
resource "aws_route_table_association" "rta-1b-public-xlb" {
route_table_id = aws_route_table.rt-1b-public-xlb.id
subnet_id = aws_subnet.sn-1b-public-xlb.id
}
resource "aws_route_table_association" "rta-1c-public-xlb" {
route_table_id = aws_route_table.rt-1c-public-xlb.id
subnet_id = aws_subnet.sn-1c-public-xlb.id
}
// Private Generic Subnets
resource "aws_route_table_association" "rta-1a-private-generic" {
route_table_id = aws_route_table.rt-1a-private-generic.id
subnet_id = aws_subnet.sn-1a-private-generic.id
}
resource "aws_route_table_association" "rta-1b-private-generic" {
route_table_id = aws_route_table.rt-1b-private-generic.id
subnet_id = aws_subnet.sn-1b-private-generic.id
}
resource "aws_route_table_association" "rta-1c-private-generic" {
route_table_id = aws_route_table.rt-1c-private-generic.id
subnet_id = aws_subnet.sn-1c-private-generic.id
}
vpc_nat_gateway.tf
Nat Gateway definitions.
resource "aws_nat_gateway" "nat-1a" {
allocation_id = aws_eip.nat-1a.id
subnet_id = aws_subnet.sn-1a-public-xlb.id
tags = {
Name = "habil-dev-1a-nat-gw"
Environment = "dev"
CostCenter = "habil-dev-1a-nat-gw"
}
}
resource "aws_nat_gateway" "nat-1b" {
allocation_id = aws_eip.nat-1b.id
subnet_id = aws_subnet.sn-1b-public-xlb.id
tags = {
Name = "habil-dev-1b-nat-gw"
Environment = "dev"
CostCenter = "habil-dev-1b-nat-gw"
}
}
resource "aws_nat_gateway" "nat-1c" {
allocation_id = aws_eip.nat-1c.id
subnet_id = aws_subnet.sn-1c-public-xlb.id
tags = {
Name = "habil-dev-1c-nat-gw"
Environment = "dev"
CostCenter = "habil-dev-1c-nat-gw"
}
}
vpc_igw.tf
Internet Gateway Definition.
resource "aws_internet_gateway" "gateway" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "habil-dev-igw"
Environment = "dev"
CostCenter = "habil-dev-igw"
}
}
vpc_eip.tf
Elastic IP definitions.
resource "aws_eip" "nat-1a" {
vpc = true
tags = {
Name = "habil-dev-nat-eip-1a"
Environment = "dev"
CostCenter = "habil-dev-nat-eip-1a"
}
}
resource "aws_eip" "nat-1b" {
vpc = true
tags = {
Name = "habil-dev-nat-eip-1b"
Environment = "dev"
CostCenter = "habil-dev-nat-eip-1b"
}
}
resource "aws_eip" "nat-1c" {
vpc = true
tags = {
Name = "habil-dev-nat-eip-1c"
Environment = "dev"
CostCenter = "habil-dev-nat-eip-1c"
}
}
Execution
The terraform init
command initializes a working directory containing Terraform configuration files. This is the first command that should be run after writing a new Terraform configuration or cloning an existing one from version control. It is safe to run this command multiple times.
terraform init
The terraform plan
command creates an execution plan, which lets you preview the changes that Terraform plans to make to your infrastructure. By default, when Terraform creates a plan it:
- Reads the current state of any already-existing remote objects to make sure that the Terraform state is up-to-date.
- Compares the current configuration to the prior state and noting any differences.
- Proposes a set of change actions that should, if applied, make the remote objects match the configuration.
terraform plan
The terraform apply
command executes the actions proposed in a Terraform plan.
terraform apply
Terraform will create a new VPC with provided configuration. Also will save the state into provided S3 bucket for you.
If you want to destroy all your changes you need to execute following command.
terraform destroy
Result
We have created a private AWS VPC with;
- subnets
- route tables
- route table associations
- nat gateway
- Internet gateway
- elastic IP
resources with our terraform files.
As always, you can find related files in my GitHub Repository:
habil / habil-dev-blog
Contains materials used in blog posts.
habil-dev-blog
Contains materials used in blog posts.
See you in the next article. 👻
Top comments (0)