Terraform创建Azure VM引用共享镜像时version是否必填
问题背景
我近三周一直在使用Terraform,尝试在所属Azure账号中创建自托管GitHub Actions运行器。
我计划使用Azure Compute Gallery中存储的共享Windows VM镜像作为GitHub Actions运行器的基础镜像,但发现这类共享Windows VM镜像通常仅关联publisher、offer、SKU属性,并未像微软官方平台镜像那样关联可直接引用的version属性;我曾通过从现有VM新建镜像的操作验证该情况,确认并非是运维人员遗漏配置版本,而是共享镜像本身确实未挂载可直接通过数据源获取的version属性。
共享镜像示例如下:
我了解到Terraform中可通过azurerm_windows_virtual_machine和azurerm_virtual_machine两种资源创建VM,我分别使用两种资源测试运行器创建流程。
测试代码1:使用旧版azurerm_virtual_machine资源
data "azurerm_shared_image" "win19_gold_image" { provider = azurerm.gi name = "Windows-2019_base" gallery_name = data.azurerm_shared_image_gallery.cap_win_gold_image_gallery.name resource_group_name = "gi-rg" } resource "azurerm_virtual_machine" "win_runners_gold_image_based" { provider = azurerm.og name = "ga-win-gold-1" location = "East US" count = "1" # 按需调整VM数量 resource_group_name = data.azurerm_resource_group.dts_rg.name network_interface_ids = [azurerm_network_interface.azure_win_runner_gold_nic[count.index].id,] vm_size = "Standard_D4ads_v5" delete_os_disk_on_termination = true delete_data_disks_on_termination = true storage_image_reference { publisher = data.azurerm_shared_image.win19_gold_image.identifier[0].publisher offer = data.azurerm_shared_image.win19_gold_image.identifier[0].offer sku = data.azurerm_shared_image.win19_gold_image.identifier[0].sku # 此处报错:Error: compute.VirtualMachinesClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="InvalidParameter" Message="The value of parameter imageReference.version is invalid." Target="imageReference.version" } storage_os_disk { name = "ga-win-gold-os-disk-1" caching = "None" create_option = "FromImage" managed_disk_type = "StandardSSD_LRS" } os_profile { computer_name = "ga-win-gold-1" admin_username = "svc" admin_password = var.WINDOWS_ADMIN_PASS } os_profile_windows_config { enable_automatic_upgrades = true provision_vm_agent = true } storage_data_disk { name = "ga-win-gold-data-disk-1" caching = "None" create_option = "Empty" disk_size_gb = var.disk_size_gb lun = 0 managed_disk_type = "StandardSSD_LRS" } }
测试代码2:使用新版azurerm_windows_virtual_machine资源
data "azurerm_shared_image" "win19_gold_image" { provider = azurerm.gi name = "Windows-2019_base" gallery_name = data.azurerm_shared_image_gallery.cap_win_gold_image_gallery.name resource_group_name = "gi-rg" } resource "azurerm_windows_virtual_machine" "azure_win_runner" { provider = azurerm.og name = "vm-github-actions-win-${count.index}" resource_group_name = data.azurerm_resource_group.dts_rg.name location = "East US" size = var.windows-vm-size count = "${var.number_of_win_az_instances}" network_interface_ids = [ azurerm_network_interface.azure_win_runner_nic[count.index].id, ] computer_name = "vm-ga-win-${count.index}" admin_username = var.windows-admin-username admin_password = var.WINDOWS_ADMIN_PASS os_disk { name = "vm-github-actions-win-${count.index}-os-disk" caching = "None" storage_account_type = "StandardSSD_LRS" } source_image_reference { publisher = data.azurerm_shared_image.win19_gold_image.identifier[0].publisher offer = data.azurerm_shared_image.win19_gold_image.identifier[0].offer sku = data.azurerm_shared_image.win19_gold_image.identifier[0].sku version = data.azurerm_shared_image.win19_gold_image.identifier[0].version # 提示对象无version属性 # 手动填version = "latest"或其他版本号,apply时会报错版本不存在 } enable_automatic_updates = true provision_vm_agent = true }
报错汇总
- 使用
azurerm_virtual_machine资源时,若在storage_image_reference块中省略version配置,会收到如下报错:
Error: compute.VirtualMachinesClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="InvalidParameter" Message="The value of parameter imageReference.version is invalid." Target="imageReference.version"
- 若尝试添加version配置,则会收到如下报错:
Error: Unsupported attribute. This object does not have an attribute named "version".
- 使用
azurerm_windows_virtual_machine资源时,若移除version参数,Terraform会直接提示该参数为必填项;若手动填入1.0.0、latest这类版本字符串,执行terraform apply阶段会报错提示对应版本不存在;若尝试从data.azurerm_shared_image.cap_win19_gold_image数据源引用version属性,同样会报错提示该对象不存在version属性。
问题原因
这里存在两个核心认知误区:
azurerm_shared_image数据源仅返回镜像定义的基础元数据,不包含镜像版本信息。Azure Compute Gallery中的镜像版本是独立的子资源,和镜像定义分开管理,因此在这个数据源的返回值中永远无法获取version属性。source_image_reference/storage_image_reference块要求的publisher、offer、sku、version四参数组合,仅适用于Azure Marketplace公共镜像、第三方平台镜像,不支持Azure Compute Gallery中的自定义共享镜像。手动填入latest不生效也是这个原因,共享镜像不识别该版本别名。
解决方案
优先使用官方推荐的新版azurerm_windows_virtual_machine资源(旧版azurerm_virtual_machine已逐步废弃,不建议用于新部署),按以下步骤调整代码:
- 新增
azurerm_shared_image_versions数据源查询镜像下的所有可用版本,通过排序规则自动获取最新版;如果需要固定版本,可直接使用azurerm_shared_image_version数据源指定版本号。 - 删除VM资源中的
source_image_reference块,改用source_image_id参数,直接传入查询到的共享镜像版本的资源ID即可,无需再填写publisher、offer、sku、version四个字段。
修正后的核心代码示例(自动取最新镜像版本):
# 查询共享镜像定义 data "azurerm_shared_image" "win19_gold_image" { provider = azurerm.gi name = "Windows-2019_base" gallery_name = data.azurerm_shared_image_gallery.cap_win_gold_image_gallery.name resource_group_name = "gi-rg" } # 查询该镜像定义下的所有可用版本,按版本号倒序排序 data "azurerm_shared_image_versions" "win19_gold_image_versions" { provider = azurerm.gi name = data.azurerm_shared_image.win19_gold_image.name gallery_name = data.azurerm_shared_image.win19_gold_image.gallery_name resource_group_name = data.azurerm_shared_image.win19_gold_image.resource_group_name sort_descending = true } # 取排序后第一个结果,即最新版本的镜像ID locals { latest_gold_image_id = data.azurerm_shared_image_versions.win19_gold_image_versions.images[0].id } resource "azurerm_windows_virtual_machine" "azure_win_runner" { provider = azurerm.og name = "vm-github-actions-win-${count.index}" resource_group_name = data.azurerm_resource_group.dts_rg.name location = "East US" size = var.windows-vm-size count = var.number_of_win_az_instances network_interface_ids = [ azurerm_network_interface.azure_win_runner_nic[count.index].id, ] computer_name = "vm-ga-win-${count.index}" admin_username = var.windows-admin-username admin_password = var.WINDOWS_ADMIN_PASS os_disk { name = "vm-github-actions-win-${count.index}-os-disk" caching = "None" storage_account_type = "StandardSSD_LRS" } # 直接传入镜像版本ID,无需配置source_image_reference块 source_image_id = local.latest_gold_image_id enable_automatic_updates = true provision_vm_agent = true }
如果需要固定使用某个指定版本,可替换版本查询部分的代码:
data "azurerm_shared_image_version" "win19_gold_image_fixed" { provider = azurerm.gi name = "1.0.0" # 替换为实际需要使用的版本号 image_name = data.azurerm_shared_image.win19_gold_image.name gallery_name = data.azurerm_shared_image.win19_gold_image.gallery_name resource_group_name = data.azurerm_shared_image.win19_gold_image.resource_group_name } # VM中source_image_id直接引用data.azurerm_shared_image_version.win19_gold_image_fixed.id即可
如果坚持使用旧版
azurerm_virtual_machine资源,逻辑完全一致:删除storage_image_reference块中的四个自定义参数,新增id字段传入共享镜像版本的资源ID即可。
内容的提问来源于stack exchange,提问作者Sekhar Routray
相关产品推荐
相关产品推荐

