You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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. 安全扩容磁盘的操作步骤

  1. 修改var.tf中disk_template的managed_disk_size值(例如从12改为20)
  2. 执行terraform plan,确认只有azurerm_managed_disk资源会被更新,无VM相关变更
  3. 执行terraform apply,此时仅会扩容磁盘,不会触发VM重启
  4. 登录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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 08:15:54