使用Boto3资源方式创建AMI,如何为底层卷快照添加标签?
解答你的EC2 AMI快照标签问题
嗨,很高兴看到你刚接触Boto3三周就能写出这样的备份脚本!针对你的问题,我来一步步帮你梳理:
1. 是否必须切换到boto3.client('ec2')才能为卷快照打标签?
完全不需要!你当前使用的boto3.resource('ec2')同样可以给快照打标签,只是创建AMI时不会自动返回关联的快照ID,你需要额外做一步:从创建好的AMI对象中提取快照信息,再对快照进行标签操作。当然,boto3.client的API也能实现这个功能,两种方式各有优劣,看你个人习惯选择就行。
2. 备份用户通常如何给AMI关联的快照打标签?
常见的做法有两种:
- 手动提取快照ID并打标签:创建AMI后,通过AMI的
block_device_mappings属性获取所有关联的快照ID,然后复用你给AMI打标签的逻辑(跳过aws:开头的系统保留标签),给这些快照批量打标签。 - 利用标签自动传播:在创建AMI时,通过
TagSpecifications参数指定要应用的标签,同时设置让这些标签自动传播到关联的快照上。这种方式更高效,不需要额外遍历快照。
修改后的脚本示例(修复标签逻辑+添加快照标签)
我先修复了你原脚本中标签处理的小bug(原代码每次循环都会重置dst_tags,导致最终只能保留最后一个非系统标签),然后添加了给快照打标签的逻辑:
#!/usr/bin/env python3 import boto3 import argparse import time ec2 = boto3.resource('ec2') dstamp = time.strftime("_%m-%d-%Y-0") parser = argparse.ArgumentParser(description='Create Image(AMI) from Instance tag:Name Value') parser.add_argument('names', nargs='+', type=str.upper, help='instance name or list of names to create images from') args = parser.parse_args() # List Source Instances for Image/Tag Creation for instance in ec2.instances.all(): # Pull Name tags from source instances instancename = None for name in instance.tags: if name["Key"] == 'Name': instancename = name["Value"] break # 找到Name标签后直接跳出循环,提升效率 if not instancename: continue # 跳过没有Name标签的实例 # Check for Name Tag Match with args for iname in args.names: if iname == instancename.upper(): # 和传入的大写参数匹配 # 先处理要复制的标签(跳过aws:开头的系统标签) dst_tags = [] for tag in instance.tags: if tag['Key'].startswith('aws:'): print(f"Skip tag that starts with 'aws:' {tag['Key']}") else: dst_tags.append(tag) # Create an image if we have a match image = instance.create_image( Description=f"Created from Source: {instance.id} Name: {instancename}", Name=instancename + dstamp, NoReboot=True, # 可选:开启标签传播,让AMI的标签自动传到快照 # TagSpecifications=[ # { # 'ResourceType': 'image', # 'Tags': dst_tags # }, # { # 'ResourceType': 'snapshot', # 'Tags': dst_tags # } # ] ) print(f'New: {image.id} from instance.id: {instance.id} {instancename}') # 给AMI打标签(如果没使用TagSpecifications的话) if dst_tags: image.create_tags(Tags=dst_tags) print(f' Applied tags to AMI: {dst_tags}') # 方式一:手动给快照打标签(如果没使用TagSpecifications) # 等待AMI状态可用,确保快照已创建完成 image.wait_until_exists() image.reload() # 刷新AMI对象的属性 for device in image.block_device_mappings: if 'Ebs' in device and 'SnapshotId' in device['Ebs']: snapshot_id = device['Ebs']['SnapshotId'] snapshot = ec2.Snapshot(snapshot_id) snapshot.create_tags(Tags=dst_tags) print(f' Applied tags to snapshot {snapshot_id}: {dst_tags}')
脚本说明:
- 修复了标签处理逻辑:把
dst_tags的初始化移到循环外面,确保所有非系统标签都能被收集。 - 两种快照标签方式可选:
- 如果你想用自动传播,只需要取消注释
TagSpecifications部分,这样创建AMI和快照时会自动应用标签,不需要后续手动遍历快照。 - 保留了手动遍历快照打标签的逻辑,适合需要更精细控制的场景。
- 如果你想用自动传播,只需要取消注释
- 添加了等待AMI可用的步骤:确保快照已经创建完成再打标签,避免因资源未就绪导致的错误。
内容的提问来源于stack exchange,提问作者Ron
相关产品推荐
相关产品推荐

