Consider that you need to create multiple instances of a particular resource using Terraform.

How do you go about it?

You may think of declaring multiple resource blocks, using a for_each loop or exploring a third option that’s probably the best bet.

Yes, I’m talking about the Terraform count meta-argument.

In this post, I will discuss when and how you can use the Terraform count to simplify your configuration. Also, I will answer a few frequently asked questions about the count meta-argument.

1 – What is Count in Terraform?

Count is a meta-argument defined by the Terraform language. You can use it with modules as well as other resource types.

But why do we use count in Terraform?

The count argument accepts a whole number as input and creates that many instances of the resource or module where you specify it.

Let’s understand with the help of an example.

resource "aws_instance" "hello_aws" {
    ami = data.aws_ami.ubuntu.id
    instance_type = "t2.micro"
    count = 3
    tags = {
        Name = "HelloAWS ${count.index}"
    }
}

Here, we have a Terraform resource block that creates an AWS EC2 instance.

If you had to create 3 similar instances with the same AMI Id and Instance Type, you could simply add the count meta-argument to the Terraform resource block. When Terraform applies this configuration, it will provision 3 EC2 instances.

Terraform Count Index

Notice the tags section where we use a special property count.index.

In blocks where you use the count meta-argument, you get access to a special object known as count. This object has only one property i.e. index.

Basically, Count Index is an index number that corresponds to a particular instance. It starts with 0. So, in this case, the index values will be 0, 1 & 2.

2 – Terraform Count with Modules

You can also use the Count Meta-argument with Terraform modules just like you did with resources.

Here’s an example of the same:

module "ec2_instances" {
  source  = "terraform-aws-modules/ec2-instance/aws"
  version = "3.5.0"
  count   = 3

  name = "demo-ec2-cluster"

  ami                    = "ami-0ceecbb0f30a902a6"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [module.vpc.default_security_group_id]
  subnet_id              = module.vpc.public_subnets[0]

  tags = {
    Terraform   = "true"
    Environment = "development"
  }

As you can see, the Count argument is set to a value of 3 for the Terraform registry module for the EC2 instance.

Overall, the impact will be the same. When you apply this configuration, Terraform will provision 3 EC2 instances.

In case you are interested, you can check out this detailed post on how to use Terraform registry modules to build an EC2 cluster.

3 – Terraform Count Meta-argument FAQs

Despite the simplicity of the Terraform count meta-argument, I have seen a lot of queries that people have about its usage.

Here, I have compiled a few frequently asked questions to act as a reference point.

Can we use an expression in the Count argument?

Yes, the count meta-argument accepts numeric expressions. However, the value of these expressions should be known at runtime. Terraform cannot refer to any resources for which values are known only after the configuration is applied.

Here’s an example of using a numeric expression in the Terraform count meta-argument.

variable "instance_types" {
  default = ["t2.micro", "t2.small", "t2.medium"]
}

resource "aws_instance" "example" {
  count = length(var.instance_types)

  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = var.instance_types[count.index]
}

As you can see, the count property is set to the result of the length function applied to the instance_types variable.

Terraform will create one EC2 instance for each element in the instance_types list and each instance will have the corresponding instance_type value from the list.

What’s the difference between Terraform count and for_each?

Both count and for_each are used to manage multiple instances of a Terraform resource.

The count property specifies the number of instances of a resource to create. For example, if you set the count property to 3, Terraform will create two instances of the resource. The count property is useful when you know the exact number of instances you want to create in advance.

On the other hand, the for_each property creates multiple instances of a resource based on a map or set data structure. This is particularly useful when you want to create resources based on a list of values such as a list of IP addresses and so on.

If the resources you are provisioning are identical or nearly identical, then Terraform count meta-argument is a great option as it is easy to use. However, if elements of the resources change between the different instances, then I recommend using for_each. If interested, you can read more about Terraform Data Source with for_each.

How to use Terraform Count with a Conditional?

You can also determine the value of the Terraform count meta-argument using a conditional statement.

Here’s an example of the same:

variable "create_instance" {
  default = true
}

resource "aws_instance" "example" {
  count = var.create_instance == true ? 1 : 0

  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

Based on the value of the create_instance variable, we set the value of the count variable to 1 or 0.

Can we use count in output?

No, the Terraform count meta-argument can only be used in “module”, “resource”, and “data” blocks, and only when the “count” argument is set.

Conclusion

It is a very common requirement to create multiple instances of a resource or a module in Terraform.

For similar instances, the Terraform Count meta-argument is the best possible choice.

If you liked this post or found it useful, consider sharing it with friends and colleagues. In case of any queries, please write them in the comments section below.

Categories: BlogTerraform

Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *