本文主要记录 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 size | 1 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 size 与 file format。disk 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 未明显增加——符合“尚未在客户机写入新空间”的预期。
客户机内扩展分区与文件系统
镜像变大后,任选其一:
- 启动虚拟机,在客户机内用
fdisk/parted/growpart、LVM、resize2fs/xfs_growfs/btrfs filesystem resize等扩展。 - 不启动虚拟机,在宿主机用 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 等不要写进对外文档;本文已用占位或省略。