核心是精准识别并清理无引用、超期或标记临时的镜像快照,通过API/CLI验证引用关系,结合白名单、保留窗口、预检模式和日志记录实现安全可控的自动化清理。

核心是用最小权限执行精准识别、带白名单和预检的清理动作,不删正在用的,只动明确闲置的资源。
先确认哪些镜像快照真“无用”
不能靠时间一刀切,得查实际引用关系:
- OpenStack 环境:用 openstack server list --all --format value 获取所有 VM,再逐个 openstack server show
--format json 提取 image_id 和 backup_id,比对快照 ID 是否在其中 - Docker 环境:运行 docker ps -a --format '{{.Image}}' 和 docker images --quiet --filter dangling=true,再结合 docker system df -v 看哪些层没被任何容器或镜像引用
- KVM/libvirt:用 virsh list --all --name 得到所有域名,再对每个执行 virsh dumpxml | grep 'source file',提取磁盘路径后匹配快照文件名
用白名单+保留窗口守住安全底线
脚本里硬编码保护逻辑,避免误删关键资产:
- 维护一个 keep_list.txt,每行写一个必须保留的快照 ID、名称正则(如 ^ubuntu-22\.04-cuda.*$)或标签前缀(如 ci-base-)
- 只清理创建时间早于 7 天且无引用的快照;新快照哪怕闲置也留出调试缓冲期
- 对私有镜像仓库中的基础镜像(如 pytorch-cuda:v2.8),直接跳过匹配项,不走引用检查流程
脚本本身按最小权限运行
不依赖 root,也不开过度权限:
- 用普通运维账号运行,通过 sudo -l 明确授权仅几条命令(如 docker image rm、openstack image delete),拒绝 shell 通配或任意命令执行
- 所有 API 调用走专用只读/有限写入服务账号,Token 生命周期短,不存明文密码
- 脚本不写临时文件到 /tmp,日志统一记到 /var/log/snapshot-cleaner.log,由 logrotate 管理轮转
每次执行都带预检和可追溯记录
真实删除前必须人工确认,操作全程留痕:
- 加 --dry-run 参数时,只输出将删的快照 ID、创建时间、检查结果(如 “未被任何 VM 引用,创建于 2026-09-22”),不执行删除
- 正式运行时,每条删除命令前先写日志:[INFO] deleting snap-abc123 (ubuntu-test-202609): no VM reference, age=16d
- 失败立即中断并报错,不跳过;成功后自动触发 docker system df 或 df -h /var/lib/libvirt/images 记录释放空间量










