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

如何使用boto3在不关闭EC2实例的情况下创建AWS快照?

解决Boto3创建AWS快照时自动关闭实例的问题

嗨,我之前也碰到过这个坑——控制台创建运行中实例的快照完全不用关机,但自己写的boto3脚本却把实例停了,这在生产环境里绝对是红线问题。

问题根源

大概率是你的脚本里不小心加了停止实例的逻辑(比如调用了ec2.stop_instances()),或者误解了快照创建的流程:AWS EBS本身就支持在线快照,运行中的实例挂载的卷完全可以直接创建快照,根本不需要关机。

正确的自动化快照脚本

下面是我一直在用的生产级脚本,遍历所有运行中的实例,为它们的EBS卷创建快照,全程不会停止实例:

import boto3
from datetime import datetime

def create_online_snapshots():
    # 初始化EC2资源客户端
    ec2 = boto3.resource('ec2')
    
    # 筛选所有处于运行状态的实例
    running_instances = ec2.instances.filter(
        Filters=[{'Name': 'instance-state-name', 'Values': ['running']}]
    )
    
    for instance in running_instances:
        # 获取实例名称(如果有标签的话)
        instance_name = next((tag['Value'] for tag in instance.tags if tag['Key'] == 'Name'), instance.id)
        print(f"=== 开始处理实例: {instance_name} ({instance.id}) ===")
        
        # 遍历实例挂载的所有EBS卷
        for volume in instance.volumes.all():
            # 生成带时间戳的快照描述,方便后续识别
            snapshot_desc = f"Auto-snapshot | Instance: {instance_name} | Volume: {volume.id} | Created: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
            
            # 直接创建快照,无需停止实例
            snapshot = volume.create_snapshot(Description=snapshot_desc)
            print(f"已创建快照: {snapshot.id} (对应卷: {volume.id})")
            
            # 可选:等待快照完成(生产环境可以异步处理,不用阻塞)
            snapshot.wait_until_completed()
            print(f"快照 {snapshot.id} 已完成")

if __name__ == "__main__":
    create_online_snapshots()

关键注意点

  1. 不要停止实例:移除脚本中任何stop_instances()的调用,Volume.create_snapshot()方法本身就支持在线操作。

  2. 文件系统一致性(可选但推荐):如果你的应用对数据一致性要求极高(比如数据库实例),可以在创建快照前临时冻结文件系统,完成后再解冻——不用关机,用AWS SSM就能远程执行命令:

    import boto3
    
    ssm_client = boto3.client('ssm')
    
    def freeze_filesystem(instance_id, mount_point="/"):
        # 执行文件系统冻结
        response = ssm_client.send_command(
            InstanceIds=[instance_id],
            DocumentName='AWS-RunShellScript',
            Parameters={'commands': [f"fsfreeze -f {mount_point}"]}
        )
        # 等待命令执行完成
        command_id = response['Command']['CommandId']
        ssm_client.get_waiter('command_executed').wait(
            CommandId=command_id,
            InstanceId=instance_id
        )
        print(f"已冻结实例 {instance_id} 的文件系统: {mount_point}")
    
    def unfreeze_filesystem(instance_id, mount_point="/"):
        # 解冻文件系统
        response = ssm_client.send_command(
            InstanceIds=[instance_id],
            DocumentName='AWS-RunShellScript',
            Parameters={'commands': [f"fsfreeze -u {mount_point}"]}
        )
        command_id = response['Command']['CommandId']
        ssm_client.get_waiter('command_executed').wait(
            CommandId=command_id,
            InstanceId=instance_id
        )
        print(f"已解冻实例 {instance_id} 的文件系统: {mount_point}")
    

    你可以在创建快照前调用freeze_filesystem,创建完成后调用unfreeze_filesystem,这样能保证快照的数据一致性,同时完全不影响实例运行。

  3. IAM权限:确保执行脚本的角色/用户有ec2:CreateSnapshot、ec2:DescribeInstances、ec2:DescribeVolumes等权限,如果用SSM的话,还需要ssm:SendCommand和ssm:GetCommandInvocation权限。

总结

只要去掉脚本中停止实例的逻辑,直接调用卷的create_snapshot()方法,就能实现和控制台一样的在线快照功能,完全符合生产环境的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:54:32