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

Terraform创建Azure NIC与ASG关联时索引无效问题求助

Terraform Azure NIC与应用安全组(ASG)关联索引错误修复

问题说明

使用Terraform创建Azure网络接口(NIC)与应用安全组(ASG)关联时,现有代码中nic_asg_associations本地值未保留NIC的唯一标识键,且azurerm_network_interface_application_security_group_association资源的索引引用逻辑错误,导致执行时抛出无效索引错误,无法匹配到已创建的NIC资源。

错误根源

  1. nic_asg_associations仅提取了nic_name和asg_id,丢失了NIC资源的唯一键(格式为${vm.vm_name}-${nic.nic_name},如app1_node1-nic1)
  2. 关联资源的for_each键构造错误,使用了nic_name|asg_id,与NIC资源的键不匹配
  3. 引用NIC资源时使用了错误的索引值,未对应到NIC资源的实际键

修正后的代码实现

修正nic_asg_associations本地值

保留NIC的唯一键,确保每个ASG关联项能关联到正确的NIC:

locals {
  all_nics = {
    for vm in flatten([
      for vm_name, vm in var.virtual_machines: [
        for nic_name, nic in vm.networks : {
          vm_number      = vm.vm_num,
          vm_name        = vm_name,
          nic_name       = nic_name,
          subnet_value   = nic.subnet,
          nic_name_value = nic.nic_name
          asg_ids        = nic.asg_ids
        }
      ]
    ]) : "${vm.vm_name}-${vm.nic_name}" => vm
  }

  # 修正:保留NIC资源的唯一键,用于关联NIC资源
  nic_asg_associations = flatten([
    for nic_key, nic in local.all_nics : [
      for asg_id in nic.asg_ids : {
        nic_key  = nic_key,  # 保留NIC资源的唯一键
        asg_id   = asg_id
      }
    ]
  ])
}

修正azurerm_network_interface_application_security_group_association资源

使用包含NIC唯一键的nic_asg_associations构造for_each,并正确引用NIC资源:

resource "azurerm_network_interface_application_security_group_association" "nic_asg_association" {
  # 用nic_key和asg_id组合成唯一键,避免重复
  for_each = {
    for assoc in local.nic_asg_associations : 
    "${assoc.nic_key}|${assoc.asg_id}" => assoc
  }

  # 通过nic_key正确引用NIC资源
  network_interface_id          = azurerm_network_interface.nic[each.value.nic_key].id
  application_security_group_id = each.value.asg_id
}

完整修正后代码

variable "vm_prefix" {
  type    = string
  default = "test"
}

variable "virtual_machines" {
  default = {
      app1_node1 = {
        "vm_name" = "app"
        "vm_num"  = "1"
        networks = {
          nic1 = {
            "nic_name" = "app-1"
            "subnet"   = "/subscriptions/**/resourceGroups/pluto/providers/Microsoft.Network/virtualNetworks/pluto-infra/subnets/app-subnet"
            "asg_ids"  = ["/subscriptions/**/resourceGroups/pluto/providers/Microsoft.Network/applicationSecurityGroups/app-asg", "/subscriptions/**/resourceGroups/pluto/providers/Microsoft.Network/applicationSecurityGroups/db-asg"]
          },
        }
      },
    }
  }


variable "resource_group" {
  type    = string
  default = "test"
}

data "azurerm_resource_group" "rg" {
  name = var.resource_group
}

locals {
  all_nics = {
    for vm in flatten([
      for vm_name, vm in var.virtual_machines: [
        for nic_name, nic in vm.networks : {
          vm_number      = vm.vm_num,
          vm_name        = vm_name,
          nic_name       = nic_name,
          subnet_value   = nic.subnet,
          nic_name_value = nic.nic_name
          asg_ids        = nic.asg_ids
        }
      ]
    ]) : "${vm.vm_name}-${vm.nic_name}" => vm
  }

  nic_asg_associations = flatten([
    for nic_key, nic in local.all_nics : [
      for asg_id in nic.asg_ids : {
        nic_key  = nic_key,
        asg_id   = asg_id
      }
    ]
  ])
}

resource "azurerm_network_interface" "nic" {
  for_each            = local.all_nics
  name                = "${var.vm_prefix}-${each.value.nic_name}-nic"
  location            = "eastus"
  resource_group_name = var.resource_group

  ip_configuration {
    name                          = "${var.vm_prefix}-${each.value.nic_name}-ipconfig"
    subnet_id                     = each.value.subnet_value
    private_ip_address_allocation = "Dynamic"
  }
}


resource "azurerm_linux_virtual_machine" "vm" {
  depends_on                      = [azurerm_network_interface.nic]
  for_each                        = var.virtual_machines
  name                            = "${var.vm_prefix}-${each.value.vm_name}-${each.value.vm_num}"
  admin_username                  = "testadmin"
  admin_password                  = "test@1234522"
  disable_password_authentication = false
  location                        = "eastus"
  resource_group_name             = var.resource_group
  network_interface_ids           = [for nic_key, nic in azurerm_network_interface.nic : nic.id if startswith(nic_key, "${each.key}-")]
  size                            = "Standard_B2ms"

  os_disk {
    name                 = "${var.vm_prefix}-${each.value.vm_name}-${each.value.vm_num}-OSdisk"
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "RedHat"
    offer     = "RHEL"
    sku       = "82gen2"
    version   = "latest"
  }
}

resource "azurerm_network_interface_application_security_group_association" "nic_asg_association" {
  for_each = {
    for assoc in local.nic_asg_associations : 
    "${assoc.nic_key}|${assoc.asg_id}" => assoc
  }

  network_interface_id          = azurerm_network_interface.nic[each.value.nic_key].id
  application_security_group_id = each.value.asg_id
}

验证说明

修正后,nic_asg_associations会为每个NIC的每个ASG生成包含NIC唯一键的关联项,for_each使用nic_key|asg_id作为唯一标识,确保每个关联资源实例唯一,同时通过nic_key正确匹配到azurerm_network_interface.nic中的资源,解决索引无效问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:35:05