2192 字
11 分钟
KVM虚拟化入门(二):不影响数据扩容 KVM 虚拟机磁盘完全指南

环境:Dell PowerEdge R730 / Debian 13 宿主机 / KVM+libvirt / Debian 13 虚拟机

目标:将虚拟机磁盘从 30G 扩容到 50G,不影响已有数据

风险等级:⚠️ 中等(涉及分区表操作,务必先备份)

1. 扩容前准备#

1.1 确认虚拟机信息#

首先列出所有虚拟机,确认目标 VM 的名称和运行状态:

Terminal window
sudo virsh list --all
# Id 名称 状态
# ------------------------
# 1 debian13 运行
# 2 arch-vm 运行
# - fedora-vm 关闭

查看目标 VM 的磁盘配置:

Terminal window
sudo virsh domblklist debian13
# 目标 源
# ----------------------------------------------
# vda /var/lib/libvirt/images/debian.qcow2

1.2 检查磁盘镜像详情#

Terminal window
# VM 运行时需加 --force-share
sudo qemu-img info --force-share /var/lib/libvirt/images/debian.qcow2
# VM 关机后直接查
sudo qemu-img info /var/lib/libvirt/images/debian.qcow2

输出示例:

image: /var/lib/libvirt/images/debian.qcow2
file format: qcow2
virtual size: 30 GiB (32212254720 bytes) ← 虚拟大小(对 VM 可见)
disk size: 27.4 GiB ← 实际占用宿主机空间
cluster_size: 65536

1.3 确认 VM 内磁盘使用情况#

通过 SSH 或 virsh console 进入 VM,查看分区布局和剩余空间:

Terminal window
lsblk
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
# vda 254:0 0 30G 0 disk
# ├─vda1 254:1 0 28.4G 0 part /
# ├─vda2 254:2 0 1K 0 part
# └─vda5 254:5 0 1.6G 0 part [SWAP]
df -h /
# 文件系统 大小 已用 可用 已用% 挂载点
# /dev/vda1 28G 25G 1.5G 95% /

95% 已用,必须扩容了!

判断分区表类型(影响后续操作):

Terminal window
sudo fdisk -l /dev/vda | grep "Disklabel type"
# Disklabel type: dos → MBR 分区表
# Disklabel type: gpt → GPT 分区表

或使用 parted

Terminal window
sudo parted /dev/vda print | grep "Partition Table"
# Partition Table: msdos → MBR
# Partition Table: gpt → GPT

2. 备份(最重要的一步)#

⚡ 无论对操作多有把握,这一步绝对不能跳过。 qemu-img resize 本身不删数据,但后续分区调整一旦失误,分区表损坏可能导致数据全部丢失。

2.1 关闭虚拟机#

扩容磁盘最好在 VM 关机状态下进行(部分格式支持在线扩容,但关机最安全):

Terminal window
sudo virsh shutdown debian13
# 等待关机完成
sudo virsh list --all | grep debian13
# - debian13 关闭

2.2 检查宿主机剩余空间#

确保有足够空间存放备份文件(备份和原文件一样大):

Terminal window
df -h /var/lib/libvirt/images/
# 文件系统 大小 已用 可用 已用% 挂载点
# /dev/sda1 251G 44G 195G 19% /

195G 可用,备份 31G 的 qcow2 绰绰有余。

2.3 执行备份#

Terminal window
# 带日期的备份文件名
sudo cp /var/lib/libvirt/images/debian.qcow2 \
/var/lib/libvirt/images/debian.qcow2.bak.$(date +%Y%m%d)
# 确认备份完成
ls -lh /var/lib/libvirt/images/debian.qcow2*
# -rw------- 1 libvirt-qemu libvirt-qemu 31G 6月 3日 11:58 debian.qcow2
# -rw------- 1 root root 31G 6月 3日 12:08 debian.qcow2.bak.20260603

⚠️ 31G 文件拷贝需要约 2~3 分钟,磁盘 I/O 期间 ls 等命令可能卡顿,耐心等待。

3. 扩展虚拟磁盘#

3.1 qcow2 格式扩容#

Terminal window
# 增加 20G
sudo qemu-img resize /var/lib/libvirt/images/debian.qcow2 +20G
# 或者指定最终大小
sudo qemu-img resize /var/lib/libvirt/images/debian.qcow2 50G

验证:

Terminal window
sudo qemu-img info /var/lib/libvirt/images/debian.qcow2 | grep "virtual size"
# virtual size: 50 GiB (53687091200 bytes) ✅

3.2 raw 格式扩容#

如果是 raw 格式镜像,方法类似:

