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

使用Terraform Google Provider创建防火墙规则时获取子网IPv6前缀报错

Terraform Google Provider 防火墙规则获取子网IP前缀问题解决

问题场景

尝试通过Terraform的Google Provider创建防火墙规则,需要从VPC的所有子网中提取IP前缀作为source_ranges,但在遍历子网数据源时遇到以下错误:

用户原代码

data "google_compute_network" "vpc" {
  name    = "my-vpc"
  project = "my-project"
}

data "google_compute_subnetwork" "subnetwork" {
  for_each  = toset(data.google_compute_network.vpc.subnetworks_self_links)
  self_link = each.value
}

resource "google_compute_firewall" "composer-firewall-rule" {
  name        = "allow-egress-from-composer-control-plane"
  description = "Allow Egress traffic from k8 nodes to Control Plane"
  network     = data.google_compute_network.vpc
  project     = var.DEPLOY_PROJECT
  priority    = 980
  allow { protocol = "all" }
  direction     = "EGRESS"
  disabled      = false
  source_ranges = [data.google_compute_subnetwork.subnetwork.self_link.external_ipv6_prefix]
}

报错信息

Error: Missing resource instance key

on modules\firewall_rules\main.tf line 23, in resource "google_compute_firewall" "composer-firewall-rule"
23: source_ranges = [data.google_compute_subnetwork.subnetwork.self_link.external_ipv6_prefix]

Because data.google_compute_subnetwork.subnetwork has "for_each" set, its attributes must be accessed using a specific instance key.

For example, to correlate with indices of a referring resource, use:
data.google_compute_subnetwork.subnetwork[each.key]

错误原因

data.google_compute_subnetwork.subnetwork使用了for_each,因此它是一个映射类型的数据源集合,无法直接通过.self_link访问单个实例的属性,必须遍历所有实例提取所需值。

解决方案

场景1:获取所有子网的external_ipv6_prefix

修改防火墙规则的source_ranges配置,通过values()+for表达式+flatten()提取所有非空的IPv6前缀:

resource "google_compute_firewall" "composer-firewall-rule" {
  name        = "allow-egress-from-composer-control-plane"
  description = "Allow Egress traffic from k8 nodes to Control Plane"
  network     = data.google_compute_network.vpc
  project     = var.DEPLOY_PROJECT
  priority    = 980
  allow { protocol = "all" }
  direction     = "EGRESS"
  disabled      = false
  # 提取所有子网的external_ipv6_prefix,过滤空值并扁平化列表
  source_ranges = flatten([
    for subnet in values(data.google_compute_subnetwork.subnetwork) :
    subnet.external_ipv6_prefix != "" ? [subnet.external_ipv6_prefix] : []
  ])
}

场景2:获取所有子网的二级IP范围(即用户提到的"secondary IP")

如果需要提取子网的secondary_ip_ranges中的CIDR,调整为以下配置:

resource "google_compute_firewall" "composer-firewall-rule" {
  name        = "allow-egress-from-composer-control-plane"
  description = "Allow Egress traffic from k8 nodes to Control Plane"
  network     = data.google_compute_network.vpc
  project     = var.DEPLOY_PROJECT
  priority    = 980
  allow { protocol = "all" }
  direction     = "EGRESS"
  disabled      = false
  # 提取所有子网的二级IP范围CIDR
  source_ranges = flatten([
    for subnet in values(data.google_compute_subnetwork.subnetwork) :
    [for secondary_range in subnet.secondary_ip_ranges : secondary_range.ip_cidr_range]
  ])
}

代码说明

  • values(data.google_compute_subnetwork.subnetwork):将映射类型的子网数据源转换为实例列表
  • for表达式:遍历每个子网实例,提取目标IP前缀/二级IP范围
  • flatten():将嵌套的列表结构转为一维数组,符合source_ranges的参数格式要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 03:05:42