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
- Latest Terraform installed locally
- An AWS Account
- A HCP Terraform account with HCP Terraform locally authenticated.
- A HCP Terraform variable set configured with your AWS credentials.
- VS Code.
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