为所有EC2实例主网卡分配安全组失败问题排查
问题:Terraform中安全组附加到EC2实例网卡时索引不匹配报错
需求:查找所有VPC并在每个VPC中创建安全组,找出所有运行及停止状态的EC2实例,将新安全组附加到每个实例的主网卡(排除Auto Scaling组中的实例)。
执行terraform plan时出现以下错误:
│ Error: Invalid index │ │ on main.tf line 70, in resource "aws_network_interface_sg_attachment" "attach_sg": │ 70: security_group_id = aws_security_group.vpc_sg[data.aws_instance.instance[each.key].network_interface_id] │ ├──────────────── │ │ aws_security_group.vpc_sg is object with 3 attributes │ │ data.aws_instance.instance is object with 33 attributes │ │ each.key is "i-xxxxxxxxxxxxxxxxx" │ │ The given key does not identify an element in this collection value.
错误原因
- 索引不匹配:
aws_security_group.vpc_sg的for_each基于VPC ID列表创建,集合的键是VPC ID,但代码中用网卡ID去索引该集合,自然找不到对应元素。 - each.key为实例ID的原因:
aws_network_interface_sg_attachment的for_each定义为{ for id in data.aws_instances.all.ids : id => (data.aws_instance.instance[id].network_interface_id) },这里明确用实例ID作为map的键、网卡ID作为值,因此each.key必然是实例ID。
修正方案
通过实例所属的VPC ID索引对应安全组(每个实例属于一个VPC,安全组按VPC创建,二者可匹配)。
修正后的完整代码
provider "aws" { region = "us-east-1" } # 获取所有VPC data "aws_vpcs" "all" {} # 在每个VPC中创建安全组 resource "aws_security_group" "vpc_sg" { for_each = toset(data.aws_vpcs.all.ids) name = "Example" description = "Allows SSH access" vpc_id = each.value ingress { from_port = 0 to_port = 22 protocol = "tcp" cidr_blocks = ["1.1.1.0/27"] # 根据环境更新 } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } # 获取所有运行/停止状态的EC2实例 data "aws_instances" "all" { filter { name = "instance-state-name" values = ["running", "stopped"] } } # 获取每个实例的详细信息 data "aws_instance" "instance" { for_each = toset(data.aws_instances.all.ids) instance_id = each.key } # 将安全组附加到非ASG实例的主网卡 resource "aws_network_interface_sg_attachment" "attach_sg" { for_each = { for id in data.aws_instances.all.ids : id => data.aws_instance.instance[id].network_interface_id if lookup(data.aws_instance.instance[id].tags, "aws:autoscaling:groupName", null) == null } # 通过实例的VPC ID索引对应的安全组 security_group_id = aws_security_group.vpc_sg[data.aws_instance.instance[each.key].vpc_id] network_interface_id = each.value }
说明
- 修正核心:将
security_group_id的索引从网卡ID改为实例所属的VPC ID,匹配对应VPC下创建的安全组。 each.value直接对应网卡ID,简化了network_interface_id的引用逻辑。
内容的提问来源于stack exchange,提问作者Mark Schoonover
相关产品推荐
相关产品推荐

