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

如何在Terraform中传递for_each创建的资源属性至其他资源?

解决Terraform批量创建Azure Bastion Host时的资源引用问题

你的核心问题是:通过for_each批量创建的子网和公网IP是资源集合(map/set类型),而非单个资源,直接调用.id会触发Terraform错误,必须通过对应的键来索引到集合中的具体资源实例。

关键前提确认

确保以下变量的元素/键完全对应(比如都以Azure区域名称作为标识):

  • var.bastion_subnet:建议是以区域名为key的map(比如{"eastus" = {...}, "westus" = {...}}),这样每个区域对应一个Bastion子网
  • var.public_ip_location:包含的区域名和var.bastion_subnet的key一致
  • var.location_list:包含的区域名和前两者完全匹配

修改后的Bastion Host配置

resource "azurerm_bastion_host" "bastion" {
  for_each            = toset(var.location_list)
  name                = "bastion-${each.value}"
  location            = each.value
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                 = "configuration"
    # 通过each.key(当前区域名)索引到对应区域的Bastion子网
    subnet_id            = azurerm_subnet.AzureBastionSubnet[each.key].id
    # 同样通过each.key索引到对应区域的公网IP
    public_ip_address_id = azurerm_public_ip.bastion_public_ip[each.key].id
  }

  # 可选:Terraform会自动推断依赖,这个depends_on可以省略
  # depends_on = [azurerm_public_ip.bastion_public_ip]
}

原理说明

  1. 当用for_each创建资源时,Terraform会生成一个资源集合:
    • azurerm_subnet.AzureBastionSubnet是map类型,key为var.bastion_subnet的每个键(即区域名)
    • azurerm_public_ip.bastion_public_ip是set类型,但由于用区域名作为元素,也可以通过区域名直接索引
  2. 在Bastion Host的for_each循环中,each.key(或each.value,因为是set类型两者相同)代表当前循环的区域名,用它作为索引就能精准获取对应区域的子网和公网IP的ID。

额外优化建议

如果你的var.bastion_subnet、var.public_ip_location、var.location_list内容重复,可以合并为一个变量,进一步保证一致性:

variable "bastion_regions" {
  type = map(object({
    subnet_name         = string
    subnet_addresses    = list(string)
  }))
  default = {
    "eastus" = {
      subnet_name      = "AzureBastionSubnet"
      subnet_addresses = ["10.0.1.0/26"]
    },
    "westus" = {
      subnet_name      = "AzureBastionSubnet"
      subnet_addresses = ["10.0.2.0/26"]
    }
  }
}

然后所有资源的for_each都指向这个变量:

resource "azurerm_subnet" "AzureBastionSubnet" {
  for_each             = var.bastion_regions
  name                 = each.value["subnet_name"]
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet[each.key].name
  address_prefixes     = each.value["subnet_addresses"]

  depends_on = [azurerm_virtual_network.vnet]
}

resource "azurerm_public_ip" "bastion_public_ip" {
  for_each            = var.bastion_regions
  name                = "bastion-public-ip-${each.key}"
  location            = each.key
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Static"
  sku                 = "Standard"

  depends_on = [azurerm_subnet.AzureBastionSubnet]
}

resource "azurerm_bastion_host" "bastion" {
  for_each            = var.bastion_regions
  name                = "bastion-${each.key}"
  location            = each.key
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                 = "configuration"
    subnet_id            = azurerm_subnet.AzureBastionSubnet[each.key].id
    public_ip_address_id = azurerm_public_ip.bastion_public_ip[each.key].id
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 20:01:33