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

如何在Terraform中跨for_each资源引用子网ID创建NIC?

问题解决与优化方案

核心错误原因

你在创建NIC时错误使用了each.value.id,这里的each.value是var.regions中的对象(仅包含name、region、address_space属性),并没有id字段。正确做法是引用通过for_each创建的子网资源实例的ID。

修正后的完整代码

variable "regions" {
  type = map(object({
    name          = string
    region        = string
    address_space = string
  }))
  default = {
    "us-east-2" = {
      name          = "us-east-2"
      region        = "East US 2"
      address_space = "10.1.0.0/16"
    },
    "uk-south" = {
      name          = "uk-south"
      region        = "UK South"
      address_space = "10.2.0.0/16"
    },
    "aus-east" = {
      name          = "aus-east"
      region        = "Australia East"
      address_space = "10.3.0.0/16"
    }
  }
}

variable "resource-group" {
  default = "rg-vm"
}

# 虚拟网络:通过for_each遍历regions变量
resource "azurerm_virtual_network" "vnet" {
  for_each             = var.regions
  name                 = "vnet-${each.value.name}"
  location             = each.value.region
  resource_group_name  = var.resource-group
  address_space        = [each.value.address_space]
}

# 子网:引用对应区域的VNET,避免硬编码名称
resource "azurerm_subnet" "subnet-lan" {
  for_each             = var.regions
  name                 = "vnet-${each.value.name}-LAN"
  resource_group_name  = var.resource-group
  virtual_network_name = azurerm_virtual_network.vnet[each.key].name
  address_prefixes     = [cidrsubnet(each.value.address_space, 8, 1)]
}

# 网络接口:正确引用对应区域的子网ID
resource "azurerm_network_interface" "nic" {
  for_each             = var.regions
  name                 = "nic-${each.value.name}-ub-vm01"
  location             = each.value.region
  resource_group_name  = var.resource-group

  ip_configuration {
    name                          = "ipconfig1"
    subnet_id                     = azurerm_subnet.subnet-lan[each.key].id
    private_ip_address_allocation = "Dynamic"
  }
}

# 可选:添加VM资源,关联对应的NIC
resource "azurerm_linux_virtual_machine" "vm" {
  for_each               = var.regions
  name                   = "vm-${each.value.name}-01"
  resource_group_name    = var.resource-group
  location               = each.value.region
  size                   = "Standard_D2s_v3"
  admin_username         = "adminuser"
  network_interface_ids  = [azurerm_network_interface.nic[each.key].id]

  admin_ssh_key {
    username   = "adminuser"
    public_key = file("~/.ssh/id_rsa.pub")
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Premium_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts"
    version   = "latest"
  }
}

# 输出所有子网ID,depends_on可省略(Terraform自动处理依赖)
output "subnet_ids" {
  value = {
    for k, v in azurerm_subnet.subnet-lan : k => v.id
  }
}

关键修改点

  1. 子网关联VNET:将子网的virtual_network_name从硬编码的"vnet-${each.value.name}"改为azurerm_virtual_network.vnet[each.key].name,确保资源引用的准确性,避免命名规则变更引发错误。
  2. NIC引用子网ID:将subnet_id = each.value.id替换为azurerm_subnet.subnet-lan[each.key].id,直接引用对应区域的子网资源实例ID,这是Terraform关联资源的标准方式。
  3. 移除冗余依赖声明:output "subnet_ids"中的depends_on可以省略,Terraform会自动识别子网资源的依赖关系。

高效实现建议

  • 模块化拆分:如果后续需要扩展公共IP、安全组等资源,建议将VNET/子网、NIC、VM拆分为独立模块,提升代码复用性和可维护性。
  • 变量抽象:将VM规格、管理员用户名、SSH密钥路径等配置抽象为变量,方便批量修改。
  • 依赖自动化:Terraform会自动处理资源间的依赖关系,除非存在隐式依赖(如自定义脚本依赖资源创建),否则无需手动添加depends_on。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 03:12:03