Terraform中筛选Spoke VNet并解决对等配置的Count参数错误
Terraform配置Hub-Spoke VNet对等连接的count依赖问题
问题背景
需要获取Spoke网络的名称和ID,用于配置azurerm_virtual_network_peering。先后尝试两种方式均失败:
- 通过VNet输入的额外属性区分Hub和Spoke,无法将VNet名称、ID列表与VNet map(objects)结构结合
- 传入所有
azurerm_virtual_network资源到子模块筛选,同样无法解决依赖问题
尝试的配置(基于azurerm_resources数据源)
想用标签筛选Spoke网络,写出如下配置:
data "azurerm_resources" "spokes" { type = "Microsoft.Network/virtualNetworks" required_tags = { role = "spokeNetwork" } } resource "azurerm_virtual_network_peering" "peer-hub-spoke-eastus" { count = length(data.azurerm_resources.spokes.resources) name = "peer-hub-to-${data.azurerm_resources.spokes.resources[count.index].name}" resource_group_name = var.rg_network_name virtual_network_name = var.vnet_hub_name remote_virtual_network_id = data.azurerm_resources.spokes.resources[count.index].id allow_virtual_network_access = true allow_forwarded_traffic = true allow_gateway_transit = false }
遇到的错误
执行terraform plan时触发错误:
Error: Invalid count argument │ │ on modules\networking\modules\Fortigate\Active-Active-ELB-ILB\00-main.tf line 91, in resource "azurerm_virtual_network_peering" "peer-hub-spoke-eastus": │ 91: count = length(data.azurerm_resources.spokes.resources) │ │ The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on. ╵
试过用-target参数单独应用azurerm_resources和azurerm_virtual_network,问题没解决;换成for_each也会报类似错误。
可行解决方案
方案1:显式传入Spoke VNet元数据列表
在根模块定义变量,手动传入所有Spoke VNet的名称和ID:
variable "spoke_vnets" { type = list(object({ name = string id = string })) description = "要与Hub建立对等连接的Spoke虚拟网络列表" } resource "azurerm_virtual_network_peering" "peer-hub-spoke-eastus" { for_each = { for vnet in var.spoke_vnets : vnet.name => vnet } name = "peer-hub-to-${each.value.name}" resource_group_name = var.rg_network_name virtual_network_name = var.vnet_hub_name remote_virtual_network_id = each.value.id allow_virtual_network_access = true allow_forwarded_traffic = true allow_gateway_transit = false }
这种方式完全规避了数据源的依赖问题,Terraform在plan阶段就能明确知道要创建的对等连接数量。
方案2:逐个引用已知的Spoke VNet数据源
如果Spoke VNet的名称和资源组都是已知的,可以逐个定义数据源:
data "azurerm_virtual_network" "spoke1" { name = "spoke-vnet-1" resource_group_name = var.rg_spoke1_name } data "azurerm_virtual_network" "spoke2" { name = "spoke-vnet-2" resource_group_name = var.rg_spoke2_name } locals { spoke_vnets = [ data.azurerm_virtual_network.spoke1, data.azurerm_virtual_network.spoke2 ] } resource "azurerm_virtual_network_peering" "peer-hub-spoke-eastus" { for_each = { for vnet in local.spoke_vnets : vnet.name => vnet } name = "peer-hub-to-${each.value.name}" resource_group_name = var.rg_network_name virtual_network_name = var.vnet_hub_name remote_virtual_network_id = each.value.id allow_virtual_network_access = true allow_forwarded_traffic = true allow_gateway_transit = false }
适合Spoke VNet数量固定、名称明确的场景,plan阶段就能确定资源数量。
方案3:通过远程状态获取Spoke VNet信息
如果Spoke VNet是在其他Terraform栈中创建的,可以用terraform_remote_state拉取状态:
data "terraform_remote_state" "spokes" { backend = "azurerm" config = { resource_group_name = "tf-state-rg" storage_account_name = "tfstateaccount" container_name = "tfstate" key = "spokes.tfstate" } } locals { spoke_vnets = data.terraform_remote_state.spokes.outputs.spoke_vnets } resource "azurerm_virtual_network_peering" "peer-hub-spoke-eastus" { for_each = { for vnet in local.spoke_vnets : vnet.name => vnet } name = "peer-hub-to-${each.value.name}" resource_group_name = var.rg_network_name virtual_network_name = var.vnet_hub_name remote_virtual_network_id = each.value.id allow_virtual_network_access = true allow_forwarded_traffic = true allow_gateway_transit = false }
需要在Spoke的Terraform栈中输出包含名称和ID的spoke_vnets列表。
内容的提问来源于stack exchange,提问作者arhenk226
相关产品推荐
相关产品推荐

