镜像文件格式解析:raw、qcow2、vmdk、vhd 等格式的差异,以及它们对分区表的影响
镜像文件格式决定了数据在磁盘上的组织方式、元数据结构以及虚拟化平台的支持能力。不同的格式对分区表的存储、访问和修改行为有直接影响。本章将逐一解析主流镜像格式的核心差异,并重点分析它们对分区表排查工作的影响。
2.1 主流镜像格式概览
下表从元数据、稀疏特性、快照支持、平台兼容性四个维度对比了四种常见格式:
| 格式 | 元数据存储 | 稀疏文件支持 | 快照/克隆 | 主要平台 |
|---|---|---|---|---|
| raw | 无独立元数据 | 否(依赖文件系统) | 不支持 | 所有平台 |
| qcow2 | 内嵌头部 + L2 表 | 是(原生) | 支持(内部/外部) | QEMU/KVM |
| vmdk | 描述符文件 + 扩展头 | 是(稀疏粒度可配) | 支持(快照链) | VMware |
| vhd/vhdx | 页脚/头部 + BAT 表 | 是(动态扩展) | 有限(差异盘) | Hyper-V / Azure |
排查要点: raw 格式没有元数据层,分区表直接暴露在文件偏移 0 处,
fdisk -l 或 parted 可以直接读取。而 qcow2、vmdk、vhd 的元数据层会改变分区表的访问路径,必须通过 qemu-nbd 或 losetup -P 等工具映射后才能识别。
2.2 raw 格式:最直接的访问路径
raw 格式是磁盘数据的逐字节副本,没有头部、没有元数据、没有压缩。分区表位于 LBA0(偏移 0x1BE 处的主引导记录)。
- 优势:性能最高,工具兼容性最好,
dd、fdisk、parted可直接操作。 - 劣势:占用完整磁盘大小,不支持快照,传输效率低。
- 分区表影响:无任何间接层,分区表损坏后恢复手段直接。
# 直接查看 raw 镜像的分区表
fdisk -l disk.raw
# 使用 dd 提取 MBR
dd if=disk.raw of=mbr.bin bs=512 count=1
2.3 qcow2 格式:元数据层带来的分区表偏移
qcow2 在镜像头部(通常 2 MB 对齐)存储了 L1/L2 地址映射表。虚拟机看到的 LBA 0 在物理文件中并不对应偏移 0,而是经过元数据翻译后的虚拟地址。
- 元数据开销:头部 512 字节 + 扩展区域,后续 L1 表、L2 表、数据簇。
- 稀疏特性:未写入的簇不占用物理空间,分区表所在簇通常被写入,因此物理上存在。
- 分区表影响:直接
fdisk读取 qcow2 文件会看到乱码或报错“无法读取分区表”。必须通过qemu-nbd挂载为网络块设备。
# 挂载 qcow2 镜像为 nbd 设备
modprobe nbd max_part=8
qemu-nbd --connect=/dev/nbd0 disk.qcow2
# 查看分区表
fdisk -l /dev/nbd0
# 完成后断开
qemu-nbd --disconnect /dev/nbd0
常见陷阱: 如果 qcow2 镜像使用了
preallocation=metadata 或 cluster_size=512 等非默认参数,分区表的物理偏移可能发生变化。排查时务必使用 qemu-img info 查看镜像参数。
2.4 vmdk 格式:描述符文件与扩展头
vmdk 分为两种类型:单文件(monolithic flat) 和 多文件(split / stream-optimized)。单文件 vmdk 的头部包含 512 字节的描述符区域,之后才是数据区。
- 描述符区域:包含磁盘几何参数、CID、父镜像引用等元数据。
- 数据区起始偏移:对于 monolithic flat 类型,数据从偏移 0 开始(头部在扩展描述符中);对于 monolithic sparse 类型,数据区从偏移 512 或 1 MB 开始。
- 分区表影响:分区表可能不在文件偏移 0 处,需要根据描述符中的
ddb.geometry.sectors和ddb.geometry.heads计算真实偏移。
# 查看 vmdk 描述符信息
head -20 disk.vmdk
# 使用 qemu-nbd 挂载(兼容 vmdk)
qemu-nbd --connect=/dev/nbd0 disk.vmdk
fdisk -l /dev/nbd0
2.5 vhd/vhdx 格式:页脚与 BAT 表
vhd 格式在文件末尾存储 512 字节的页脚(footer),包含磁盘大小、CHS 参数、UUID 等。vhdx 是 vhd 的改进版,使用 64 KB 对齐的头部和日志区域。
- vhd 页脚:位于文件末尾 512 字节,数据区从偏移 0 开始,但动态扩展时 BAT(Block Allocation Table)位于文件头部。
- vhdx 结构:头部 1 MB 区域包含元数据、日志、BAT 表,数据区从 1 MB 对齐偏移开始。
- 分区表影响:vhd 的分区表在偏移 0 处,但动态扩展 vhd 的 BAT 表可能覆盖前 512 字节?不会——BAT 表位于头部,数据区从偏移 0 开始,分区表始终在 LBA0。
# 使用 losetup 挂载 vhd(需要内核支持)
losetup -P --show --read-only /dev/loop0 disk.vhd
fdisk -l /dev/loop0
# 使用 qemu-nbd 挂载 vhdx
qemu-nbd --connect=/dev/nbd0 disk.vhdx
fdisk -l /dev/nbd0
2.6 格式对分区表排查的影响对比
| 排查场景 | raw | qcow2 | vmdk | vhd/vhdx |
|---|---|---|---|---|
直接 fdisk 读取 |
✅ 支持 | ❌ 需挂载 | ❌ 需挂载 | ❌ 需挂载 |
| 分区表物理偏移 | 固定 0 | 虚拟化,不固定 | 依赖描述符 | 固定 0 |
| 稀疏区域分区表丢失 | 不适用 | 可能(未写入) | 可能(稀疏粒度大) | 可能(动态扩展) |
| 快照链中分区表 | 不适用 | 需遍历快照 | 需遍历快照 | 差异盘需合并 |
| 推荐排查工具 | fdisk / dd |
qemu-nbd |
qemu-nbd / vmware-mount |
losetup / qemu-nbd |
核心结论: 分区表排查的第一步是确认镜像格式。raw 格式可以直接操作;qcow2 和 vmdk 必须通过块设备映射工具访问;vhd/vhdx 虽然分区表在偏移 0,但动态扩展特性可能导致稀疏区域未分配,需要先转换为固定大小再排查。
2.7 格式转换对分区表的影响
使用 qemu-img convert 进行格式转换时,分区表内容会被逐字节复制,理论上不会改变。但以下情况需要警惕:
- 稀疏转换:从 qcow2 转 raw 时,如果目标文件系统不支持稀疏,分区表所在簇会被正常写入,但其他未分配簇可能被填充为 0,不影响分区表。
- 对齐参数:
-o cluster_size=512会改变 qcow2 的簇大小,但分区表数据不变。 - 截断风险:转换时指定了错误的大小参数(如
-o size小于原始磁盘),分区表可能被截断。
# 安全转换:保留完整数据
qemu-img convert -f qcow2 -O raw disk.qcow2 disk.raw
# 验证转换后分区表
fdisk -l disk.raw
2.8 实战排查流程
- 识别格式:使用
file命令或qemu-img info确认镜像格式。 - 选择挂载方式:根据格式选择
qemu-nbd、losetup或直接读取。 - 读取分区表:使用
fdisk -l、parted -l或gdisk -l查看。 - 验证完整性:检查分区表签名(MBR 的 0x55AA,GPT 的 EFI PART)。
- 备份分区表:使用
dd或sgdisk --backup备份。
# 通用排查脚本片段
IMG=$1
FORMAT=$(qemu-img info --output=json "$IMG" | jq -r '.format')
echo "镜像格式: $FORMAT"
case $FORMAT in
raw)
fdisk -l "$IMG"
;;
qcow2|vmdk|vhdx)
modprobe nbd max_part=8
qemu-nbd --connect=/dev/nbd0 "$IMG"
fdisk -l /dev/nbd0
qemu-nbd --disconnect /dev/nbd0
;;
vhd)
losetup -P --show --read-only /dev/loop0 "$IMG"
fdisk -l /dev/loop0
losetup -d /dev/loop0
;;
*)
echo "不支持的格式"
;;
esac