本文主要记录 QEMU/KVM 场景下扩大 qcow2 虚拟磁盘容量的两段操作:在宿主机用 qemu-img resize 增加镜像虚拟大小,以及在不启动客户机时用 qemu-nbd 把镜像映射为块设备以便查看分区、扩展文件系统。

需要注意的是:只增大 qcow2 的 virtual size 并不会自动让客户机内分区和文件系统变大。客户机内仍要用 fdisk/parted、LVM 或对应 FS 工具吃掉新增空间。扩容前应关闭使用该镜像的虚拟机,并做好镜像备份;有快照时优先理清快照链,必要时先合并/删除快照再扩容(以当前 qemu 版本行为为准)。

背景说明

qcow2 常见为稀疏动态分配:qemu-img info 里的 virtual size 是客户机看到的盘容量,disk size 是宿主机上实际占用。扩容通常改的是 virtual size;物理占用随写入增长。

本文示例环境(历史记录,路径与容量请按现场替换):

项目取值(示例)
镜像vdisk2.qcow2
扩容前 virtual size1 TiB
扩容增量+2048G(扩后约 3 TiB)
宿主机qemu-img / qemu-nbd(示例内核信息来自 Unraid 类环境)
镜像内分区多分区,类型含 Linux raid autodetect(md 成员盘场景)

站内相关可参考 qemu-img 镜像格式转换 等文。

扩容镜像文件

关闭虚拟机

确认没有进程打开该 qcow2(libvirt 域已 shut off,或对应 qemu 进程已退出)。对正在写入的镜像做 resize 有损坏风险。

扩容前检查

qemu-img info vdisk2.qcow2

历史输出要点(示意):

image: vdisk2.qcow2
file format: qcow2
virtual size: 1 TiB (1099511627776 bytes)
disk size: 586 GiB
cluster_size: 65536

这里我们关注 virtual sizefile formatdisk size 小于 virtual size 在稀疏镜像上是正常现象。

执行 resize

增加 2048G(相对扩容用 + 前缀):

qemu-img resize vdisk2.qcow2 +2048G

成功时通常打印:

Image resized.

说明:

  • +10G 表示在现有 virtual size 上增加 10G
  • 不带 + 的绝对值(如 150G)表示把 virtual size 设为 该值(可能缩小;缩小前需确保未使用空间足够,且 qemu 版本支持 shrink 选项时才安全)

扩容后复查

qemu-img info vdisk2.qcow2

历史结果要点:

virtual size: 3 TiB (3298534883328 bytes)
disk size: 586 GiB

virtual size 已变大,disk size 未明显增加——符合“尚未在客户机写入新空间”的预期。

客户机内扩展分区与文件系统

镜像变大后,任选其一:

  1. 启动虚拟机,在客户机内用 fdisk/parted/growpart、LVM、resize2fs/xfs_growfs/btrfs filesystem resize 等扩展。
  2. 不启动虚拟机,在宿主机用 nbd(或 libguestfs)挂载后操作(见下一节)。

Linux 客户机内常见路径(设备名以现场为准,如 /dev/vda):

# 查看分区
fdisk -l
lsblk -f

# 扩展最后一个分区(示例:parted)
parted /dev/vda
# print
# resizepart <N> 100%
# quit

# ext4 扩 FS
resize2fs /dev/vda<N>

若使用 LVM,需要先扩展 PV/VG/LV 再扩文件系统。Windows 客户机可用磁盘管理(diskmgmt.msc)扩展卷。

宿主机用 qemu-nbd 映射镜像

适用于离线检查分区、在宿主机上直接 resize 文件系统(需文件系统工具支持、且分区布局你足够熟悉)。

加载 nbd 模块

modprobe nbd max_part=63
lsmod | grep nbd

若输出中有 nbd 行,说明模块已加载。max_part 控制每个 nbd 设备可暴露的分区数量上限。

可选查看模块参数:

modinfo nbd

选择空闲 nbd 设备并连接

ls /dev/nbd*

选定未使用的节点(示例 /dev/nbd0),连接镜像:

qemu-nbd -c /dev/nbd0 vdisk2.qcow2

识别分区

fdisk -l /dev/nbd0

历史示意(扩容后 virtual size 为 3 TiB;分区表仍反映客户机内布局,末分区 End 可能尚未延伸到新盘尾):

Disk /dev/nbd0: 3 TiB, ...
Disklabel type: dos

Device      Boot    Start        End    Sectors    Size Id Type
/dev/nbd0p1          8192   16785407   16777216      8G fd Linux raid autodetect
/dev/nbd0p2      16785408   20979711    4194304      2G fd Linux raid autodetect
/dev/nbd0p3      21241856 2147278847 2126036992 1013.8G fd Linux raid autodetect
lsblk -f

示意中分区类型为 linux_raid_member 时,说明这是 md RAID 成员盘,不能简单当单盘 ext4 直接 resize2fs。需要:

  • 在完整 RAID 套件环境中扩展阵列与上层 FS,或
  • 确认业务允许的离线阵列操作流程

UUID/阵列名等已脱敏处理;以本机 lsblk -f / mdadm --detail 为准。

断开 nbd

操作结束后务必断开,避免镜像被占用:

qemu-nbd -d /dev/nbd0

确认无残留占用后再启动依赖该镜像的虚拟机。

验证结果

步骤判断标准
resize 后qemu-img info 的 virtual size 为目标值;命令无报错
客户机内lsblk/df -h 看到分区与 FS 容量增加
nbd 路径fdisk -l /dev/nbdX 能列出分区;用完 qemu-nbd -d 成功
启动虚拟机正常开机,无因分区表错误无法挂载

注意事项

  • 先备份镜像(或存储快照),再 resize / 改分区表。
  • 存在 qcow2 外部快照时,对 base 或 top 的 resize 行为更复杂,优先查阅当前版本文档并在测试盘验证。
  • 缩小 virtual size 极易丢数据,默认只做增大。
  • RAID 成员、LVM、btrfs 多设备等布局,扩容步骤与“单盘单分区 ext4”完全不同;本文 nbd 示例停在识别分区,后续 FS 扩展需按实际类型继续(原稿提到 btrfs 场景,完整命令以现场 btrfs 工具链为准,待确认具体子卷挂载方式)。
  • Unraid / 定制内核上 nbd.ko 路径与参数以 modinfo 为准。
  • 内网主机名、阵列 UUID 等不要写进对外文档;本文已用占位或省略。

参考资料