腾讯云API接口自动快照教程


叙述195 阅0 评

我在使用的是腾讯云轻量应用服务器,免费快照额度只有2个,每一次都是手动删除旧快照再创建新快照实在太麻烦,问了客服也没有直接设置的功能,但好在提供了API接口来实现。

所以当前使用了1Panel面板的计划任务和腾讯云API来实现:自动识别并删除旧的自动快照,立即创建一个新的快照。

一、获取API 密钥

bluehe_2026-07-04_14-16-40

1.创建子账号,点击新建用户 → 选择自定义创建,用户类型:可访问资源并接收消息,填写用户名(如 lighthouse-snapshot),访问方式勾选编程访问,完成创建后,务必下载或复制好 SecretId 和 SecretKey。

bluehe_2026-07-04_14-19-16

bluehe_2026-07-04_14-29-57

2.进入访问管理 → 策略,点击 新建自定义策略 → 按策略语法创建 → 空白模板。
名称随意(如 Lighthouse-Snapshot),粘贴以下 JSON:

{
    "statement": [
        {
            "action": [
                "lighthouse:CreateInstanceSnapshot",
                "lighthouse:DeleteSnapshots",
                "lighthouse:DescribeSnapshots",
                "lighthouse:DescribeSnapshotsDeniedActions"
            ],
            "effect": "allow",
            "resource": [
                "*"
            ]
        }
    ],
    "version": "2.0"
}

bluehe_2026-07-04_14-37-19

bluehe_2026-07-04_14-37-56

3.自动跳回自定义策略列表,找到刚创建的子账号,关联刚才建立的策略,API密钥即使泄漏,攻击者也只能操作快照。

二、服务器环境准备

安装 Python 虚拟环境及腾讯云 SDK,本教程以 Debian 12 为例,其他系统请自行调整包管理器命令,如果系统提示没有 pip,可以先安装 python3-pip。

# 1. 安装 python3 虚拟环境依赖
apt update
apt install python3.11-venv -y

# 2. 创建专属虚拟环境
mkdir -p /opt/scripts
python3 -m venv /opt/scripts/venv

# 3. 激活虚拟环境并安装腾讯云 SDK
source /opt/scripts/venv/bin/activate
pip install tencentcloud-sdk-python-lighthouse
deactivate

三、编写自动化脚本

1.创建脚本文件:

vim /opt/scripts/snapshot_backup.py

2.将以下完整代码粘贴进去,并按注释修改开头4个配置变量:

#!/opt/scripts/venv/bin/python3
# -*- coding: utf-8 -*-

import time
import logging
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.lighthouse.v20200324 import lighthouse_client, models

# ========== 请修改以下4个配置 ==========
SECRET_ID  = "AKIDxxxxxxxxxxxxxxxx"       # 子用户的 SecretId
SECRET_KEY = "xxxxxxxxxxxxxxxxxxxx"       # 子用户的 SecretKey
REGION     = "ap-xxxxx"                   # 实例所在地域,如 ap-shanghai
INSTANCE_ID = "lhins-xxxxxxxx"            # 轻量应用服务器实例 ID
SNAPSHOT_NAME_PREFIX = "auto-snap"        # 自动快照的名称前缀,可自定义
MAX_RETRY = 10                            # 删除后等待确认的最大次数
RETRY_INTERVAL = 5                        # 每次等待秒数
# ======================================

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

try:
    cred = credential.Credential(SECRET_ID, SECRET_KEY)
    client = lighthouse_client.LighthouseClient(cred, REGION)
except Exception as e:
    logger.error(f"初始化客户端失败: {e}")
    exit(1)

def get_all_normal_snapshots():
    """获取所有状态为 NORMAL 的快照,并按创建时间升序排列"""
    try:
        req = models.DescribeSnapshotsRequest()
        resp = client.DescribeSnapshots(req)
        snapshots = [s for s in resp.SnapshotSet if s.SnapshotState == 'NORMAL']
        snapshots.sort(key=lambda x: x.CreatedTime if x.CreatedTime else '')
        return snapshots
    except TencentCloudSDKException as e:
        logger.error(f"查询快照失败: {e}")
        return []

