Calculate azure availability zone from count.index

azurerm_linux_virtual_machine contains a “zone” key, where we can input a zone number such as 1, 2 or 3 for an azure vm. This works fine for a single VM. However, if I want to deploy n number of virtual machine and I add “count” variable in the resource, then how can I automatically calculate the zone key so that each VM is deployed on different zone.

Eg, I want to stand up 5 VMs
vm1- zone -1
vm2- zone -2
vm3- zone -3
vm4- zone -1
vm]5- zone -2

The element function is perfect for this due to the wrap-around feature

I reviewed it already. I was able to do this with this. However, it is static an I need this to be dynamic

variable “availability-zones” {
type = list(string)
default = [
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
“1”, “2”, “3”,
]
}

zone = element(var.availability-zones, (count.index))

Is there any way to perform some calculation and return the zone based on it?

1 Like

WIP, but not much recent progress from what I can see https://github.com/terraform-providers/terraform-provider-azurerm/issues/3025

Note that it’s enough to do

variable “availability-zones” {
  default = [
  “1”, “2”, “3”]
}

that’s what the wrap-around does in element()

One thing I’d note here (in addition to what you all have already been discussing) is that the AWS provider already has a data source for retrieving the set of availability zones in a given region for a given account, but in practical use it has had a tendency to be rather problematic:

An EC2 instance cannot move between availablity zones, so a change to availability zone for a given instance requires Terraform to replace that instance. This is problematic when the availability zones are set dynamically based on the current set available in the region, because that set can change over time and suddenly cause all or almost all of your instances to be planned for replacement just to redistribute them over the availability zones again.

In theory we can add availability_zone to ignore_changes to mitigate that, but I’ve seen folks more commonly just snapshot a fixed set of availability zones in their configuration and then respond to the addition of new availability zones later by an explicit configuration change. That way, the change can be made with intention, rather than potentially showing up at an inconvenient moment.

I realize that you all were talking about Azure rather than AWS, but I just wanted to raise that since the issue @bentterp linked to seems to be for an Azure provider feature analogous to that existing AWS provider feature.


Another option, which I’d favor for most situations, is to have Terraform manage a scale set rather than managing individual instances. With that approach, the allocation of VMs to availability zones can be handled by the autoscale service rather than by Terraform, and so it can respond to dynamic changes in the remote system such as an availability zone outage.

For Azure, we can set zone_balance on the scale set to instruct Azure to distribute instances evenly over zones.

why i am getting this error.

zones = element([“1”,“2”,“3”], count.index)

Error: Incorrect attribute value type

│ on vm.tf line 11, in resource “azurerm_virtual_machine” “vm”:
│ 11: zones = element([“1”,“2”,“3”], count.index)
│ ├────────────────
│ │ count.index is 0

│ Inappropriate value for attribute “zones”: list of string required.

zones = [element([“1”,“2”,“3”], count.index)] — This will work fine.