The following code snippets show how to create three private subnets in AWS using terraform with ‘count’, ‘join’ and ’element’:

To start with the following variables were declared and set:

terraform.tfvars

base_cidr_block = "192.168.0.0/16"
node_count      = 3
availability_zones = ["a", "b", "c"]

variables.tf

variable "base_cidr_block" {
  description = "The base of the address range to be used by the VPC and corresponding Subnets"
}

variable "availability_zones" {
  description = "A list containing 3 AZs"
  type        = list(string)
}

variable "node_count" {
  description = "The number of ec2 instances to deploy"
  type        = number
}

Three subnets are then created using a single resource block. The cidr_block parameter uses the cidr_block function, which (when combined with the count.index) creates three separate address ranges:

network.tf

resource "aws_subnet" "privlb_private_subnet" {
  count = 3 //Three subnets are required (across 3 AZs)  

  vpc_id = aws_vpc.ed_privlb_vpc.id
  cidr_block              = cidrsubnet(var.base_cidr_block, 8, count.index + 1)
  availability_zone       = join("", ["${var.region}", "${var.availability_zones[count.index]}"])
  map_public_ip_on_launch = false
}

To ensure that instances are then deployed evenly across subnets and availabilty zones, the element function is used:

instances.tf

resource "aws_instance" "ec2_instance" {
  count = var.node_count
  ami   = ami-123456789

  instance_type = t3.micro

  subnet_id = element(aws_subnet.privlb_private_subnet.*.id, count.index % 3)
}