跳过正文
  1. 博客文章/

PVE 虚拟机启动失败:qcow2 corrupt 标记残留的排查与修复

·628 字·3 分钟·
SRE Linux 虚拟化 Storage 运维
Zayn
作者
Zayn
专注 Kubernetes、CI/CD、可观测性等云原生技术栈,记录生产环境中的实战经验与踩坑复盘。
目录
一台 PVE 虚拟机突然无法启动,QEMU 报 “Image is corrupt”。快照回滚失败,专用修复工具未授权。最终发现是 qcow2 镜像头部的 corrupt 保护标记残留,一条命令即可修复。本文完整记录排查过程、根因分析和标准 SOP。

结论前置
#

项目内容
故障类型qcow2 镜像头部残留 corrupt: true 标记
恢复用时约 25 分钟
修复命令qemu-img check -r all <disk.qcow2>
数据损失
三个关键结论:(1) corrupt: true 不等于数据已损坏,check 通过说明结构完好;(2) 修复只需 check -r all,无需数据恢复或镜像重建;(3) 快照不能替代完整备份,底层镜像异常时快照回滚同样失败。

故障现象
#

执行 qm start <vmid> 后,PVE 控制台输出:

qcow2: Image is corrupt; cannot be opened read/write
start failed: QEMU exited with code 1

受影响磁盘为关键数据盘(虚拟 1 TiB,实占 329 GiB),不可废弃,必须原地修复。


排查时间线
#

