The Terraform count meta argument allows you to deploy multiple resources using the same Terraform configuration block. This is useful when you need to deploy things like virtual machines (perhaps for Azure Virtual Desktop), which have the same configuration.
Usually, when you write a Terraform resource block, it will be to deploy a single resource. The terraform count and terraform for_each meta arguments offer ways to deploy a resource block multiple times. Count works by adding a count parameter to a resource block:
count = 3 # Deploy 3 of these Virtual Machines please!
The count
meta argument replicates the resource or module a specific number of times with an incrementing counter. It is ideal for resources that are intended to be near identical. When you deploy resources with count, there is a count index (starting at zero) which is assigned for each instance of the resource deployed. Let’s look at a practical example of how count can be used when deploying virtual machines (in this example, in Azure).
Using the Terraform Count Meta Argument
The idea here is to demonstrate how count can be used. The below examples are not a full terraform plan, just enough code to show how terraform count works. First of all, I have configured some variables. As I want to deploy multiple VMs, I am setting a name prefix –vm_name_pfx
-, so that each VM deployed will be named consistently. As the deployed virtual machine resources will be identical, we need a way to give each instance a unique name. One way to do so is to use a prefix to make up part of the name, along with count index, which will append the index number thereby making the name unique.
variable "vm_name_pfx" {
description = "VM Names"
default = "test-vm-"
type = string
}
variable "vm_count" {
description = "Number of Virtual Machines"
default = 3
type = string
}
I have also set a vm_count
variable – which is simply the number of times I wish to deploy the resource. I have set this to ‘3’ which will result in 3 virtual machines being deployed. These variables are then used by my azurerm_windows_virtual_machine
resource block shown below:
resource "azurerm_windows_virtual_machine" "vm" {
count = var.vm_count # Count Value read from variable
name = "${var.vm_name_pfx}-${count.index}" # Name constructed using count and pfx
resource_group_name = azurerm_resource_group.rg.name
location = var.location
size = "Standard_F2"
admin_username = var.vm_admin_login
admin_password = var.vm_admin_password
tags = var.tags
network_interface_ids = [
azurerm_network_interface.nic[count.index].id,
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2016-Datacenter"
version = "latest"
}
}
First you will notice the count property, which will use the value in the vm_count
variable, which is set to ‘3’. I have also used the count index to help set the virtual machines name:
name = "${var.vm_name_pfx}-${count.index}"
As we have asked for 3 resources, this will result in 3 identical virtual machines with the following names:
test-vm-00
test-vm-01
test-vm-02
An important point to be aware of when using the terraform count argument is that if you have resources that are closely linked you have add the same count to that resource also. For example, with Azure Virtual Machines you have to create a NIC resource as well as the Virtual Machine resource. When using count we need a way to ensure that when we create 3 virtual machines, we also create 3 network interfaces.
To achieve this we add the same count statement to the corresponding network interface resource, which would look something like this:
resource "azurerm_network_interface" "nic" {
count = var.vm_count
name = "${var.vm_name_pfx}-${count.index}-nic"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
tags = var.tags
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.demo-subnet.id
private_ip_address_allocation = "Dynamic"
}
}
In the virtual machine resource we can link to this, but have to use the count index to ensure each virtual machine is linked to each corresponding network interface:
network_interface_ids = [
azurerm_network_interface.nic[count.index].id,
]
Summary
In this article you have learned how you can use the Terraform count meta argument to deploy multiple copies of the same resource, which is useful when deploying resources such as virtual machines and is an alternative to using terraform for_each loops. For more information on terraform count check out the official documentation here.