Scaling Infrastructure with count in Terraform

Introduction

The count argument allows you to create multiple instances of a resource or module, using an incrementing index. It’s most effective when the resources are identical or very similar.

In this tutorial, you'll use Terraform to provision a VPC, load balancer, and EC2 instances on AWS. You'll then apply the count argument to deploy multiple EC2 instances in each private subnet using a single resource block.

Requirements

Create infrastructure

  • Clone the Learn Terraform variables GitHub repository for this tutorial by running the following command:

git clone https://github.com/hashicorp-education/learn-terraform-count

  • Change to the repository directory.

cd learn-terraform-count

Create Infrastructure

Set the TF_CLOUD_ORGANIZATION environment variable to your HCP Terraform organization name. This will configure your HCP Terraform integration.

export TF_CLOUD_ORGANIZATION=

  • Run terraform init to initialize your configuration.

  • Run terraform apply to apply the configuration. This configuration has a limitation: each private subnet currently contains only one EC2 instance. Increasing the private_subnets_per_vpc variable won’t automatically create more instances, because the EC2 resources are hard-coded.

To make the configuration more flexible, introduce a variable to control the number of EC2 instances per private subnet, and use the count argument to dynamically create the appropriate number of instances.

Refactor the EC2 configuration

  • Refactor the EC2 configuration to make it more generic. Remove or comment out the entire block defining the app_b EC2 instance from main.tf.

  • Next, rename the resource for the other EC2 instance from app_a to app.

Declare a variable for instance number

Next, add the instances_per_subnet variable to variables.tf. This variable will define how many EC2 instances to launch in each private subnet.

variable "instances_per_subnet" {
  description = "Number of EC2 instances in each private subnet"
  type        = number
  default     = 2
}

Scale EC2 configuration with count

Next, update the main.tf file to use the count argument in the EC2 instance resource block. Multiply the number of private subnets by the instances_per_subnet variable to dynamically provision the correct number of instances.

count = var.instances_per_subnet * length(module.vpc.private_subnets)

subnet_id              = module.vpc.private_subnets[count.index % length(module.vpc.private_subnets)]

Each instance created using the count argument receives a unique count.index, starting from zero. This configuration uses count.index along with modulo division to assign each instance to a private subnet in a round-robin fashion.

With the default value of instances_per_subnet set to 2, Terraform will provision two EC2 instances for each private subnet.

Update the load balancer

Update the load balancer configuration in the elb_http block to attach the instances to the load balancer.

number_of_instances = length(aws_instance.app)

instances           = aws_instance.app.*.id

When you use count with a resource or module, its name refers to the entire collection of instances. For example, aws_instance.app represents all the EC2 instances created by that block. You can reference individual instances using index notation, such as aws_instance.app[0] for the first instance.

To retrieve a specific attribute from all instances, use the splat () operator. For example, aws_instance.app[].id returns a list of all instance IDs.

Now, update outputs.tf to reference the new aws_instance.app block instead of the individual app_a and app_b resources.

value = aws_instance.app.*.id

Apply scalable configuration

Apply this configuration now. Be sure to respond to the confirmation prompt with yes.

Terraform will output values for the VPC, load balancer, and instances.

You have now configured the number of EC2 instances per private subnet using the instances_per_subnet variable and the count argument. Terraform automatically provisioned the specified number of instances per subnet, assigned them appropriately, and attached them to the load balancer.

Thanks for staying till the end

0
Subscribe to my newsletter

Read articles from Chigozie Ozoemena directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Chigozie Ozoemena
Chigozie Ozoemena

Hi there! 👋 I'm Daniel Ozoemena, a passionate Cloud Solution Architect and DevOps Engineer dedicated to building scalable, secure, and innovative cloud solutions. With hands-on experience in Azure, AWS, and Google Cloud Platform, I specialize in deploying infrastructure as code, automating workflows, and optimizing system reliability. Driven by a love for problem-solving, I constantly explore new technologies and best practices to deliver impactful results. Beyond the cloud, I enjoy mentoring, blogging about tech insights, and contributing to open-source projects. When I'm not automating deployments or creating secure virtual networks, you can find me playing chess, learning about AI, or brainstorming solutions to real-world challenges. Let’s connect and grow together on this tech journey! 🚀