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

如何从aws_ami_from_instance的ebs_block_device引用snapshot_id并为非根卷快照打标签?

问题描述

我通过aws_ami_from_instance资源从带有2个EBS卷的EC2实例创建AMI,生成的磁盘快照未自动添加标签。目前已通过AMI资源导出的root_snapshot_id为根快照打上标签,但不知道如何处理非根卷的快照。

现有Terraform代码:

resource "aws_ami_from_instance" "server_ami" {
  name                = "${var.env}.v${local.new_version}.ami"
  source_instance_id  = data.aws_instance.server.id
  tags = {
    Name              = "${var.env}.v${local.new_version}.ami"
    Version           = local.new_version
  }
}

resource "aws_ec2_tag" "server_ami_tags" {
  for_each    = { for tag in var.tags : tag.tag => tag }
  resource_id = aws_ami_from_instance.server_ami.root_snapshot_id
  key         = each.value.tag
  value       = each.value.value
}

尝试引用ebs_block_device的快照ID时报错:

│   25:   resource_id = aws_ami_from_instance.sever_ami.ebs_block_device.snapshot_id
│ Block type "ebs_block_device" is represented by a set of objects, and set
│ elements do not have addressable keys. To find elements matching specific
│ criteria, use a "for" expression with an "if" clause.

│   25:   resource_id = aws_ami_from_instance.sever_ami.ebs_block_device[snapshot_id]
│ A reference to a resource type must be followed by at least one attribute
│ access, specifying the resource name.

│   25:   resource_id = aws_ami_from_instance.sever_ami.ebs_block_device["snapshot_id"]
│ Block type "ebs_block_device" is represented by a set of objects, and set
│ elements do not have addressable keys. To find elements matching specific
│ criteria, use a "for" expression with an "if" clause.

请问该需求能否实现,操作上哪里有误?

解决方案

这个需求完全可以实现,问题出在你对ebs_block_device的访问方式上——它是集合(Set)类型,无法直接通过键名或索引访问单个元素,必须用for表达式遍历处理。

你可以新增一个aws_ec2_tag资源,遍历所有非根卷的快照ID,同时结合你的标签列表批量打标签:

# 为根快照打标签(保留原有代码)
resource "aws_ec2_tag" "server_ami_root_snapshot" {
  for_each    = { for tag in var.tags : tag.tag => tag }
  resource_id = aws_ami_from_instance.server_ami.root_snapshot_id
  key         = each.value.tag
  value       = each.value.value
}

# 为非根卷的快照打标签
resource "aws_ec2_tag" "server_ami_non_root_snapshots" {
  # 生成唯一键:标签名+快照ID,避免重复;同时过滤掉根快照
  for_each = {
    for tag in var.tags, ebs in aws_ami_from_instance.server_ami.ebs_block_device :
    "${tag.tag}-${ebs.snapshot_id}" => { tag = tag, ebs = ebs }
    if ebs.snapshot_id != aws_ami_from_instance.server_ami.root_snapshot_id
  }

  resource_id = each.value.ebs.snapshot_id
  key         = each.value.tag.tag
  value       = each.value.tag.value
}

关键说明:

  1. 集合遍历:用for表达式遍历ebs_block_device集合中的每个EBS卷对象,取出其中的snapshot_id。
  2. 标签批量处理:通过嵌套遍历标签列表和EBS卷集合,生成唯一的for_each键(避免资源重复创建)。
  3. 过滤根快照:通过if条件排除已处理的根快照,避免重复打标签。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:20:17