Terraform — AWS VPC with Private, Public Subnets with NAT

Prashant Bhatasana
AppGambit
Published in
5 min readJul 2, 2020

Terraform is so popular nowadays. Terraform enables you to create and manage infrastructure with code and codes can be stored in version control.

In this article, We are not discussing what is terraform and what are the advantages of Terraform or how can I install it.

Please refer following links

we are creating 1 VPC, multiple subnets(Public and Private), 1 Internet gateway, 1 security group, In addition, we will create Custom Route Tables and associate them with subnets with NAT gateway support.

Let's start our Tutorial!

Pre-Requisites To Creating Infrastructure on AWS Using Terraform

  • We require AWS IAM API keys (access key and secret key) for creating and deleting permissions for all AWS resources.
  • Terraform should be installed on the machine. If Terraform does not exist you can download and install it from here.

Amazon Resources Created Using Terraform

  1. AWS VPC with 10.0.0.0/16 CIDR.
  2. Multiple AWS VPC public subnets would be reachable from the internet; which means traffic from the internet can hit a machine in the public subnet.
  3. Multiple AWS VPC private subnets which mean it is not reachable to the internet directly without NAT Gateway.
  4. AWS VPC Internet Gateway and attach it to AWS VPC.
  5. Public and private AWS VPC Route Tables.
  6. AWS VPC NAT Gateway.
  7. Associating AWS VPC Subnets with VPC route tables.

Let’s Start!

1. Create a “provider.tf”

This is the provider file that tellTerraform to which provider you are using.

All infrastructure will be on the AWS because of provider “aws”. If you want to use another cloud provider such as GCP or Azure, you need to change this.

provider "aws" {
region = "${var.region}"
}

We already declared the region of AWS that we are creating a VPC network.

you can declare profile also if you are working on multiple AWS accounts.

`profile = “<PROFILE NAME>”

by default, it will take your default profile.

2. Create “variables.tf”

All variables will be in this file. Now, there is only one region but there will be more…

variable "region" {
description = "AWS Deployment region.."
default = "us-east-1"
}

If you are using terraform.tfvars you just need to add a description only.

3. Create “terraform.tfvars

To persist variable values, create a file, and assign variables within this file. Create a file named terraform.tfvars with the following contents:

region = "us-east-2"

For all files which match terraform.tfvars or *.auto.tfvars present in the current directory, Terraform automatically loads them to populate variables. If the file is named something else, you can use the -var-file flag directly to specify a file.

Personally, I don’t recommend saving usernames and password to version control, but you can create a local secret variables file and use -var-file to load it.

4. Create “modules > Networking” Folder

A module is a container for multiple resources that are used together. Modules can be used to create lightweight abstractions, so that you can describe your infrastructure in terms of its architecture, rather than directly in terms of physical objects.

5. Create “Main.tf” in the Networking folder.

6. Create “variables.tf” in the Networking folder.

This is the same as the above variable.tf file just declare all variables that we are using in main.tf a file so we can use get all variables value from production.tf file.

7. Create “output.tf” in the Networking folder.

We can export any details from created resources and give that as an input of another module.

output "vpc_id" {
value = "${aws_vpc.vpc.id}"
}

We can access output value in another submodule like

vpc_cidr             = "${module.Networking.vpc_id}"

Check this for more detail

8. Create “production.tf”

Production. tf files in your working directory when you run terraform plan or terraform apply together form the root module. That module may call other modules and connect them by passing output values from one to the input values of another. To learn how to use modules, see the Modules configuration section.

module "networking" {source = "./modules/networking"
region = "${var.region}"
environment = "${var.environment}"
vpc_cidr = "${var.vpc_cidr}"
public_subnets_cidr = "${var.public_subnets_cidr}"
private_subnets_cidr = "${var.private_subnets_cidr}"
availability_zones = "${local.production_availability_zones}"
}

Now, We are ready to init!

Run `terraform init` that download all modules information and download terraform in your project file.

$ terraform init
Initializing modules...
Initializing the backend...Initializing provider plugins...The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.aws: version = "~> 2.54"
* provider.random: version = "~> 2.2"
Terraform has been successfully initialized!You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

After that, you can see the .terraform folder in your project directory that contains terraform setup and modules information.

terraform plan

The terraform plan a command is used to create an execution plan. Terraform performs a refresh, unless explicitly disabled, and then determines what actions are necessary to achieve the desired state specified in the configuration files.

This command is a convenient way to check whether the execution plan for a set of changes matches your expectations without making any changes to real resources or the state. For example, terraform plan might be run before committing a change to version control, to create confidence that it will behave as expected.

terraform apply

The terraform apply a command is used to apply the changes required to reach the desired state of the configuration, or the pre-determined set of actions generated by a terraform plan execution plan.

🎊 🎉🤖🎊 🎉 Our VPC Setup is ready on AWS.

Just you need to follow above all steps or clone this repository to start terraforming.

After cloning the repo, just run the following commands.

rename sample.terraform.tfvars to terraform.tfvars

change values of variables.

terraform init

terraform plan

terraform apply

Thank you for reading, if you have anything to add please send a response or add a note!

--

--

Prashant Bhatasana
AppGambit

AWS Community Builder | AWS Certified | Terraform Associate | DevOps Engineer, Love to work with #AWS #Terraform #Jenkins #Kubernetes #Docker #Ansible #Selenium