Terraform中按可用区匹配挂载EBS卷到EC2实例报错求助
Terraform EBS卷挂载到同可用区EC2实例问题解决
问题背景
需要将同一可用区的EBS卷挂载到对应EC2实例,已通过for_each基于公有子网创建aws_ebs_volume.demo_ebs_volume和aws_instance.demo_instance_public,但编写aws_volume_attachment资源时出现属性错误。
现有代码
创建EBS卷
resource "aws_ebs_volume" "demo_ebs_volume" { for_each = aws_subnet.public_subnets availability_zone = each.value.availability_zone size = 1 encrypted = true }
创建EC2实例
resource "aws_instance" "demo_instance_public" { for_each = aws_subnet.public_subnets ami = "ami-0cc87e5027adcdca8" instance_type = "t2.micro" subnet_id = each.value.id vpc_security_group_ids = [aws_security_group.demo_security_group.id] }
挂载代码(报错版本)
resource "aws_volume_attachment" "demo_ebs_attachement" { for_each = aws_ebs_volume.demo_ebs_volume device_name = "/dev/xvda" volume_id = each.value.id instance_id = aws_instance.demo_instance_public[index(aws_instance.demo_instance_public.*.availability_zone,each.value.availability_zone)].id }
报错信息
Error: Unsupported attribute instance_id = aws_instance.demo_instance_public[index(aws_instance.demo_instance_public.*.availability_zone,each.value.availability_zone)].id Error: This object does not have an attribute named "availability_zone".
解决方案
问题原因
- 用
for_each创建的资源集合,不能通过*.availability_zone这种列表式语法批量提取属性,Terraform会将其识别为对象而非列表集合。 - 更关键的是,你完全不需要通过可用区去匹配实例——EBS卷和EC2实例都是基于同一个
aws_subnet.public_subnets创建的,它们的each.key(子网ID)完全对应,即同一个子网下的EBS卷和EC2实例必然在同一可用区。
修正后的挂载代码
resource "aws_volume_attachment" "demo_ebs_attachement" { for_each = aws_subnet.public_subnets device_name = "/dev/xvdh" # 注意:不要用/dev/xvda(这是默认根卷设备名) volume_id = aws_ebs_volume.demo_ebs_volume[each.key].id instance_id = aws_instance.demo_instance_public[each.key].id }
额外说明
- 避免将附加卷挂载到
/dev/xvda,这是EC2实例的根卷设备名,挂载会导致系统故障,建议使用/dev/xvdh、/dev/xvdf等未被占用的设备名。 - 通过
each.key直接关联资源,比通过可用区匹配更可靠,避免出现同一可用区多个实例导致的匹配错误。
内容的提问来源于stack exchange,提问作者NotAgain
相关产品推荐
相关产品推荐

