通过JSON迭代生成Terraform VPC与Subnet时的cidr_block取值问题
解决Terraform遍历JSON生成子网时cidr_block类型错误问题
问题根源
当前子网资源的for_each将每个VPC映射为子网列表,导致each.value是包含多个子网的元组,而cidr_block属性要求传入单个字符串,因此触发类型不匹配错误。
解决方案
需要将JSON中的所有子网扁平化处理,构造一个以「VPC标识-子网名称」为唯一键的集合,每个元素对应单个子网的完整信息(关联VPC、CIDR、名称),确保每个aws_subnet实例对应一个子网。
修改后的Terraform代码
resource "aws_vpc" "main" { for_each = { for vpc_key, vpc in local.json : vpc.name => vpc } cidr_block = each.value.cidr tags = { Name = each.value.name } } resource "aws_subnet" "main" { # 扁平化所有子网,生成唯一键:VPC标识-子网名称 for_each = merge([ for vpc_key, vpc in local.json : { for subnet in vpc.subnets : "${vpc_key}-${subnet.name}" => { vpc_name = vpc.name cidr = subnet.cidr name = subnet.name } } ]...) vpc_id = aws_vpc.main[each.value.vpc_name].id cidr_block = each.value.cidr tags = { Name = each.value.name } }
代码说明
- 扁平化子网集合:通过嵌套
for循环遍历每个VPC下的子网,用${vpc_key}-${subnet.name}生成唯一键,避免资源重名冲突;每个值包含子网所属VPC的名称、子网CIDR和名称。 - 关联VPC:通过
aws_vpc.main[each.value.vpc_name].id获取对应VPC的ID,确保子网创建在正确的VPC下。 - 类型匹配:
cidr_block直接取each.value.cidr,为单个字符串,满足属性类型要求。
验证for_each结构
执行terraform console查看构造的集合:
> merge([for vpc_key, vpc in local.json : {for subnet in vpc.subnets : "${vpc_key}-${subnet.name}" => {vpc_name = vpc.name, cidr = subnet.cidr, name = subnet.name}}]...) { "vpc1-subnet-one" = { "cidr" = "192.168.1.0/24" "name" = "subnet-one" "vpc_name" = "first-vpc" } "vpc1-subnet-two" = { "cidr" = "192.168.4.0/24" "name" = "subnet-two" "vpc_name" = "first-vpc" } "vpc2-subnet-three" = { "cidr" = "172.16.1.0/24" "name" = "subnet-three" "vpc_name" = "second-vpc" } "vpc2-subnet-four" = { "cidr" = "172.16.7.0/24" "name" = "subnet-four" "vpc_name" = "second-vpc" } }
每个元素都是单个子网的信息,完全符合aws_subnet资源的要求。
内容的提问来源于stack exchange,提问作者Elazar
相关产品推荐
相关产品推荐

