Terraform Basics Training Course
Working with Terraform
Count
In this article, we explore Terraform’s count meta-argument, demonstrating how it can be used to create multiple resource instances and discussing potential issues when modifying the underlying list used with count. This guide covers both static and dynamic count techniques to help you manage resources efficiently.
Creating Multiple Instances with a Static Count
One of the simplest ways to create multiple instances of a resource is by using a static count. Below is an example that creates three instances of a local file resource:
resource "local_file" "pet" {
filename = var.filename
count = 3
}
The variable is defined as follows:
variable "filename" {
default = "/root/pets.txt"
}
When you run terraform plan
, Terraform plans to create three resources:
$ terraform plan
[Output Truncated]
Terraform will perform the following actions:
...
# local_file.pet[2] will be created
+ resource "local_file" "pet" {
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "/root/pets.txt"
+ id = (known after apply)
}
Plan: 3 to add, 0 to change, 0 to destroy.
Each resource is indexed as pet[0]
, pet[1]
, and pet[2]
. Although three resources are created, all instances share the same file name, which means Terraform creates the same file three times rather than three unique files.
Creating Unique Resources by Using a List Variable
To generate unique resources, update the variable definition to a list and reference each element using count.index
. Here is the modified configuration:
resource "local_file" "pet" {
filename = var.filename[count.index]
count = 3
}
Define the list variable as follows:
variable "filename" {
default = [
"/root/pets.txt",
"/root/dogs.txt",
"/root/cats.txt"
]
}
In this configuration:
- The first iteration (index 0) creates
/root/pets.txt
. - The second iteration (index 1) creates
/root/dogs.txt
. - The third iteration (index 2) creates
/root/cats.txt
.
After executing terraform apply
, listing the /root
directory produces:
$ ls /root
pets.txt
dogs.txt
cats.txt
This confirms that each resource is now unique.
Dynamically Adjusting the Count with the length() Function
A drawback of the previous approach is its fixed count. If you wish to add more file names, the configuration would still create only three resources. To adapt dynamically to the number of elements, use the built-in length()
function:
resource "local_file" "pet" {
filename = var.filename[count.index]
count = length(var.filename)
}
You can now define the variable with any number of file names:
variable "filename" {
default = [
"/root/pets.txt",
"/root/dogs.txt",
"/root/cats.txt",
"/root/cows.txt",
"/root/ducks.txt"
]
}
When running terraform apply
, Terraform will automatically create five resources—one for each element in the list. To revert back to testing with three elements, simply modify the list back to three filenames:
variable "filename" {
default = [
"/root/pets.txt",
"/root/dogs.txt",
"/root/cats.txt"
]
}
After applying these changes, the /root
directory will properly contain the three files.
Caution
Modifying a list that drives the count parameter can lead to resource replacements due to index shifts. This may trigger unwanted service interruptions or data loss if the resources are critical.
A Pitfall: List Element Removal and Resource Replacement
When using count with a list, removing an element causes a shift in resource indices. Consider this configuration:
resource "local_file" "pet" {
filename = var.filename[count.index]
count = length(var.filename)
}
Initially, the variable is defined with three elements:
variable "filename" {
default = [
"/root/pets.txt",
"/root/dogs.txt",
"/root/cats.txt"
]
}
After a successful apply, Terraform recognizes three resources: pet[0]
, pet[1]
, and pet[2]
. Now, if you remove the first element (/root/pets.txt
), the updated variable becomes:
variable "filename" {
default = [
"/root/dogs.txt",
"/root/cats.txt"
]
}
Running terraform plan
now shows:
- The resource at index 0 is updated from
/root/pets.txt
to/root/dogs.txt
. - The resource at index 1 is updated from
/root/dogs.txt
to/root/cats.txt
. - The resource at index 2 is marked for destruction as there is no corresponding list element.
An abbreviated plan output looks like this:
$ terraform plan
...
# local_file.pet[0] must be replaced
-/+ resource "local_file" "pet" {
directory_permission = "0777"
file_permission = "0777"
~ filename = "/root/pets.txt" -> "/root/dogs.txt" #
}
# local_file.pet[1] must be replaced
-/+ resource "local_file" "pet" {
directory_permission = "0777"
file_permission = "0777"
~ filename = "/root/dogs.txt" -> "/root/cats.txt" #
}
# local_file.pet[2] will be destroyed
-/+ resource "local_file" "pet" {
directory_permission = "0777" -> null
file_permission = "0777" -> null
~ filename = "/root/cats.txt" -> null #
}
This behavior occurs because the resource indices are directly linked to the order of the list elements. Removing an element causes subsequent elements to shift, resulting in the unnecessary replacement or destruction of resources.
Viewing Resource Details
It is often useful to confirm resource details created with count. Adding an output variable lets you verify each resource's configuration:
output "pets" {
value = local_file.pet
}
After running terraform output
, you should see similar details for each resource:
$ terraform output
Outputs:
pets = [
{
"directory_permission" = "0777"
"file_permission" = "0777"
"filename" = "/root/pets.txt"
"id" = "da39a3ee5e6b4d3255bef95601890afd80709"
},
{
"directory_permission" = "0777"
"file_permission" = "0777"
"filename" = "/root/dogs.txt"
"id" = "da39a3ee5e6b4d3255bef95601890afd80709"
},
{
"directory_permission" = "0777"
"file_permission" = "0777"
"filename" = "/root/cats.txt"
"id" = "da39a3ee5e6b4d3255bef95601890afd80709"
},
]
This output confirms that Terraform manages the resources as a list, allowing each element to be accessed individually by its index.
Conclusion
In this article, we demonstrated how to use the count meta-argument in Terraform to create multiple resource instances. We examined both static and dynamic count methods using a list variable and the length()
function, respectively. Additionally, we discussed a common pitfall—removing an element from the list can trigger resource replacements due to index shifting.
Practice using the count meta-argument in your Terraform projects to automate resource creation and better manage infrastructure changes.
For more detailed information on Terraform and its resource management, refer to the Terraform Documentation.
Watch Video
Watch video content