How to Create AWS VPC Using Terraform

terraform aws vpc

In this blog, you will learn to create AWS VPC using well structure terraform modules. It is a step by step guide for beginners with detailed information.

Prerequisites

To follow this guide you need to have the following.

  1. The latest Terraform binary is installed and configured in your system.
  2. AWS CLI installed and configured with a Valid AWS account with full permissions to create and manage AWS VPC service.
  3. If you are using terraform on an ec2 instance, ensure you have a valid IAM role attached to the instance with VPC provisioning permissions.

Terraform AWS VPC Code Repository

AWS VPC terraform code is part of the terraform AWS repository. Clone it to your workstation to follow the guide.

git clone https://github.com/techiescamp/terraform-aws.git

Fork and clone the repository if you intend to reuse and make changes as per your requirements.

Terraform AWS VPC Creation Workflow

The VPC terraform code is structured in the following way.

├── infra
│   └── vpc
│       ├── main.tf
│       └── variables.tf
├── modules
│   └── vpc
│       ├── endpoint.tf
│       ├── internet-gateway.tf
│       ├── nacl.tf
│       ├── nat-gateway.tf
│       ├── outputs.tf
│       ├── route-tables.tf
│       ├── subnet.tf
│       ├── variables.tf
│       └── vpc.tf
└── vars
    └── dev
        └── vpc.tfvars

vars folder contains the variables file named vpc.tfvars . It is the only file that needs modification

The modules/vpc folder contains the following VPC related resources. All the resource provisioning logic is part of these resources.

  1. endpoint
  2. internet-gateway
  3. nacl
  4. nat-gateway
  5. route-tables
  6. subnet
  7. vpc

The infra/vpc/main.tf file calls all the vpc module with all the VPC resources using the variables we pass using the vpc.tfvars file

Create VPC Using Terraform

Note: The VPC and subnets for this demo is created based on our VPC design document. Please refer it if you want to understand how to design a VPC.

We will be creating the VPC with the following

  1. CIDR Block: 10.0.0.0/16
  2. Region: us-west-2
  3. Availability Zones: us-west-2a, us-west-2b, us-west-2c
  4. Subnets: 15 Subnets (One per availability Zone)
    • Public Sunets (3)
    • App Subets (3)
    • DB Subnets (3)
    • Management Subnet (3)
    • Platform Subnet (3)
  5. NAT Gateway for Private subnets
  6. Internet Gateway for public subnets.
  7. Enabled Endpoints: s3, Cloudwatch & Secrets Manager
  8. Dedicated NACLs for 4 set of subnets.

Follow the steps give below to create VPC using Terraform code.

Step 1: CD in the Cloned Repository

If you haven’t already cloned the repo, clone it using the following command.

git clone https://github.com/techiescamp/terraform-aws.git

Then cd in to the terraform-aws folder

cd terraform-aws

Step 2: Modify the vpc.tfvars

Note: Open the repository folder in your favorite IDE, as it makes editing and reviewing the code easier.

Modify the vars/dev/vpc.tfvars file as per your requirements. I have highlighted the key parameters in bold.

If you dont want the NAT gateway, set create_nat_gateway to false.

#vpc
region               = "us-west-2"
vpc_cidr_block       = "10.0.0.0/16"
instance_tenancy     = "default"
enable_dns_support   = true
enable_dns_hostnames = true

#elastic ip
domain = "vpc"

#nat-gateway
create_nat_gateway = true

#route-table
destination_cidr_block = "0.0.0.0/0"

#tags
owner       = "techiescamp"
environment = "dev"
cost_center = "techiescamp-commerce"
application = "ecommerce"

#subnet

map_public_ip_on_launch       = true

public_subnet_cidr_blocks     = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
app_subnet_cidr_blocks        = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"]
db_subnet_cidr_blocks         = ["10.0.7.0/24", "10.0.8.0/24", "10.0.9.0/24"]
management_subnet_cidr_blocks = ["10.0.10.0/24", "10.0.11.0/24", "10.0.12.0/24"]
platform_subnet_cidr_blocks   = ["10.0.13.0/24", "10.0.14.0/24", "10.0.15.0/24"]
availability_zones            = ["us-west-2a", "us-west-2b", "us-west-2c"]

#public nacl

ingress_public_nacl_rule_no    = [100]
ingress_public_nacl_action     = ["allow"]
ingress_public_nacl_from_port  = [0]
ingress_public_nacl_to_port    = [0]
ingress_public_nacl_protocol   = ["-1"]
ingress_public_nacl_cidr_block = ["0.0.0.0/0"]