Terminal window
sudo qemu-img resize /var/lib/libvirt/images/debian.raw +20G

3.3 启动虚拟机验证磁盘大小#

Terminal window
sudo virsh start debian13
# 进入 VM 或用 SSH 确认磁盘已变大
lsblk
# vda 254:0 0 50G 0 disk ← 50G 了!
# ├─vda1 254:1 0 28.4G 0 part / ← 但分区还是旧的

磁盘总量已变为 50G,但分区和文件系统仍为原来的大小,需要继续扩容。

4. 扩容分区#

分区扩容的复杂程度取决于分区表类型和布局。以下分场景说明。

4.1 场景一:GPT 分区表 + 根分区是最后一个分区(最简单)#

这是现代 Linux 发行版的典型布局,使用 growpart 一键搞定:

Terminal window
# 安装工具(如未安装)
sudo apt install cloud-guest-utils -y
# 扩容第 1 个分区到磁盘末尾
sudo growpart /dev/vda 1

4.2 场景二:MBR 分区表 + 根分区后还有扩展分区和 swap(本文实战)#

这是笔者遇到的真实场景——根分区 vda1 后面紧跟着扩展分区 vda2 和 swap vda5,无法直接扩容 vda1,必须先删除后面的分区再重建。

初始布局#

vda (30G)
├─ vda1 28.4G ext4 /
├─ vda2 1K 扩展分区
└─ vda5 1.6G swap

第 1 步:关闭 swap 并注释 fstab#

Terminal window
sudo swapoff /dev/vda5
sudo sed -i '/swap/s/^/#/' /etc/fstab

第 2 步:删除扩展分区和 swap#

Terminal window
sudo parted /dev/vda rm 5 # 删除 swap 逻辑分区
sudo parted /dev/vda rm 2 # 删除扩展分区

第 3 步:扩容根分区#

Terminal window
# 将 vda1 扩容到 48G(留 2G 给后面的 swap)
sudo parted /dev/vda resizepart 1 48GiB

parted 会警告分区正在使用中,输入 Yes 确认。resize2fs 支持在线扩容,不影响正在运行的系统。

第 4 步:重建 swap 分区#

扩容后磁盘布局:

vda (50G)
├─ vda1 48G ext4 /
└─ 空闲 2G

使用 fdisk 重建扩展分区和 swap:

Terminal window
sudo fdisk /dev/vda
# n → p → 回车(默认分区号)→ 回车(默认起始扇区)→ 回车(默认结束扇区)
# t → 分区号 → 82(Linux swap)
# w(写入并退出)

也可以用 parted 非交互模式:

Terminal window
sudo parted -s /dev/vda mkpart extended 48GiB 100%
sudo parted -s /dev/vda mkpart linux-swap 48GiB 100%

第 5 步:格式化 swap 并恢复 fstab#

Terminal window
sudo mkswap /dev/vda5
sudo swapon /dev/vda5
# 获取新 swap 的 UUID
sudo blkid /dev/vda5
# /dev/vda5: UUID="c7117931-8d4f-4145-a23a-9855dc8eb9a4" TYPE="swap"
# 写入 fstab
echo 'UUID=c7117931-8d4f-4145-a23a-9855dc8eb9a4 none swap sw 0 0' | sudo tee -a /etc/fstab

4.3 场景三:LVM 布局#

如果 VM 使用了 LVM(逻辑卷管理),操作路径不同——不需要动分区表,直接在 LVM 层面扩容:

Terminal window
# 1. 让内核识别新磁盘大小
echo 1 > /sys/block/vda/device/rescan
# 2. 扩容 PV(物理卷)
sudo pvresize /dev/vda2 # 假设 LVM 在 vda2 上
# 3. 扩容 LV(逻辑卷)
sudo lvextend -l +100%FREE /dev/mapper/vg0-root
# 4. 扩容文件系统(见第 5 节)

LVM 的优势:无需关机、无需删分区、在线完成全部操作。

5. 扩容文件系统#

分区扩容后,文件系统还不知道分区变大了,需要执行 resize2fs(ext4)或等价的命令。

5.1 ext4 文件系统#

Terminal window
sudo resize2fs /dev/vda1

输出示例:

resize2fs 1.47.2 (1-Jan-2025)
Filesystem at /dev/vda1 is mounted on /; on-line resizing required
old_desc_blocks = 4, new_desc_blocks = 6
The filesystem on /dev/vda1 is now 12582656 (4k) blocks long.

ext4 支持在线扩容resize2fs 直接作用于已挂载的 /),无需卸载或进入恢复模式。

5.2 XFS 文件系统#

