VMware 虚拟机磁盘扩容实战文档(Ubuntu 22.04 + LVM)
日期:2026-11-06
机器:taoserver(192.168.179.128,VMware NAT,Ubuntu 22.04 x86_64)
场景:Docker 构建/运行导致根分区 94% 满,需要在线扩容
一、任务背景
taoserver 上跑着 Docker(mysql8、portainer、jenkins),/var/lib/docker 与系统同盘。
根分区只剩 614MB(94% 已用),后续要构建 PHP 应用镜像(需 2~3GB 临时空间),必须扩容。
扩容目标:40G 硬盘 → 根分区用满,可用空间 ≥ 28G。
二、原理:为什么"扩了硬盘磁盘却没变大"
VMware 虚拟机的磁盘是一条三层结构,扩容必须逐层打通,缺一层都白做:
第 1 层 VMware 虚拟硬盘 (在 VMware 设置里扩,或开机状态下在线扩)
↓
第 2 层 分区 sda3 (要在系统里扩分区)
↓
第 3 层 LVM 逻辑卷 + 文件系统 (要 pvresize → lvextend → resize2fs)
本机初始状态(典型的「只做了第 1 层」):
| 层 | 初始 | 扩容后 |
|---|---|---|
| sda 硬盘 | 40G | 40G(不变) |
| sda3 分区 | 18.2G | 38.2G |
| PV / VG 空闲 | 18.2G / 8.22G 空闲 | 38.2G / 0 |
| LV(ubuntu-lv) | 10G | 38.2G |
/ 文件系统 | 9.8G(94% 用) | 38G(25% 用,剩 28G) |
LVM 的价值就体现在这里:分区/LV 可以在线扩大,不用重启、不用停业务。
(反过来缩小则危险得多,LVM 不支持在线缩 ext4。)
三、扩容前体检命令(判断卡在哪一层)
lsblk # 看磁盘→分区→LV 的层级和大小
df -h / # 看文件系统实际大小
pvs / vgs / lvs # 看 LVM 三层:物理卷/卷组/逻辑卷
fdisk -l /dev/sda # 看硬盘总量
判断口诀:
lsblk里 sda 是 40G、sda3 还是小 → 分区没扩(本次情况)- sda3 扩了但
vgs有 VFree → LV 没扩 lvs扩了但df -h没变 → 文件系统没扩(漏了 resize2fs)
四、实施步骤(全程在线,不停机不停容器)
第 1 步:VMware 层扩硬盘
虚拟机设置 → 硬盘 → 扩展(或 vmware-vdiskmanager)。开机状态也支持在线扩。
本次用户已在 VMware 里扩到 40G。
第 2 步:扩分区(sda3 是最后一个分区才安全)
parted -s /dev/sda resizepart 3 100%
-s非交互模式;100%表示分区吃到磁盘末尾;- 前提:sda3 必须是该磁盘最后一个分区(本机 sda1/sda2 在前,满足);
- 实际输出:
PART_OK(无报错即成功)。
若系统没有 parted,可用
growpart /dev/sda 3(cloud-guest-utils 包,云镜像自带)。
第 3 步:刷新物理卷
pvresize /dev/sda3
实际输出:
Physical volume "/dev/sda3" changed
1 physical volume(s) resized or updated / 0 physical volume(s) not resized
第 4 步:扩展逻辑卷(吃掉 VG 全部空闲)
lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
实际输出:
Size of logical volume ubuntu-vg/ubuntu-lv changed from 10.00 GiB (2560 extents) to 38.22 GiB (9785 extents).
Logical volume ubuntu-vg/ubuntu-lv successfully resized.
常用写法:
lvextend -L +20G ...(加 20G)或-l +100%FREE(加全部空闲,本次用)。
第 5 步:在线扩展文件系统(ext4)
resize2fs /dev/ubuntu-vg/ubuntu-lv
实际输出:
Filesystem at /dev/ubuntu-vg/ubuntu-lv is mounted on /; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 5
The filesystem on /dev/ubuntu-vg/ubuntu-lv is now 10019840 (4k) blocks long.
on-line resizing required= 在线扩展,挂载状态下直接生效,无需重启。
五、验证
df -h /
lsblk /dev/sda
vgs
最终结果:
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv 38G 8.7G 28G 25% /
sda 40G
└─sda3 38.2G
└─ubuntu--vg-ubuntu--lv 38.2G
VG VSize VFree
ubuntu-vg 38.22g 0
业务验证:mysql8 / portainer 容器全程未受影响(docker ps 状态不变)。
六、命令速查表
| 命令 | 作用 | 关键点 |
|---|---|---|
lsblk | 树状看块设备层级 | 判断卡在哪一层的第一工具 |
parted -s /dev/sda resizepart N 100% | 扩分区到磁盘末尾 | 仅限最后一个分区;-s 免交互 |
growpart /dev/sda N | 同上(cloud 工具) | 云镜像常用 |
pvresize /dev/sda3 | PV 认领分区新空间 | 必须在 lvextend 之前 |
lvextend -l +100%FREE /dev/vg/lv | LV 吃掉 VG 全部空闲 | -L +20G 按容量加 |
resize2fs /dev/vg/lv | 在线扩 ext4 文件系统 | 挂载状态可执行;最后一步,漏了 df 不变 |
xfs_growfs / | 若是 xfs 用这条(不是 resize2fs) | Ubuntu 默认 ext4,RHEL/CentOS 默认 xfs |
vgs / pvs / lvs | LVM 三层状态 | VFree=0 说明 VG 空间用尽 |
七、踩坑与注意
- 只扩 VMware 硬盘不够——三层结构,少扩一层 df 都不会变。最常见就是只做第 1 层。
parted resizepart只能扩最后一个分区——如果 sda3 后面还有分区,方案完全不同(需删分区重建或加新盘)。- 文件系统类型决定最后一步命令——
df -T /看类型:ext4 用resize2fs,xfs 用xfs_growfs /(参数是挂载点不是设备名)。 - LVM 缩容不支持在线——扩容随意,缩容要卸载+离线,规划时尽量一步到位。
- 引导分区 sda2(/boot)不在 LVM 里——扩根分区不影响 /boot,别动 sda2。
- 操作前 mysql 等容器无需停止——全部操作在线,但属于磁盘级变更,仍建议避开业务高峰。
八、SOP 模板(下次直接照抄)
# 前提:VMware 层已扩容,目标分区是磁盘最后一个分区
lsblk && df -T / # 体检:确认层级与文件系统类型
parted -s /dev/sda resizepart <N> 100% # 1. 扩分区
pvresize /dev/sda<N> # 2. 刷 PV
lvextend -l +100%FREE /dev/<vg>/<lv> # 3. 扩 LV
resize2fs /dev/<vg>/<lv> # 4. 扩文件系统(ext4)
df -h / # 5. 验证
九、FAQ
Q1:扩容后 df -h 没变化?
九成是漏了第 5 步 resize2fs(LV 扩了文件系统没扩)。lvs 看大小对不对,再看 df -T 确认文件系统类型。
Q2:VMware 里"扩展"按钮是灰的?
说明虚拟机有快照。先删掉所有快照再扩(快照链会锁定磁盘)。
Q3:不想动系统盘,能不能加一块新盘给 Docker?
可以,而且更干净:加盘 → 整盘做 PV → 建 VG/LV → 格式化挂到 /data → 改 Docker 的 data-root 指过去。适合后续还要持续膨胀的场景。
Q4:resize2fs 中途断了会不会坏数据?
不会。在线 resize 是原子的元数据操作,中断则自动回退到原大小,不会损坏已写入数据。
本次扩容:10G → 38.2G,在线完成,全程约 1 分钟,业务无感知。