egress_public_nacl_rule_no    = [200]
egress_public_nacl_action     = ["allow"]
egress_public_nacl_from_port  = [0]
egress_public_nacl_to_port    = [0]
egress_public_nacl_protocol   = ["-1"]
egress_public_nacl_cidr_block = ["0.0.0.0/0"]

#app nacl

ingress_app_nacl_rule_no    = [100]
ingress_app_nacl_action     = ["allow"]
ingress_app_nacl_from_port  = [0]
ingress_app_nacl_to_port    = [0]
ingress_app_nacl_protocol   = ["-1"]
ingress_app_nacl_cidr_block = ["0.0.0.0/0"]

egress_app_nacl_rule_no    = [200]
egress_app_nacl_action     = ["allow"]
egress_app_nacl_from_port  = [0]
egress_app_nacl_to_port    = [0]
egress_app_nacl_protocol   = ["-1"]
egress_app_nacl_cidr_block = ["0.0.0.0/0"]

##db nacl

ingress_db_nacl_rule_no    = [100]
ingress_db_nacl_action     = ["allow"]
ingress_db_nacl_from_port  = [0]
ingress_db_nacl_to_port    = [0]
ingress_db_nacl_protocol   = ["-1"]
ingress_db_nacl_cidr_block = ["0.0.0.0/0"]

egress_db_nacl_rule_no    = [200]
egress_db_nacl_action     = ["allow"]
egress_db_nacl_from_port  = [0]
egress_db_nacl_to_port    = [0]
egress_db_nacl_protocol   = ["-1"]
egress_db_nacl_cidr_block = ["0.0.0.0/0"]

##management nacl

ingress_management_nacl_rule_no    = [100]
ingress_management_nacl_action     = ["allow"]
ingress_management_nacl_from_port  = [0]
ingress_management_nacl_to_port    = [0]
ingress_management_nacl_protocol   = ["-1"]
ingress_management_nacl_cidr_block = ["0.0.0.0/0"]

egress_management_nacl_rule_no    = [200]
egress_management_nacl_action     = ["allow"]
egress_management_nacl_from_port  = [0]
egress_management_nacl_to_port    = [0]
egress_management_nacl_protocol   = ["-1"]
egress_management_nacl_cidr_block = ["0.0.0.0/0"]

#platform nacl

ingress_platform_nacl_rule_no    = [100]
ingress_platform_nacl_action     = ["allow"]
ingress_platform_nacl_from_port  = [0]
ingress_platform_nacl_to_port    = [0]
ingress_platform_nacl_protocol   = ["-1"]
ingress_platform_nacl_cidr_block = ["0.0.0.0/0"]

egress_platform_nacl_rule_no    = [200]
egress_platform_nacl_action     = ["allow"]
egress_platform_nacl_from_port  = [0]
egress_platform_nacl_to_port    = [0]
egress_platform_nacl_protocol   = ["-1"]
egress_platform_nacl_cidr_block = ["0.0.0.0/0"]

#endpoint

create_s3_endpoint              = true
create_secrets_manager_endpoint = true
create_cloudwatch_logs_endpoint = true

Step 2: Initialize Terraform and Execute the Plan

Now cd in to infra/vpc folder and execute the terraform plan to validate the configurations.

cd infra/vpc

Initialize Terraform

terraform init

Execute the plan

terraform plan  -var-file=../../vars/dev/vpc.tfvars

You should see an output with all the resources that will be created by terraform.

Step 3: Create VPC With Terraform Apply

Lets create the VPC and related resources using terraform apply.

terraform apply  -var-file=../../vars/dev/vpc.tfvars

Step 4: Validate VPC

Head over to the AWS Console the check the Resource Map of the VPC.

Click on the created VPC and scroll down to view the Resource Map.

You should see 15 subnets , 6 route tables, internet gateway and NAT gateway as shown beow.

Step 5: Cleanup the Resources

If you have created the VPC for learning purposes and wish to clean up the resources created by Terraform, execute the following command

terraform destroy  -var-file=../../vars/dev/vpc.tfvars

Real World Terraform Code Reference

If you want to understand how Terraform code is structured and maintained in a real-world project environment, you should refer to the modernisation platform repository.

It contains code and standards that are actually used in the infrastructure management of the UK Ministry of Justice platform.

Refer to the architecture decision document to understand the reasoning behind each design.

https://github.com/ministryofjustice/modernisation-platform

Conclusion

In this guide, we looked at creating aws VPC using terraform.

When implemented in real projects, you may need to consider more VPC options, like flow logs, peering connections, etc.

For state management, you should use remote backend with s3 with dynamoDB lock.

Also, tweak the Terraform code according to your requirements. If you want to gain more knowledge, go through each resource under the VPC module

If you face any errors or have any queries or suggestions, drop a comment below.

Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like