Create subnet per availability zone in aws through terraform
When building basic AWS network infrastructure for your application, many a times you need to create public and private subnets in each availability zone depending upon number of availability zones in the region.
Aws have many regions and each region have different number of availability zones and AWS is rigorously working on increasing its area by increasing number of availability zones. So, you cannot hard code the number of az’s per region and change the number of subnets.
So, for this Purpose you can use terraform and its property of count to create subnet per availability zone.
Here I will demonstrate how to create one public and one private subnet in each availability zone of any region. It will automatically count the az’s and create subnets for you.
Lets start with provider first, as it is specific to aws, we will define our provider as aws
provider.tf
provider "aws" {
region = "${var.region}"
}
Then we need to define remote state
terraform.tf
terraform {
backend "s3" {}
}data "terraform_remote_state" "state" {
backend = "s3"
config {
bucket = "${var.stateBucketName}"
region = "${var.stateBucketRegion}"
key = "${var.stateBucketKey}"
}
}
I am going with very simplest approach defining all components in different files which is easy to differentiate and easy to understand.
Now we define basic variables, you can add up more according to your requirement
variables.tf
variable "region" {
description = "AWS region"
}variable "stateBucketName" {
description = "S3 Bucket Name"
}variable "stateBucketRegion" {
description = "S3 Bucket Region"
}variable "stateBucketKey" {
description = "S3 Bucket Key"
}
Now we will define file vpc.tf which will contain a vpc and public and private subnets.
vpc.tf
data "aws_availability_zones" "available" {}resource "aws_vpc" "myVpc" {
cidr_block = "10.20.0.0/16"
enable_dns_hostnames = true
tags {
Name = "myVpc"
}
}resource "aws_subnet" "public_subnet" {
count = "${length(data.aws_availability_zones.available.names)}"
vpc_id = "${aws_vpc.myVpc.id}"
cidr_block = "10.20.${10+count.index}.0/24"
availability_zone = "${data.aws_availability_zones.available.names[count.index]}"
map_public_ip_on_launch = true
tags {
Name = "PublicSubnet"
}
}resource "aws_subnet" "private_subnet" {
count = "${length(data.aws_availability_zones.available.names)}"
vpc_id = "${aws_vpc.myVpc.id}"
cidr_block = "10.20.${20+count.index}.0/24"
availability_zone= "${data.aws_availability_zones.available.names[count.index]}"
map_public_ip_on_launch = false
tags {
Name = "PrivateSubnet"
}
}
In above code, the main part which is important is
data "aws_availability_zones" "available" {}
This line of code will return us all available availability zones for the region in which you are running the terraform.
Now you can just run the terraform by initializing the variables.
I ran this terraform in Mumai region and I got my vpc and subnets created in this region. It created 3 private and 3 public subnets in each availability zone.
You can get this code on github. https://github.com/maneet8/subnetperazterraform
By cloning you can just directly run the project by just passing region and bucket name to run.bash.
You can define your run.bash as
run.bash
#!/bin/bashterraform -v
echo "Initializing terraform...."
export TF_VAR_stateBucketName=$2
export TF_VAR_stateBucketRegion=$1
export TF_VAR_region=$1
export TF_VAR_stateBucketKey=vpcterraform init -input=false -backend-config "bucket=$TF_VAR_stateBucketName" -backend-config "key=$TF_VAR_stateBucketKey" -backend-config "region=$TF_VAR_stateBucketRegion"echo "Terraform plan...."
terraform plan -out=tfplan -input=falseecho "Updating Stack...."
terraform apply -input=false -auto-approve
And then you can run this with below command.
Note: “Please create bucket before passing to this command in same region”
$ ./run.bash ap-south-1 testterraformxyza
Then you can see all the configuration created in Mumbai region like this:
I hope this will definitely help you a lot and saves a lot in code maintenance.