控制面与数据面快照链不一致导致云盘快照删除失败排查
问题说明
本文记录如何解决因管理数据库(控制面)与底层 libvirt/QCOW2 后端链(数据面)不一致而导致的云盘快照删除失败(could not find image ... in chain)问题。排查流程会沿快照链比对宿主机上的实际状态与数据库记录,并删除 libvirt 已无法匹配的残留数据库记录。
现象
- 删除云盘快照时失败,提示:
操作错误,因为 invalid argument: could not find image
'/dev/f179d81a3fd748608be2d4da35a50c8d/ff42324c90c144768f444683c6fd21c8'
beneath '/dev/f179d81a3fd748608be2d4da35a50c8d/6174c7db57ac4942bee35556097cf7e6'
in chain for '/dev/f179d81a3fd748608be2d4da35a50c8d/6174c7db57ac4942bee35556097cf7e6'
- 一个历史快照卷(源案例中为
/dev/f179d81a3fd748608be2d4da35a50c8d/ff42324c90c144768f444683c6fd21c8)已在底层存储上删除,但管理数据库中仍保留对该记录的引用。
适用环境
- 产品:ZStack Cloud(ZCF)。
- 版本:4.x、5.x。
- 组件:主存储(源案例使用基于 Ceph 或 LVM 的部署,向 libvirt 暴露
/dev/<vg>/<image>路径)、libvirt、qemu-img、管理数据库(VolumeSnapshotVO)。 - 部署形态:任何使用共享块或 LVM/Ceph 主存储的部署,存在快照已在宿主机删除但管理 DB 仍保留记录的情况。
可能原因
- 历史快照卷已在底层存储实际删除成功,但
libvirt报告了失败,导致管理数据库处于不一致状态(数据库记录存在,但宿主机上已无后端文件)。 - 链中所引用的某个后端文件在宿主机上已不存在,导致删除下一个快照时 libvirt 无法解析该链。
- 之前的审计超时或中止的删除任务只残留了数据库记录,而未将宿主机状态回滚。
排查步骤
1. 查看快照审计日志中是否存在超时删除记录
- 检查项:确认早期存在一条 libvirt 超时的删除任务,而底层快照实际上已被删除。
- 预期结果:审计日志中存在超时的快照删除记录(暗示底层存储已删除对应卷)。
2. 登录承载受影响云主机的物理机,查看后端链
- 定位承载该云主机的宿主机(即运行受影响
libvirt域的节点)。 - 查看云盘(源案例中为
6174c7db57ac4942bee35556097cf7e6):
qemu-img info --backing-chain /dev/f179d81a3fd748608be2d4da35a50c8d/6174c7db57ac4942bee35556097cf7e6
- 查看链中上一级快照(源案例中为
8eb6fba2d9bb4d80b805a9def3e78883):
qemu-img info --backing-chain /dev/f179d81a3fd748608be2d4da35a50c8d/8eb6fba2d9bb4d80b805a9def3e78883
- 查看 libvirt 已无法找到的快照(源案例中为
ff42324c90c144768f444683c6fd21c8):
qemu-img info --backing-chain /dev/f179d81a3fd748608be2d4da35a50c8d/ff42324c90c144768f444683c6fd21c8
- 预期结果:报 “could not find image” 的快照没有后端文件,而其他两条记录能够正常解析。
- 异常处理:若连云盘本身都无法解析,请停止操作并升级处理——不一致程度已超过单条孤立记录。
3. 确认宿主机上是否仍存在该快照文件
- 通过 LVM 查看该快照 UUID:
lvs | grep -i <snapshot-uuid>
- 查看候选路径:
qemu-img info /dev/<vg>/<image>
- 预期结果:
lvs不返回缺失快照对应记录,且qemu-img info返回 “No such file or directory”——确认底层存储已被清理。
4. 检查云主机 libvirt XML 中记录的快照配置
- 备份云主机 domain XML:
virsh dumpxml <vm-uuid> > /root/uuid.xml.bak
- 预期结果:XML 记录中的快照链与数据库保持一致。
5. 从管理数据库中删除残留的 VolumeSnapshotVO 记录
警告:本步骤将直接修改管理数据库。执行前请对两台管理节点分别导出新的数据库备份,并核实即将删除的 UUID 确实就是第 3 步中确认缺失的那条快照。
- 先禁用全局 HA,再对两台管理节点分别备份数据库:
zstack-ctl dump_mysql --file-name zstack-db-backup-master # 主节点
zstack-ctl dump_mysql --file-name zstack-db-backup-slave # 备节点
- 登录数据库,定位残留记录:
mysql -uroot -p'<mysql-root-password>' zstack
select * from VolumeSnapshotVO where uuid = '8eb6fba2d9bb4d80b805a9def3e78883';
- 确认
primaryStorageInstallPath列内容为空——这表明底层存储已不再引用该记录。 - 删除残留记录:
delete from VolumeSnapshotVO where uuid = '8eb6fba2d9bb4d80b805a9def3e78883';
- 预期结果:该记录已删除;
select返回 0 行。 - 异常处理:从本步骤开始时的备份进行恢复。
6. 重试快照删除
- UI:重新尝试原先失败的快照删除操作。
- 预期结果:删除成功;剩余的快照链恢复一致。
7. 验证处理结果
完成第 5 步删除残留 VolumeSnapshotVO 记录后,在 UI 中重新发起快照删除。任务应能成功完成,快照列表中对应条目消失,云主机始终保持 Running 状态。在宿主机上使用 qemu-img info <backing-file> 验证后端链已恢复一致。
8. 记录风险与回滚信息
警告:第 5 步直接修改管理数据库(delete from VolumeSnapshotVO)。该操作属于带外操作(out-of-band),并未通过任何 ZStack API 暴露。仅允许具备数据库访问权限的售后工程师执行,并且必须先在两台管理节点上分别执行完整 MySQL 导出。建议将该 KB 的可见性限制为 visibility: partner 或 internal。 风险:若删错记录,会导致数据库与磁盘上实际的快照文件状态不一致。请使用审计日志中确切的 UUID,不要使用模糊匹配。 注意事项:操作前请先在两台管理节点上分别备份 MySQL。 回滚:从上述注意事项中导出的 MySQL 备份恢复。
补充信息
预防及优化方案
- 出现删除超时时,应当怀疑“底层存储实际成功而 libvirt 失败”的场景,重试前先在宿主机上验证。
- 任何直接修改数据库的操作前,都应在两台管理节点上分别导出新的备份。
- 避免对同一卷连续快速删除多个快照;libvirt 的链校验依赖稳定的状态。
- 一旦删除失败,应在尝试恢复前先保留完整的审计日志和
qemu-img info --backing-chain输出,以维持审计追溯。
升级到 R&D
如果执行此流程后快照删除仍然以相同的 could not find image 错误失败,请升级到 ZStack R&D 并附上以下材料:
- 删除尝试前后 30 分钟的
management-server.log(管理节点上的/var/log/zstack/management-server.log) - 受影响云盘及周边快照的
qemu-img info --backing-chain输出 - 直接编辑数据库之前捕获的
virsh dumpxml <vm-uuid>输出 - 被删除的
VolumeSnapshotVO行及其时间戳(来自审计日志) - 编辑后新做的
zstack-ctl dump_mysql(不要在文件名中包含管理节点密码)
在 R&D 审查之前,不要对其他行重做直接编辑数据库。R&D 可能希望在进一步变更之前检查剩余的快照链。
支持信息
- 相关组件:主存储(Ceph / LVM / 共享块)、
libvirt、qemu-img、管理数据库VolumeSnapshotVO。 - 相关命令:
qemu-img info --backing-chain、virsh dumpxml、lvs、zstack-ctl dump_mysql、mysql。 - 免责声明:直接编辑数据库属于带外操作,在生产环境中执行第 5 步前请与 ZStack 售后支持沟通确认。
