问题说明
本文用于排查删除单盘快照、批量删除单盘快照或删除快照组时,任务在固定时间后失败,并显示 live merging snapshot chain failed, block job not finished 的问题。排查重点是先识别实际调用的删除入口,再核对对应的 API 超时配置和同一次任务的 deadline,最后判断底层 block job 是被期限取消,还是本身存在存储、容量或快照链异常。
现象
- 已把
APIDeleteVolumeSnapshotMsg和APIBatchDeleteVolumeSnapshotMsg调整为 24 小时,但删除快照仍在约 3 小时后失败。 - 管理节点日志出现
VolumeSnapshotTreeBase$35、batch delete volume snapshot error或live merging snapshot chain failed, block job not finished。 - 删除快照组时,任务详情中的外层
DeleteVolumeSnapshotGroupAction可能显示成功,但某个成员的results[].success为false,随后显示运行时错误。 - 已记录案例中,实际请求是
APIDeleteVolumeSnapshotGroupMsg。请求携带timeout=10800000,即 3 小时;期限到达时,在线 full rebase 的 Pull block job 仍在推进,随后被取消。
适用环境
- 产品:ZVF ZSphere
- 版本:4.10.25.65(已记录案例;其它版本应先按本文查询实际配置,不直接套用该版本结论)
- 组件:单盘快照、快照组、管理节点 API timeout、KVM Agent 和 libvirt block job
- 部署形态:删除运行中虚拟机的快照时需要在线合并快照链;已记录案例使用 SharedBlock 数据存储
可能原因
该现象可能由以下一种或多种原因导致:
- 调整的配置项与实际操作入口不一致。例如,现场执行的是“删除快照组”,但只调整了单盘和批量单盘删除的 API timeout。
- 配置在任务创建后才调整。一个已经开始的请求,其 deadline 已经确定;事后修改 GlobalConfig 不会延长旧任务。
- timeout 已正确延长,但底层 block job 进度缓慢或停止推进。可能需要继续检查存储 I/O、iSCSI 路径、数据存储容量、快照链或 QEMU/libvirt 状态。
- 只看了快照组事件的外层
success,没有检查每个成员的results[],因而遗漏了单个卷的删除失败。
以下错误不能直接当成根因或配置名:
VolumeSnapshotTreeBase$35是上层流程报告错误的位置,不是 GlobalConfig 名称。disk vda does not have an active block job如果出现在 deadline 到达、任务取消之后,通常是清理阶段再次取消 block job 的次生信息;应先找到它之前的超时和合并进度日志。
排查步骤
1. 判断删除的是单盘快照、批量单盘快照还是快照组
- 检查对象:任务详情中的操作名称、API ID、快照 UUID、快照组 UUID、虚拟机 UUID和开始时间。
- 操作位置:在 ZSphere UI 打开失败任务详情,记录完整错误、开始和结束时间以及
apiId。然后按实际操作对照下表:
| 用户操作 | 管理节点日志中的 API | 对应的 API timeout GlobalConfig name |
|---|---|---|
| 删除一个单盘快照 | APIDeleteVolumeSnapshotMsg | org.zstack.header.storage.snapshot.APIDeleteVolumeSnapshotMsg |
| 一次批量删除多个单盘快照 | APIBatchDeleteVolumeSnapshotMsg | org.zstack.header.storage.snapshot.APIBatchDeleteVolumeSnapshotMsg |
| 删除快照组 | APIDeleteVolumeSnapshotGroupMsg | org.zstack.header.storage.snapshot.group.APIDeleteVolumeSnapshotGroupMsg |
- 预期结果:任务详情和管理节点日志能够确定同一次失败请求使用了哪一个 API。
- 异常处理:如果只看到
VolumeSnapshotTreeBase$35或页面上的“删除快照”,不能据此选择配置项;继续执行步骤 2,从管理节点日志确认真实 API。
2. 使用 apiId 查询管理节点请求、timeout 和 deadline
- 检查对象:同一次请求的 API 类名、
timeout、deadline、内部消息和目标 ZSphere 主机。 - 操作位置:SSH 登录管理节点,使用步骤 1 记录的
apiId查询当前和归档日志。把引号中的示例值替换为现场值:
KB_API_UUID='将任务详情中的apiId粘贴到这里'
cd /usr/local/zstack/apache-tomcat/logs || exit 1
ls -lh management-server.log*
zgrep -a -n -C 5 "$KB_API_UUID" management-server.log*
zgrep -a -n "$KB_API_UUID" management-server.log* | grep -iE 'APIDeleteVolumeSnapshot(Group)?Msg|APIBatchDeleteVolumeSnapshotMsg|DeleteVolumeSnapshotMsg|MergeVolumeSnapshotOnKvmMsg|timeout|deadline|mergesnapshot|block job|error'
- 预期结果:
- 单盘或批量单盘删除应命中各自的 API;快照组删除应命中
APIDeleteVolumeSnapshotGroupMsg。 - 如果已按 24 小时创建新请求,应看到
86400000毫秒及与请求时间匹配的新 deadline。 - 内部
DeleteVolumeSnapshotMsg、MergeVolumeSnapshotOnKvmMsg和发往 KVM Agent 的/vm/volume/mergesnapshot请求应属于同一条调用链,剩余期限应与上层请求一致。 - 异常处理:
- 如果真实入口是快照组,而日志仍显示
10800000毫秒或约 3 小时 deadline,说明调整错了配置项,进入步骤 3。 - 如果真实入口和 timeout 均正确,但 deadline 仍是旧值,确认该任务是否在修改配置前已经开始;旧任务不能通过事后修改配置获得新期限。
- 如果无法从 apiId 找到 Agent
taskUuid,改用快照 UUID、快照组 UUID、虚拟机 UUID和准确时间窗继续查询,并保存所有命中行。
3. 在 CLI 中查询三个删除入口的当前配置
- 检查对象:三种删除入口的实际 GlobalConfig 值。不同版本或环境可能不同,必须查询后再决定是否调整。
- 操作位置:SSH 登录管理节点,进入
zstack-cli并使用有权限的账号登录,然后分别执行:
QueryGlobalConfig category=apiTimeout name=org.zstack.header.storage.snapshot.APIDeleteVolumeSnapshotMsg
QueryGlobalConfig category=apiTimeout name=org.zstack.header.storage.snapshot.APIBatchDeleteVolumeSnapshotMsg
QueryGlobalConfig category=apiTimeout name=org.zstack.header.storage.snapshot.group.APIDeleteVolumeSnapshotGroupMsg
- 预期结果:步骤 1 确认的真实 API,其配置值能够覆盖预期的删除和合并时间;同时把三个原值保存到工单中。
- 异常处理:不要因为报错位置包含
VolumeSnapshotTreeBase$35就查询同名配置。不要一次性盲目修改三个配置;只处理与实际入口对应的项目,并继续检查底层任务是否健康。
4. 查询 KVM Agent 和 libvirt block job 是否仍在推进
- 检查对象:Agent
taskUuid、虚拟机状态、目标盘、block job 进度和快照链 backing 信息。 - 操作位置:先从步骤 2 的管理节点日志取得目标 ZSphere 主机、Agent
taskUuid和虚拟机 UUID,再 SSH 登录该 ZSphere 主机执行。先根据virsh domblklist的结果确认故障硬盘对应的目标盘符;下面用vda举例,现场不一致时必须替换:
KB_TASK_UUID='将management-server日志中的taskUuid粘贴到这里'
KB_VM_UUID='将受影响虚拟机UUID粘贴到这里'
KB_DISK_TARGET='vda'
cd /var/log/zstack || exit 1
ls -lh zstack-kvmagent.log*
zgrep -a -n -C 5 "$KB_TASK_UUID" zstack-kvmagent.log*
zgrep -a -n "$KB_TASK_UUID" zstack-kvmagent.log* | grep -iE 'mergesnapshot|fullRebase|block|progress|timeout|deadline|cancel|error|fail'
virsh domstate "$KB_VM_UUID"
virsh domblklist "$KB_VM_UUID" --details
virsh blockjob "$KB_VM_UUID" "$KB_DISK_TARGET" --info
virsh qemu-monitor-command "$KB_VM_UUID" --pretty '{"execute":"query-block-jobs"}'
- 预期结果:
- 删除仍在执行时,block job 存在,连续两次查询的已处理数据量持续增长,且没有存储路径、I/O 或容量错误。
- 任务已经正常结束时,block job 可以不存在,但管理节点和 Agent 日志应有成功响应,虚拟机磁盘 backing 关系与平台记录一致。
- 异常处理:
virsh blockjob显示没有任务时,先按时间顺序检查此前是否已经发生 timeout 和 cancel;不要把清理阶段的“没有 active block job”当成首因。- block job 存在但连续观察无进度,或日志出现 I/O、iSCSI 路径、VG 容量、快照链错误时,停止重试,保留输出并转 ZStack 技术支持排查底层原因。延长 API timeout 不能修复这些问题。
- 不要手工执行
blockJobAbort、删除 LV、修改数据库快照状态或重启管理节点来清理现场。
5. 检查快照组的逐成员结果
- 检查对象:
APIDeleteVolumeSnapshotGroupEvent返回中的results[],以及每个成员的快照 UUID、卷 UUID、success和错误信息。 - 操作位置:在任务详情、API 返回或步骤 2 的管理节点日志中展开完整响应;逐项记录失败的是根硬盘还是数据硬盘。
- 预期结果:只有
results[]中所有成员都成功,才能认定快照组删除成功。 - 异常处理:外层 event 为
success=true、但任意results[n].success=false时,仍按删除失败处理。使用失败成员的卷 UUID、快照 UUID 和 AgenttaskUuid回到步骤 4 定位对应 block job。
6. 在受控窗口为正确入口延长超时并重新发起任务
临时方案(Workaround)
- 适用条件:已经确认真实 API;旧删除任务已结束;当前没有同一虚拟机的快照、备份、合并或迁移任务;虚拟机和磁盘 backing 链状态一致;数据存储/VG 有足够空间;步骤 4 未发现 I/O、路径或链异常;已保存原 GlobalConfig 值,并获得维护窗口和业务批准。
- 操作位置:在管理节点的
zstack-cli中,只执行与真实入口匹配的一条更新命令。以下 24 小时值来自已记录案例,是临时观察窗口,不代表所有环境的固定推荐值:
# 删除一个单盘快照时
UpdateGlobalConfig category=apiTimeout name=org.zstack.header.storage.snapshot.APIDeleteVolumeSnapshotMsg value=24h
# 批量删除多个单盘快照时
UpdateGlobalConfig category=apiTimeout name=org.zstack.header.storage.snapshot.APIBatchDeleteVolumeSnapshotMsg value=24h
# 删除快照组时
UpdateGlobalConfig category=apiTimeout name=org.zstack.header.storage.snapshot.group.APIDeleteVolumeSnapshotGroupMsg value=24h
- 重新发起:修改配置后必须创建一个新的删除请求。旧请求的 deadline 已固定,修改配置不会延长它。新请求开始后立即执行步骤 2,确认 API 请求及 Agent 调用携带
86400000毫秒和匹配的新 deadline。 - 观察方法:任务运行期间按固定间隔重复步骤 4 的只读查询,确认 block job 进度持续增长,同时观察数据存储容量、主机 I/O 和业务延迟。快照组还必须检查每个
results[]。 - 成功判据:新任务在 deadline 内结束;单盘删除返回成功,或快照组的所有成员结果均成功;不再存在对应 block job;虚拟机运行、磁盘 backing 链和平台快照清单一致;没有新增 I/O 或容量告警。
- 停止条件:block job 长时间无进度、预计无法在维护窗口内完成、出现存储路径/I/O/容量/快照链错误、虚拟机异常,或无法确认快照链一致性时,立即停止继续重试并联系 ZStack 技术支持。不要通过反复加大 timeout 掩盖底层问题。
- 回退方式:任务成功或失败并确认已完全结束后,将修改过的 GlobalConfig 恢复为步骤 3 记录的原值,再执行
QueryGlobalConfig确认。恢复原值只影响以后创建的请求,不会取消或缩短已经运行的任务。
补充信息
- 提交支持信息时,应包含:失败任务截图、API ID、快照/快照组/虚拟机/硬盘 UUID、准确时间窗、三个 API timeout 查询结果、管理节点命中日志、Agent
taskUuid日志、block job 两次以上的进度样本、数据存储容量和异常告警。 - 已记录案例能证明“快照组入口未调整,3 小时 deadline 到达后取消尚未完成的在线合并”,但不能仅凭该案例把合并慢进一步归因于某块磁盘、iSCSI 路径或 QEMU 缺陷,也不能保证调整为 24 小时后一定完成。
- 本文中的配置变更属于临时方案。正式长期处置应以底层 block job、存储性能和快照链证据为基础,不应把无限延长超时作为修复。