flowchart TD
    START["VM 启动失败"]
    START --> ERR["报错:qcow2 Image is corrupt
QEMU exited with code 1"] ERR --> CHECK1["qemu-img check
一致性检查"] CHECK1 --> R1{"检查结果?"} R1 -->|"No errors found"| CONFLICT["矛盾:check 通过
但 QEMU 仍报错"] CONFLICT --> CONFIG["qm config
确认目标磁盘为关键盘"] CONFIG --> ROLLBACK["尝试快照回滚"] ROLLBACK --> R2{"回滚结果?"} R2 -->|失败| SNAP_FAIL["镜像无法打开
快照回滚被阻断"] SNAP_FAIL --> INFO["qemu-img info
确认 corrupt: true"] INFO --> FIX1["qemu-img check -r leaks
低风险修复"] FIX1 --> FIX2["qemu-img check -r all
清除 corrupt 标记"] FIX2 --> VERIFY["qemu-img info
确认 corrupt: false"] VERIFY --> END["VM 启动成功"] style START fill:#e55,color:#fff style CONFLICT fill:#f90,color:#fff style SNAP_FAIL fill:#f90,color:#fff style END fill:#4a4,color:#fff

一致性检查通过,但启动仍失败
#

qemu-img check /path/to/vm-disk.qcow2
# 输出:No errors were found on the image.
关键矛盾qemu-img check 通过说明镜像内部逻辑结构完整(refcount、cluster、L1/L2 表均无异常),但 QEMU 启动仍报错。问题来自镜像头部的状态标记,而非数据本身。

快照回滚全部失败
#

三个自动快照均无法恢复:

qm rollback <vmid> <snapshot-name>
# 结果:失败,错误仍指向 qcow2 镜像无法打开

快照回滚流程需要先以读写方式打开底层镜像。corrupt 标记导致 QEMU 在第一步就拒绝打开,回滚被阻断。

方案评估
#

方案风险结论
qemu-img check -r优先采用
qcow2-dump 专项工具环境未授权,不可用
快照回滚已确认失效
qemu-img convert 重建耗时长,空间需求大,留作后手
qemu-nbd + ddrescue适合严重损坏,本次非首选

确认根因并修复
#

# Step 1:查看镜像状态
qemu-img info /path/to/vm-disk.qcow2
# 输出:corrupt: true  <-- 损坏标记存在

# Step 2:执行修复
qemu-img check -r all /path/to/vm-disk.qcow2

# Step 3:验证修复
qemu-img info /path/to/vm-disk.qcow2
# 输出:corrupt: false  <-- 标记已清除

# Step 4:启动虚拟机
qm start <vmid>
# 成功

根因分析
#

corrupt 标记的触发机制
#

flowchart TD
    A1["宿主机异常重启 / 强制断电"] --> F
    A2["存储设备瞬断 I/O 中断"] --> F
    A3["QEMU 进程被强制 kill"] --> F
    A4["存储空间不足导致写入失败"] --> F
    F["QEMU 检测到写入异常"] --> G["标记 corrupt: true"]
    G --> H["拒绝后续读写打开"]
    H --> I["异常结束后标记未自动清理"]
    I --> J["虚拟机下次启动失败"]

qcow2 镜像头部有一个 corrupt 字段,是 QEMU 的保护机制。写入异常时置为 true,防止后续写入造成更严重损坏。但异常结束后标记不会自动清理。

qemu-img check vs QEMU 启动的检查差异
#

检查维度qemu-img checkQEMU 启动
cluster 分配检查不独立检查
refcount 信息检查不独立检查
L1/L2 table检查不独立检查
corrupt 标记不清除直接拒绝

这是最容易误判的点:check 通过不代表能启动,必须用 check -r 才能清除标记。

快照回滚失败的原理
#

flowchart TD
    A["qm rollback"] --> B["需要打开底层镜像"]
    B --> C["镜像头部 corrupt: true"]
    C --> D["QEMU 拒绝读写打开"]
    D --> E["快照回滚被阻断"]

    style C fill:#f66,color:#fff
    style E fill:#f66,color:#fff
快照不等于完整灾备。快照适合短期版本回退,但底层镜像异常时快照回滚同样失败。关键业务必须建立"快照 + 独立完整备份"双层保护。

标准 SOP:三阶段修复
#

遇到 PVE / qcow2 虚拟机启动失败,按以下三阶段顺序处理,不跳步。

阶段一:诊断(只读,零风险)
#

# 停止虚拟机
qm stop <vmid> || true

# 查看镜像状态,确认 corrupt 字段
qemu-img info <disk.qcow2>

# 一致性检查(不执行修复)
qemu-img check <disk.qcow2>
flowchart TD
    A["qemu-img info + check"] --> B{"corrupt 标记?"}
    B -->|"false"| C["check 通过? → 镜像正常,检查其他原因"]
    B -->|"true"| E{"check 结果?"}
    E -->|无错误| F["阶段二:清除 corrupt 标记"]
    E -->|有错误| G["阶段二:修复错误 + 清除标记"]
    E -->|严重错误| H["阶段三:数据级恢复"]

    style F fill:#6a6,color:#fff
    style G fill:#fa0,color:#fff
    style H fill:#f66,color:#fff

阶段二:标记修复(低风险)
#

# Step 1:仅修复 leaks(最保守)
qemu-img check -r leaks <disk.qcow2>

# Step 2:修复所有可修复问题,含 corrupt 标记
qemu-img check -r all <disk.qcow2>

# Step 3:验证 corrupt: false
qemu-img info <disk.qcow2>

# Step 4:启动虚拟机
qm start <vmid>

阶段三:高级恢复(高风险,阶段二无效时)
#

# 检查宿主机内核日志
dmesg -T | grep -iE "I/O error|corrupt|EXT4-fs error|nvme|scsi"

# 镜像转换重建
qemu-img convert --salvage -O qcow2 <damaged.qcow2> <recovered.qcow2>

# 数据级恢复(最后手段)
modprobe nbd max_part=8
qemu-nbd --connect=/dev/nbd0 <disk.qcow2>
ddrescue /dev/nbd0 /dev/nbd1 rescue.log
qemu-nbd --disconnect /dev/nbd0
阶段三风险提示:执行前确认磁盘空间充足,强烈建议先拷贝镜像文件。宿主机存在 I/O 错误时优先排查底层存储硬件。

预防措施
#

1. 存储健康巡检
#

# 内核错误日志
dmesg -T | grep -iE "I/O error|blk|buffer|EXT4-fs error|nvme|scsi|corrupt|ENOSPC"

# 系统级错误
journalctl -b -p err..alert

2. 存储空间监控
#

建议告警阈值:

  • 文件系统使用率 > 80%
  • inode 使用率 > 70%
  • LVM thin pool > 75%

3. 有序停机
#

# 正确方式:等待 QEMU 完成写入后退出
qm shutdown <vmid>
qm wait <vmid>

强制 kill -9 QEMU、宿主机掉电、存储瞬断均可能触发 corrupt 标记。

4. 双层备份保护
#

flowchart LR
    VM["关键虚拟机"]
    VM -->|短期| SNAP["快照:每日自动"]
    VM -->|长期| BAK["完整备份:每周全量"]
    SNAP --> SA["用途:版本回退"]
    SNAP --> SB["限制:依赖底层镜像"]
    BAK --> BA["用途:灾难恢复"]
    BAK --> BB["存储:独立备份介质"]

核心经验
#

  1. corrupt: true 不等于数据已损坏。须结合 qemu-img check 判断,check 通过说明是标记残留
  2. qemu-img check 不清除 corrupt 标记。只有 check -r leakscheck -r all 才能清除
  3. 快照回滚依赖底层镜像正常打开。镜像有 corrupt 标记时快照回滚同样失败
  4. 分阶段修复,低风险优先。顺序:infocheckcheck -r leakscheck -r all,不跳步
  5. 关键磁盘高风险操作前必须先备份。即使时间紧迫,也应至少新建快照

相关文章

Linux LVM 分区扩容完整指南
·827 字·4 分钟
SRE Linux Lvm Storage
Gitea Actions ActRunner 基于 Systemd 部署安装
·142 字·1 分钟
SRE Devops Linux
当 AI Agent 遇上运维自动化:我的实践踩坑之路
·135 字·1 分钟
AI AI Agent 自动化 运维 OpenClaw