如何用Terraform实现Azure托管磁盘的单VM独占与多VM共享
问题分析
当前Terraform代码通过嵌套循环将每个VM与所有磁盘模板进行组合,导致共享磁盘(data-disk)被重复创建(每个VM对应一个),无法实现“1个共享盘供多VM使用”的需求。你的核心需求是:
- 每台VM对应1个专属localdisk(当前逻辑已满足)
- 仅创建1个data-disk,挂载到所有VM上
解决方案
核心思路是将磁盘分为**专属磁盘(max_shares=1)和共享磁盘(max_shares>1)**两类,分开处理磁盘创建和挂载逻辑:
修改后的managedisk.tf代码
locals { # 筛选专属磁盘(max_shares=1),并与每个VM组合 dedicated_disks_vm_map = merge([ for vm, vm_vals in var.vm_template : { for disk, disk_vals in var.disk_template : "${vm_vals.vm_name}-${disk_vals.managed_disk_name}" => { vm = vm vm_name = vm_vals.vm_name disk_key = disk 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 max_shares = disk_vals.max_shares } if disk_vals.managed_disk_size != "0" && disk_vals.max_shares == "1" } ]...) # 筛选共享磁盘(max_shares>1),单独处理 shared_disks = { for disk, disk_vals in var.disk_template : disk => disk_vals if disk_vals.managed_disk_size != "0" && disk_vals.max_shares != "1" } # 合并所有需要创建的磁盘:专属磁盘用VM+磁盘名作为key,共享磁盘用磁盘名作为key all_disks_to_create = merge( local.dedicated_disks_vm_map, { for k, v in local.shared_disks : v.managed_disk_name => v } ) # 生成共享磁盘的挂载组合:每个共享磁盘对应所有VM shared_disk_attachments = merge([ for disk, disk_vals in local.shared_disks : { for vm, vm_vals in var.vm_template : "${vm_vals.vm_name}-${disk_vals.managed_disk_name}" => { vm = vm vm_name = vm_vals.vm_name disk_key = disk managed_disk_name = disk_vals.managed_disk_name managed_disk_lun = disk_vals.managed_disk_lun managed_disk_caching = disk_vals.managed_disk_caching } } ]...) } # 创建托管磁盘:专属磁盘按VM+磁盘名创建,共享磁盘仅创建一次 resource "azurerm_managed_disk" "managed_disk" { for_each = local.all_disks_to_create name = contains(keys(local.shared_disks), each.value.disk_key) ? each.value.managed_disk_name : "${each.value.vm_name}-${each.value.managed_disk_name}" location = var.location resource_group_name = data.azurerm_resource_group.system_rg_name.name storage_account_type = each.value.managed_disk_type create_option = each.value.create_option max_shares = each.value.max_shares os_type = each.value.os_type disk_size_gb = each.value.managed_disk_size } # 挂载专属磁盘到对应VM resource "azurerm_virtual_machine_data_disk_attachment" "dedicated_disk_attach" { for_each = local.dedicated_disks_vm_map 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.vm[each.value.vm].id } # 挂载共享磁盘到所有VM resource "azurerm_virtual_machine_data_disk_attachment" "shared_disk_attach" { for_each = local.shared_disk_attachments managed_disk_id = azurerm_managed_disk.managed_disk[each.value.managed_disk_name].id lun = each.value.managed_disk_lun caching = each.value.managed_disk_caching virtual_machine_id = azurerm_windows_virtual_machine.vm[each.value.vm].id }
关键改动说明
- 拆分磁盘类型:通过
max_shares值区分专属/共享磁盘,避免共享磁盘被重复创建 - 磁盘创建逻辑:
- 专属磁盘:保留原VM+磁盘的组合命名,每个VM对应一个
- 共享磁盘:仅创建一次,直接使用磁盘模板中的名称
- 挂载逻辑拆分:
- 专属磁盘:仅挂载到对应的VM
- 共享磁盘:遍历所有VM,将同一个磁盘挂载到每台VM上
- 变量复用:保持原
var.tf的配置不变,无需修改模板定义
验证效果
执行terraform plan后,你会看到:
- 2个专属localdisk(test02-localdisk、test03-localdisk)
- 1个共享data-disk(data-disk)
- 2次专属磁盘挂载 + 2次共享磁盘挂载,共4条挂载记录
内容的提问来源于stack exchange,提问作者gotothesky
相关产品推荐
相关产品推荐

