Terraform v12使用aws_subnet_ids配置安全组时cidr_block解析报错
报错核心原因
- 用到的
aws_subnet_ids数据源本身仅输出匹配规则的子网ID列表,不存储子网CIDR块等元数据属性,代码里尝试从这个数据源取cidr_block字段时,自然会触发“对象无对应属性”的报错。 - 原代码传
cidr_blocks参数时多包裹了一层列表结构,就算取到正确的CIDR值,也会因为传入的是嵌套列表而非扁平字符串列表,触发参数格式校验失败的后续报错。
Terraform v0.12 版本适配的修正方法
- 保留原有按标签筛选VPC、筛选目标子网ID列表的逻辑,额外增加
aws_subnet数据源,通过遍历已获取的子网ID列表,拉取每个子网的完整元数据(包含需要的cidr_block) - 从新的子网数据源中提取所有匹配子网的CIDR值,以扁平字符串列表的形式传给安全组的
cidr_blocks参数
修正后的完整可运行配置:
data "aws_vpc" "my-vpc" { filter { name = "tag:MY_VPC" values = ["TRUE"] } } # 原有逻辑:筛选带指定NAME标签的子网ID集合 data "aws_subnet_ids" "my-subnets" { vpc_id = data.aws_vpc.my-vpc.id filter { name = "tag:NAME" values = ["MY_SUBNET"] } } # 新增数据源:遍历子网ID,获取每个子网的完整属性 data "aws_subnet" "my-subnet-details" { for_each = data.aws_subnet_ids.my-subnets.ids id = each.value } resource "aws_security_group" "my-sg" { name = "my-sg" description = "my-sg" vpc_id = data.aws_vpc.my-vpc.id ingress { from_port = 443 protocol = "tcp" to_port = 443 cidr_blocks = values(data.aws_subnet.my-subnet-details.*.cidr_block) } ingress { from_port = 22 protocol = "tcp" to_port = 22 cidr_blocks = values(data.aws_subnet.my-subnet-details.*.cidr_block) } ingress { from_port = 80 protocol = "tcp" to_port = 80 cidr_blocks = values(data.aws_subnet.my-subnet-details.*.cidr_block) } # 若需匹配原配置的自定义出网规则,可将下方CIDR替换为和入站规则一致的取值 egress { from_port = 0 protocol = "-1" to_port = 0 cidr_blocks = ["0.0.0.0/0"] } }
注意事项
aws_subnet_ids的设计目标就是仅返回子网ID集合,不存在ID之外的业务属性,强行读取非ID字段必然报错- Terraform v0.12中通过
*.属性名语法从集合类资源提取属性时,返回结果本身就是扁平的属性值列表,不需要再额外包裹一层中括号构造嵌套列表 - 原配置中把子网CIDR作为出网权限的逻辑不符合通用使用习惯,示例中默认使用通用的全量出网规则,如有自定义出网需求可替换为对应的CIDR列表
内容的提问来源于stack exchange,提问作者Lagot
相关产品推荐
相关产品推荐

