Creating multiple different Azure Win servers with managed disks using For_each argument

110 views Asked by At

New to terraform I've been using the count argument to create VMs in Azure. Best practices suggests using For_each argument over using count. I've encountered issues where I wanted to change certain servers configurations.

I've taken some code from peoples recommendations on here. In the code below, in it's current state it will create a managed disk for each vm.

However the managed disk is not independent in that if I change the disk size for the managed disk it will change it for all of the vm's. How can I accomplish to have different disk sizes per VM for managed disks. I did try adding the managed disks to a single key in the variables locals for each vm. However for some reason the plan was going to create two managed disks per vm?

Any pointers/advice would be greatly appreciated!

Under a subdirectory 
#########################################################################################
variable.tf

variable "m_resource_group_name" {
  description = "This is defines the resouce grp name"

}

variable "m_location" {
  description = "This is defines the location"

}

variable "m_subnet_id" {

    description = "The ID of the subnet "
  
}

variable "m_admin_username" {

    description = "admin username"
 
}

 variable "m_vault_name_id" {
   description = "Azure Key Vault data source"
  type        = object({
    id                 = string
    name               = string
    resource_group_name = string
  })
}

variable "winserver-test-pw" {
  description = "admin pw"
}

############################# NEW variable map #######################

variable "vm_map" {
description = "values for the server"
  type = map(object({
    name = string
    size = string
  }))
default = {
  "vm1" = {
    name = "vm1"
    size = "Standard_DC2ds_v3"
    nic = "nic1"
    
  }

  "vm2" = {
    name = "vm2"
    size = "Standard_DC2ds_v3"
    nic = "nic1"
    
  }
}
}

variable "disk_template" {
  type = map(any)
  default = {
    disk1 = {
      managed_disk_name    = "data-disk1"
      managed_disk_type    = "StandardSSD_LRS"
      managed_disk_size    = "10"
      managed_disk_lun     = "2"
      managed_disk_caching = "ReadWrite"
      create_option        = "Empty"
      os_type              = "Windows"
    }
  }
}
#####################################################################################################
locals.tf
# Managed Disk

locals {
  disk_vm_flat = merge([
    for vm, vm_vals in var.vm_map : {
      for disk, disk_vals in var.disk_template :
      "${vm_vals.name}-${disk_vals.managed_disk_name}" =>  {
        name                 = vm_vals.name
        managed_disk_name    = disk_vals.managed_disk_name
        managed_disk_size    = disk_vals.managed_disk_size
        managed_disk_lun     = disk_vals.managed_disk_lun
        managed_disk_type    = disk_vals.managed_disk_type
        managed_disk_caching = disk_vals.managed_disk_caching
        os_type              = disk_vals.os_type
        create_option        = disk_vals.create_option
      }  if disk_vals.managed_disk_size != "0"
    }
  ]...) # Do not remove the dots. 
}

#######################################################################################################

main.tf

resource "azurerm_network_interface" "nic-multi-vms-01" {
  for_each            = var.vm_map
  name                = "${each.value.name}-nic" #append the keyname to nic at the end
  location            = var.m_location
  resource_group_name = var.m_resource_group_name

  ip_configuration {
    name                          = "${each.value.name}-ipconf"
    subnet_id                     = var.m_subnet_id
    private_ip_address_allocation = "Dynamic"

  }
}


resource "azurerm_windows_virtual_machine" "winservertest" {


  for_each = var.vm_map
  name                 = each.value.name
  resource_group_name = var.m_resource_group_name
  location            = var.m_location
  size                = each.value.size
  admin_username      = var.m_admin_username
  admin_password      = var.winserver-test-pw
  patch_mode               = "Manual" 
  enable_automatic_updates = false 
  network_interface_ids = [
    azurerm_network_interface.nic-multi-vms-01[each.key].id
  ]
  

os_disk {
    name = "${each.value.name}-OS"
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
    disk_size_gb         = 127
  }

source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2019-Datacenter"
    version   = "latest"
  }
}


resource "azurerm_managed_disk" "managed_disk" {
  for_each = local.disk_vm_flat
  name     = "${each.value.name}-${each.value.managed_disk_name}"
  location             = var.m_location
  resource_group_name  = var.m_resource_group_name
  storage_account_type = each.value.managed_disk_type
  create_option        = each.value.create_option
  os_type              = each.value.os_type
  disk_size_gb         = each.value.managed_disk_size
}

resource "azurerm_virtual_machine_data_disk_attachment" "disk_attach" {
  for_each = local.disk_vm_flat
  managed_disk_id = azurerm_managed_disk.managed_disk[each.key].id
  lun             = each.value.managed_disk_lun
  caching         = each.value.managed_disk_caching
  virtual_machine_id = azurerm_windows_virtual_machine.winservertest[each.value.name].id #amended
}



# ############################
# ### output info
# ############################

output "vm_ids" {
  value = { for vm, vm_vals in var.vm_map : vm => vm_vals }
}




1

There are 1 answers

2
Marcin On

This happens because you have one disk_template for all VMs. If you want to have different disk sizes for each vm, you have to move your managed_disk_size into var.vm_map. This way you can have different disk sizes for different VMs.