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

Terraform从含数据磁盘的Azure通用镜像创建VM报错及恢复方法

问题:使用Terraform从带数据磁盘的Azure通用镜像创建VM时出现400错误

我制作了一个附加独立数据磁盘的Windows虚拟机通用镜像,在Azure门户中可正常创建包含该数据磁盘的资源,但使用Terraform代码创建时出现如下400错误:

Virtual Machine Name: "test-vm"): performing CreateOrUpdate: unexpected status 400 (400 Bad Request) with error: InvalidParameter: StorageProfile.dataDisks.lun does not have required value(s) for image specified in storage profile.
│
│   with azurerm_windows_virtual_machine.vm["vm1"],
│   on vm.tf line 67, in resource "azurerm_windows_virtual_machine" "vm":
│   67: resource "azurerm_windows_virtual_machine" "vm" {

用户提供的代码

var.tf

############################
### Location & Network 
############################
### Location
variable "location" {
  type      = string
  default   = "Korea Central"
}

### Resource Group Valiable - Network
variable "network_rg" {
  type      = string
  default   = "test-vm-rg"
}

### Virtual Network Valiable
variable "network_vnet" {
  type      = string
  default   = "vnet-test-vm"
}

### Subnet Valiable
variable "network_subnet" {
  type      = string
  default   = "subnet-test-vm"
}

### Private IP Setting
variable "private-ip-type" {
  type    = string
  default = "Static"
}

############################
### Resource & OS env
############################
### Resource Group
variable "system_rg" {
  type    = string
  default = "test-vm-d-rg"
}

############################
### Image Information
############################
### Image Publisher
variable "vm_template" {
  type = map(any)
  default = {
    vm1 = {
      source_image_id = "/subscriptions/0000000000000/resourceGroups/test-vm-rg/providers/Microsoft.Compute/images/vm-test-vm-image-v1"
      vm_name      = "test-vm"
      hostname     = "test-vm"
      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_D2s_v5"
      adminid      = "testadmin"
      private_ip   = "10.10.10.10"
      nic          = "nic01"
      os_disk      = "osdisk01"
    }
  }
}

vm.tf

data "azurerm_resource_group" "system_rg_name" {
  name = var.system_rg
}

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
  accelerated_networking_enabled = 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
  source_image_id     = each.value.source_image_id
  license_type        = each.value.license_type
  size                = each.value.vm_type
  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
  }

  computer_name  = each.value.hostname
  admin_username = each.value.adminid
  admin_password = data.azurerm_key_vault_secret.password.value
  timezone       = "Korea Standard Time"

}

解决方案

错误原因

你的通用镜像包含数据磁盘,但当前Terraform代码仅定义了OS磁盘配置,未声明镜像中的数据磁盘信息。Azure API要求创建VM时必须匹配镜像中数据磁盘的LUN值,因此触发StorageProfile.dataDisks.lun缺失的参数错误。

修改后的代码(vm.tf)

通过添加data "azurerm_image"获取镜像元数据,再用dynamic "data_disk"块自动生成数据磁盘配置,确保与镜像的LUN值一致:

data "azurerm_resource_group" "system_rg_name" {
  name = var.system_rg
}

data "azurerm_subnet" "network_subnet" {
  name                 = var.network_subnet
  virtual_network_name = var.network_vnet
  resource_group_name  = var.network_rg
}

# 加载镜像元数据,获取数据磁盘配置
data "azurerm_image" "vm_image" {
  for_each = var.vm_template
  # 从source_image_id拆分镜像名称和资源组
  name                = split("/", each.value.source_image_id)[length(split("/", each.value.source_image_id)) - 1]
  resource_group_name = split("/", each.value.source_image_id)[4]
}

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
  accelerated_networking_enabled = 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
  source_image_id     = each.value.source_image_id
  license_type        = each.value.license_type
  size                = each.value.vm_type
  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
  }

  # 动态生成数据磁盘配置,匹配镜像中的LUN、大小、缓存策略
  dynamic "data_disk" {
    for_each = data.azurerm_image.vm_image[each.key].storage_profile_data_disks
    content {
      lun                   = data_disk.value.lun
      caching               = data_disk.value.caching
      disk_size_gb          = data_disk.value.disk_size_gb
      storage_account_type  = each.value.osdisk_type # 可替换为自定义存储类型
      name                  = "${each.value.vm_name}-datadisk-${data_disk.value.lun}"
    }
  }

  computer_name  = each.value.hostname
  admin_username = each.value.adminid
  admin_password = data.azurerm_key_vault_secret.password.value
  timezone       = "Korea Standard Time"
}

说明

  1. data "azurerm_image":自动从source_image_id拆分镜像名称和所属资源组,加载镜像的完整配置,包括数据磁盘的LUN、大小、缓存方式等信息。
  2. dynamic "data_disk":遍历镜像中的所有数据磁盘,自动生成对应磁盘配置,确保每个数据磁盘的LUN值与镜像完全一致,满足Azure API参数要求。
  3. 若需自定义数据磁盘存储类型,可将storage_account_type替换为目标类型(如Premium_LRS),无需修改LUN值。

内容的提问来源于stack exchange,提问作者gotothesky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:27:03