Terminal window
# XFS 只能在线扩容,且必须指定挂载点
sudo xfs_growfs /

⚠️ XFS 不支持缩容,只能扩大不能缩小。

5.3 Btrfs 文件系统#

Terminal window
# 扩容到分区最大
sudo btrfs filesystem resize max /
# 或指定大小
sudo btrfs filesystem resize 48G /

6. 验证结果#

6.1 确认分区布局#

Terminal window
lsblk
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
# vda 254:0 0 50G 0 disk
# ├─vda1 254:1 0 48G 0 part /
# ├─vda2 254:2 0 1K 0 part
# └─vda5 254:5 0 2G 0 part [SWAP]

6.2 确认文件系统#

Terminal window
df -h /
# 文件系统 大小 已用 可用 已用% 挂载点
# /dev/vda1 48G 25G 20G 56% /

6.3 确认 swap#

Terminal window
free -h
# total used free
# 交换: 2.0Gi 0B 2.0Gi

6.4 最终对比#

项目扩容前扩容后
虚拟磁盘30 GB50 GB
根分区 /dev/vda128.4G (95% 已用)48G (56% 已用)
Swap1.6G2.0G

7. 清理备份#

确认系统稳定运行一段时间后(建议 3~7 天),可删除备份释放空间:

Terminal window
# 确认一切正常后执行
sudo rm /var/lib/libvirt/images/debian.qcow2.bak.20260603

31G 备份文件占地不小,但别急着删——等确认所有服务正常运行后再清理。

8. 常见问题排查#

问题可能原因解决方案
qemu-img: Failed to get shared "write" lockVM 正在运行--force-share 或先关机
growpart: unexpected output分区表非 GPT改用 parted 手动调整
parted: Can't have overlapping partitions新分区起始位置错误unit GiB print free 查看精确边界
resize2fs: Bad magic number文件系统非 ext4确认文件系统类型:df -T /
扩容后 df 没变化只扩了 PV/LV 没扩文件系统执行 resize2fs/xfs_growfs
VM 启动失败分区表损坏从备份恢复:cp debian.qcow2.bak.* debian.qcow2

9. 总结#

核心流程#

备份磁盘 ──► 关机 VM ──► qemu-img resize ──► 启动 VM
├── 调整分区
│ ├── GPT: growpart 一键
│ ├── MBR: 删重建 swap + resizepart
│ └── LVM: pvresize + lvextend
└── 扩容文件系统
├── ext4: resize2fs
├── XFS: xfs_growfs
└── Btrfs: btrfs filesystem resize

关键要点#

  1. 备份是第一优先级——31G 的磁盘备份只需几分钟,数据恢复可能永远做不到
  2. 关机扩容最安全——虽然 ext4/XFS 支持在线扩容,但分区表操作建议关机
  3. MBR 分区表是先删除后重建——根分区后的逻辑分区必须先删,扩容后再重建
  4. ext4 resize2fs 支持在线扩容——即使是根分区 / 也可以在挂载状态下扩容
  5. swap 的 UUID 会变——重建 swap 后务必更新 /etc/fstab,否则重启后 swap 不生效

通用扩容命令速查#

Terminal window
# === 宿主机 ===
sudo virsh shutdown <vm-name>
sudo cp <disk-path> <disk-path>.bak.$(date +%Y%m%d)
sudo qemu-img resize <disk-path> +<增量>G
sudo virsh start <vm-name>
# === 虚拟机内 ===
# GPT 分区
sudo growpart /dev/vda 1
sudo resize2fs /dev/vda1 # ext4
sudo xfs_growfs / # XFS
sudo btrfs filesystem resize max / # Btrfs
# LVM
sudo pvresize /dev/vda2
sudo lvextend -l +100%FREE /dev/mapper/vg0-root
sudo resize2fs /dev/mapper/vg0-root

本文记录于 2026 年 6 月 3 日,环境 Debian 13 + libvirt 11.3.0 + QEMU 10.0.8

KVM虚拟化入门(二):不影响数据扩容 KVM 虚拟机磁盘完全指南
https://www.mintlab.top/posts/tries/kvm-disk-resize-guide/
作者
Mint
发布于
2026-06-03
许可协议
CC BY-NC-SA 4.0
发表评论

输入用户名和邮箱后自动检查登录状态。登录后用户名和邮箱将被绑定, 只可以修改头像和主页链接。

未登录
昵称
邮箱
填写头像链接与主页链接

头像链接为空默认使用gravatar头像

头像
主页
人机验证
评论列表

以下是可爱的评论们:

暂无评论, 呜呜, 快来评论喵!