使用Terraform扩容Azure虚拟机磁盘触发重启的解决方案咨询
Azure Terraform扩容管理磁盘避免VM重启的解决方案
问题描述
通过Azure Portal扩容管理磁盘时无需重启虚拟机,但使用Terraform扩容管理磁盘时却触发了重启。当前使用单独的Terraform代码创建磁盘,寻求避免重启的解决方案。
当前代码
vm.tf
data "azurerm_resource_group" "system_rg_name" { name = azurerm_resource_group.system_rg.name } data "azurerm_subnet" "network_subnet" { name = var.network_subnet virtual_network_name = var.network_vnet resource_group_name = var.network_rg } resource "azurerm_network_interface" "nic" { for_each = var.vm_template name = "${each.value.vm_name}-${each.value.nic}" location = var.location resource_group_name = data.azurerm_resource_group.system_rg_name.name enable_accelerated_networking = true ip_configuration { name = "internal" subnet_id = data.azurerm_subnet.network_subnet.id private_ip_address_allocation = var.private-ip-type private_ip_address = each.value.private_ip } } resource "azurerm_windows_virtual_machine" "vm" { for_each = var.vm_template name = each.value.vm_name location = var.location resource_group_name = data.azurerm_resource_group.system_rg_name.name license_type = each.value.license_type size = each.value.vm_type additional_capabilities { ultra_ssd_enabled = true } network_interface_ids = [ azurerm_network_interface.nic[each.key].id, ] identity { type = "SystemAssigned" } os_disk { name = "${each.value.vm_name}-${each.value.os_disk}" caching = "ReadWrite" storage_account_type = each.value.osdisk_type disk_size_gb = each.value.osdisk_size } source_image_reference { publisher = each.value.os_publisher offer = each.value.os_offer sku = each.value.os_sku version = each.value.os_version } computer_name = each.value.hostname admin_username = each.value.adminid admin_password = data.azurerm_key_vault_secret.password.value timezone = "Korea Standard Time" lifecycle { ignore_changes = [ zone, ] } }
manageddisk.tf
locals { disk_vm_flat = 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 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" } ]...) } resource "azurerm_managed_disk" "managed_disk" { for_each = local.disk_vm_flat 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 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_linux_virtual_machine.vm[each.value.vm].id }
var.tf
variable "location" { type = string default = "Korea Central" } ### Resource Group Valiable - Network variable "network_rg" { type = string default = "" } ### Virtual Network Valiable variable "network_vnet" { type = string default = "" } ### Subnet Valiable variable "network_subnet" { type = string default = "" } ### Resource Group Valiable variable "system_rg" { type = string default = "testrg" } ### Private IP Setting variable "private-ip-type" { type = string default = "Static" } variable "vm_template" { type = map(any) default = { vm1 = { vm_name = "test01vm" hostname = "test01vm" os_publisher = "MicrosoftWindowsServer" os_offer = "WindowsServer" os_sku = "2022-datacenter-azure-edition" license_type = "Windows_Server" os_version = "latest" osdisk_type = "StandardSSD_LRS" osdisk_size = "128" vm_type = "Standard_D4s_v5" private_ip = "10.x.x.x" nic = "nic01" os_disk = "osdisk01" } vm2 = { vm_name = "test02vm" hostname = "test02vm" os_publisher = "MicrosoftWindowsServer" os_offer = "WindowsServer" os_sku = "2022-datacenter-azure-edition" license_type = "Windows_Server" os_version = "latest" osdisk_type = "StandardSSD_LRS" osdisk_size = "128" vm_type = "Standard_D4s_v5" private_ip = "10.x.x.x" nic = "nic01" os_disk = "osdisk01" } } } variable "disk_template" { type = map(any) default = { disk1 = { managed_disk_name = "localdisk" managed_disk_type = "StandardSSD_LRS" managed_disk_size = "12" managed_disk_lun = "1" managed_disk_caching = "ReadWrite" create_option = "Empty" os_type = "Windows" } } }
解决方案
1. 修正VM资源引用错误
当前manageddisk.tf中的磁盘挂载资源错误引用了Linux VM资源,而你的VM是Windows类型,这会导致Terraform执行时出现不必要的资源变更,触发VM重启。修改azurerm_virtual_machine_data_disk_attachment中的virtual_machine_id:
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 # 修正为Windows VM资源引用 virtual_machine_id = azurerm_windows_virtual_machine.vm[each.value.vm].id }
2. 确保磁盘与VM支持在线扩容
Azure支持在线扩容的前提:
- 磁盘类型:Standard SSD/HDD、Premium SSD、Ultra SSD(你的磁盘类型
StandardSSD_LRS符合要求) - VM系列:使用支持在线存储调整的VM大小(你的
Standard_D4s_v5属于Dv5系列,支持该特性) - 磁盘状态:磁盘已挂载到运行中的VM,且未处于快照或复制状态
3. 安全扩容磁盘的操作步骤
- 修改
var.tf中disk_template的managed_disk_size值(例如从12改为20) - 执行
terraform plan,确认只有azurerm_managed_disk资源会被更新,无VM相关变更 - 执行
terraform apply,此时仅会扩容磁盘,不会触发VM重启 - 登录Windows VM,通过磁盘管理工具或
diskpart命令扩展磁盘分区,使扩容后的空间可用
4. 可选:添加Lifecycle规则避免不必要变更
在azurerm_virtual_machine_data_disk_attachment资源中添加Lifecycle规则,确保磁盘属性变更不会触发挂载资源的重建:
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.vm[each.value.vm].id lifecycle { ignore_changes = [ # 磁盘大小变更不影响挂载资源,忽略该类变更 managed_disk_id, ] } }
内容的提问来源于stack exchange,提问作者gotothesky
相关产品推荐
相关产品推荐