def get_old_snapshot_id():
    """
    决定删除哪个快照:
    1. 优先删除名称以 SNAPSHOT_NAME_PREFIX 开头的自动快照
    2. 若没有,则删除最早的一个普通快照(用于首次清理手动快照)
    """
    snapshots = get_all_normal_snapshots()
    if not snapshots:
        return None

    for snap in snapshots:
        if snap.SnapshotName and snap.SnapshotName.startswith(SNAPSHOT_NAME_PREFIX):
            return snap.SnapshotId

    # 未找到自动前缀快照,返回最早的一个
    logger.warning("未找到自动前缀快照,将删除最早的一个普通快照以腾出配额")
    return snapshots[0].SnapshotId

def delete_snapshot(snapshot_id):
    """删除指定快照"""
    try:
        req = models.DeleteSnapshotsRequest()
        req.SnapshotIds = [snapshot_id]
        resp = client.DeleteSnapshots(req)
        logger.info(f"已发起删除快照 {snapshot_id}")
        return True
    except TencentCloudSDKException as e:
        logger.error(f"删除快照失败: {e}")
        return False

def wait_snapshot_deleted(snapshot_id):
    """轮询等待快照彻底消失"""
    for i in range(MAX_RETRY):
        logger.info(f"等待快照 {snapshot_id} 被删除... ({i+1}/{MAX_RETRY})")
        found = False
        try:
            req = models.DescribeSnapshotsRequest()
            req.SnapshotIds = [snapshot_id]
            resp = client.DescribeSnapshots(req)
            if resp.SnapshotSet:
                logger.info(f"快照仍存在,状态: {resp.SnapshotSet[0].SnapshotState}")
                found = True
        except TencentCloudSDKException as e:
            if 'ResourceNotFound' in str(e):
                logger.info(f"快照已删除")
                return True
            else:
                logger.warning(f"查询状态异常: {e}")
        if not found:
            return True
        time.sleep(RETRY_INTERVAL)
    logger.error("删除超时,未能确认")
    return False

def create_snapshot():
    """创建新快照,名称包含时间戳"""
    try:
        timestr = time.strftime("%Y%m%d-%H%M%S")
        snapshot_name = f"{SNAPSHOT_NAME_PREFIX}-{timestr}"
        req = models.CreateInstanceSnapshotRequest()
        req.InstanceId = INSTANCE_ID
        req.SnapshotName = snapshot_name
        resp = client.CreateInstanceSnapshot(req)
        logger.info(f"成功创建快照 {resp.SnapshotId},名称: {snapshot_name}")
        return resp.SnapshotId
    except TencentCloudSDKException as e:
        logger.error(f"创建快照失败: {e}")
        return None

if __name__ == "__main__":
    logger.info("===== 开始自动快照轮换 =====")
    old_id = get_old_snapshot_id()
    if not old_id:
        logger.warning("无可删除的快照,请检查配额和快照状态")
        exit(1)

    logger.info(f"待删除快照: {old_id}")
    if not delete_snapshot(old_id) or not wait_snapshot_deleted(old_id):
        logger.error("删除未完成,中止操作")
        exit(1)

    new_id = create_snapshot()
    if new_id:
        logger.info("===== 快照轮换成功 =====")
    else:
        logger.error("创建新快照失败")
        exit(1)

3.赋予执行权限并测试:

chmod +x /opt/scripts/snapshot_backup.py
/opt/scripts/venv/bin/python3 /opt/scripts/snapshot_backup.py

出现的情况有,检测不到auto-snap前缀的快照,自动删除最早的手动快照,随后创建一个名如auto-snap-20260704-120000 的新快照

四、1Panel 配置定时任务

bluehe_2026-07-04_14-57-43

1.登录 1Panel 面板,进入计划任务,点击创建计划任务,填写脚本内容等:

/opt/scripts/venv/bin/python3 /opt/scripts/snapshot_backup.py >> /var/log/snapshot_backup.log 2>&1

2.保存后,可先点击右侧的 “执行” 手动测试一次,并查看日志确认无误。

常见问题

Q:我的系统是 CentOS,命令一样吗?
A:基本相同,只需将 apt 换成 yum 或 dnf,Python 包名可能略有差异(如 python3-venv 需要安装 python3-virtualenv)。

Q:我不想删除最早的手动快照怎么办?
A:可以先将手动快照重命名为带有 auto-snap 前缀,或者删除一个手动快照释放配额后再运行脚本。

最后更新 2026-07-04
评论 ( 0 )