loopsvirtual-machineazure-bicepavailability-zone

Bicep - allocate VM to Availability zone based on loop index


I am learning bicep and trying to get my head around loops. I have a basic integer based loop which will create x number of VMs based on the int value passed through as a parameter (aka if parameter value is 3, 3 VMs should be created). I am having trouble getting Bicep to allocate the VMs to the correct AZ. The code I have is below:

param location string
param vmname string
param tags object
param OSVersion string 
param compName string
param username string
@secure()
param password string
param vmCount int


resource virutalmachine 'Microsoft.Compute/virtualMachines@2022-03-01' = [for i in 
range(1, vmCount): {
name: '${vmname}${i}'
location: location
tags: tags

properties: {
  hardwareProfile: {
    vmSize: 'Standard_D2as_v4'
  }

  osProfile: {
    computerName: compName
    adminUsername: username
    adminPassword: password
  }

  storageProfile: {
    imageReference: {
      publisher: 'MicrosoftWindowsServer'
      offer: 'WindowsServer'
      sku: OSVersion
      version: 'latest'
    }

   osDisk: {
      createOption: 'FromImage'
      diskSizeGB: 128
      managedDisk: {
          storageAccountType: 'StandardSSD_LRS'
        }
      }
    }

  networkProfile: {
    networkInterfaces: [
        {
        id: nic[i].id
        }
      ]
    }
  }

zones: [
 '${i}'
 ]

}]

resource nic 'Microsoft.Network/networkInterfaces@2022-01-01' = 
[for i in range(0, vmCount): {
name: '${nicname}${i}'
location: location

properties: {
  ipConfigurations:[
    {
      name: 'ipconfig1'
      properties: {
        privateIPAllocationMethod: 'Dynamic'
        subnet: {
          id: subnetID
        }
  
      }
    }
  ]

  networkSecurityGroup: {
    id: nsgID
    }

  }
}]

Solution

  • Where an indeterminate number of VMs should be deployed in to alternate AZs, where there are 3 AZs, based on the iteration of a loop, the only modification required to the above code is:

    zones: [string(i % 3 + 1)]
    

    Assuming you're not trying to deploy thousands of VMs, or some other weird edge case, this will cycle through the AZs 1, 2, 3, 1, 2, 3, 1... etc. as your loop iterates.

    You can see this with the following bicep:

    var zero = 0
    var one = 1
    var two = 2
    var three = 3
    var four = 4
    var five = 5
    var six = 6
    var seven = 7
    
    
    output out_zero string = string(zero % 3 + 1)
    output out_one string = string(one % 3 + 1)
    output out_two string = string(two % 3 + 1)
    output out_three string = string(three % 3 + 1)
    output out_four string = string(four % 3 + 1)
    output out_five string = string(five % 3 + 1)
    output out_six  string = string(six % 3 + 1)
    output out_seven  string = string(seven % 3 + 1)
    

    This will output the following:

    OutputsString           : 
                              Name             Type                       Value
                              ===============  =========================  ==========
                              out_zero         String                     "1"
                              out_one          String                     "2"
                              out_two          String                     "3"
                              out_three        String                     "1"
                              out_four         String                     "2"
                              out_five         String                     "3"
                              out_six          String                     "1"
                              out_seven        String                     "2"
    

    HTH someone.