老实说,给VMware里的Ubuntu扩容这件事,我见过太多人卡在同一步了:虚拟磁盘大小已经在界面里加到了100G,系统也重启过,结果打开终端一敲 df -h,根分区容量纹丝不动,甚至 lsblk 里能看到一块几十G的未分配空间,却不知道拿它怎么办。这个场景通常只适用LVM分区的Ubuntu——如果你当初安装时选了常规分区、传统分区表方案,那要走的路完全是另一套。如果你手里正好是一台LVM分区的虚拟机,那这篇文章就把整条链路从VMware界面一路拆到文件系统层,每一步命令、每个输出、每个坑,都按我实际环境里验证过的顺序写给你。
1. VMware和LVM的扩容逻辑:为什么非得“两层一起动”
1.1 虚拟磁盘变大,不等于文件系统变大
先说一个最容易被忽略的认知偏差:VMware里的磁盘扩展,本质只是把虚拟机的“虚拟磁盘文件”改大了,系统层面的分区、卷组、逻辑卷、文件系统,全都不会跟着自动变。就像你在仓库外墙上开了一道新侧门,仓库内部的隔断墙没拆,货物依然放不进新区域。
虚拟机的存储,自上而下实际上是四层:物理磁盘文件(VMDK)→ 磁盘内的分区表 → LVM的物理卷/卷组/逻辑卷 → 文件系统。VMware界面操作的是最外层,而df -h看的是最内层。所以只要有一层没跟上,扩容结果在系统里就是“看得见、用不着”。
很多教程只教你“扩展磁盘 → 重启 → 完成”,这是典型的治标不治本。完整链路应该是:先让VMware把虚拟磁盘变大,然后让Ubuntu识别到新磁盘容量,再把LVM各层逐级扩展,最后扩展文件系统本身。每一层都要执行一次“吸收新空间”的动作。
1.2 为什么标题限定“LVM分区”
LVM(逻辑卷管理)是一种存储抽象层,它把物理分区封装成物理卷(PV),再把多个PV汇入一个卷组(VG),最后从卷组里划出逻辑卷(LV)挂载给系统用。这里面的核心思想就是“池化”——空间不是被某个分区死死绑定,而是放在一个大池子里按需分配。
对比一下传统分区表:MBR方案里主分区只有4个,扩展分区的空间只能在磁盘末尾,想把根分区变大就得处理起始扇区、分区编号这些硬约束,风险高且操作繁琐。GPT方案稍微好一点,但也必须动用分区调整工具去改分区边界。而LVM的设计初衷就是应对“容量不够了随时扩”的场景,新增的空间既可以并入原有PV,也可以作为新PV加入VG,动态性完全不同。
所以这篇文章标题里的“只适用LVM分区”不是随便写的——如果你用lsblk看到根分区类型是lvm,下面的操作就能复用;如果看到的是普通分区如/dev/sda2直接挂载到/,那你要做的不是本篇内容,而是去研究分区表扩展那一套流程,思路完全不同。
1.3 完整扩容链路预览
先给你一张“地图”,后面每一步都是按这个顺序来:
- VMware图形界面扩展虚拟磁盘大小
- 系统内确认新磁盘容量已被识别
- 扩展承载LVM的分区(分区表层面)
pvresize扩展物理卷- 确认卷组VG的可用空间
lvextend扩展逻辑卷resize2fs或xfs_growfs扩展文件系统- 用
df -h和lsblk验证结果
顺序不允许乱。尤其最后两步,必须先扩逻辑卷,再扩文件系统。反过来操作不仅会报错,还有可能把文件系统元数据处理成异常状态,切记。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手前先摸底:确认分区布局、快照与目标容量
2.1 用lsblk和pvs确认分区布局
在碰VMware界面之前,先在Ubuntu里运行下面这组命令,把现状摸清楚:
bash复制lsblk
df -hT
sudo pvs
sudo vgs
sudo lvs
拿我手头这台模拟环境来说,lsblk输出大致长这样:
code复制NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 60G 0 disk
├─sda1 8:1 0 512M 0 part /boot/efi
└─sda2 8:2 0 59.5G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 39.5G 0 lvm /
只要看到TYPE列出现lvm,就说明你的Ubuntu确实是LVM布局,可以继续往下走。这里面有几个关键信息要记下来:PV对应的分区(这里是/dev/sda2),VG名(这里是ubuntu-vg),根逻辑卷的设备路径(/dev/ubuntu-vg/ubuntu-lv或/dev/mapper/ubuntu--vg-ubuntu--lv注意双横线)。
不同版本的Ubuntu默认VG名可能不同,有ubuntu-vg、vg00、myvg等等。不要凭经验猜名字,直接以vgs输出为准。
2.2 确认根和swap的归属
继续用df -hT看挂载点:
bash复制df -hT
如果/的TYPE列显示ext4,后面文件系统扩展就用resize2fs;如果显示xfs,就用xfs_growfs。这两种工具不能混用,混用的报错信息也不太友好,先确认类型能省掉后面一堆麻烦。
另外看下swap逻辑卷:LVM默认安装的Ubuntu通常会给/swap.img或swap_1单独划分一个逻辑卷。扩容根分区时一般不需要动swap,除非你计划同时调大swap空间。记住swap是独立的LV,别在扩容根分区时误操作到它。
2.3 快照与回滚:不要裸奔操作
扩容虽然不算高风险操作,但虚拟化环境里“快照”就是你的后悔药,尤其当这台虚拟机里有业务数据时,我强烈建议在开始前打一个快照。
VMware Workstation里可以直接通过“虚拟机 → 快照 → 拍摄快照”完成。需要注意:如果虚拟机当前已经有其他快照,部分版本的VMware会不允许扩展磁盘,图形界面的“扩展”按钮呈灰色。这时候需要先删除旧快照、或者把快照整体提交掉,再执行扩容。这个细节我在不少环境里踩过,提前知道能少折腾不少时间。
打快照的时机建议选在虚拟机待机状态下,I/O负载最低的时候。生产环境如果用的是vSphere那类集中管理平台,扩容前的快照策略更严格,但本篇文章讲的是单机VMware使用场景,虚拟机快照足够应付了。
2.4 估算目标容量
扩容前先算清楚要加多少空间,别拍脑袋直接拉满。一般都会根据当前使用率来算:
bash复制df -h /
比如当前根分区是39.5G,已用约30G,可用空间已经明显吃紧,你想让根分区拥有80G左右的空间,那就应该在VMware里把虚拟磁盘总容量从60G调到整块盘至少100G,给根LV腾出足够的可扩展空间。
这里有个容易混淆的点:VMware界面里输入的是“磁盘总容量”,不是“新增多少G”。比如原盘60G、想加40G,界面里应该填100,而不是填40。填错了、填少了,后面所有步骤都会跟着走样。我在初始规划阶段习惯算好“现有LV总大小 + 我要预留的富裕空间”,再反推出虚拟磁盘最终容量。
3. 第一层动作:在VMware里扩虚拟磁盘
3.1 图形界面扩展与注意事项
在VMware Workstation中,选中虚拟机 → 编辑虚拟机设置 → 硬盘 → 右侧的“磁盘信息”工具里找到“扩展”按钮,输入新的总容量,点击扩展。等待虚拟机磁盘文件在宿主机上完成调整。
整个过程很快,但有两个提醒:
- 输入的是“最终总容量”,不是增量。原盘60G,想加40G,填100G,不是填40G。
- 如果磁盘是thin provisioning(精简置备)模式,扩容后宿主机上实际的磁盘占用并不会立刻增加,只有虚拟机内真正写入新数据时才会逐步占用宿主机空间。但还是要提前检查宿主机剩余磁盘空间,别等到虚拟机里拷贝大文件时才发现在宿主层也没空间了。
3.2 热扩展还是关机扩展
VMware里磁盘扩展能否在线进行,取决于虚拟磁盘挂载的总线类型。SCSI(含SAS、PVSCSI)总线的磁盘在多数较新版本里可以支持在线扩展;而IDE总线通常必须在虚拟机关机状态下才能调整。
如果你拿不准,稳妥起见就是关机再扩展。关机扩展不会有任何识别问题,开机后系统直接能看到新容量。部分同学会问“我开机状态扩展了,但系统里怎么看都是旧容量”,这其实很常见,不一定是没扩展成功,只是系统没扫描到新总线信息,下一节会讲怎么处理。
如果想确认自己用的是哪种控制器,在VMware的设置界面里点开硬盘,看“虚拟设备节点”旁标注的总线类型即可。Ubuntu里也可以用lsblk -d -o NAME,TRAN看传输类型,如果显示sata或scsi就是SCSI体系,如果是sata且挂在IDE控制器下则要谨慎。
3.3 让Ubuntu“看到”新磁盘容量
在线扩展完成后,一般不需要重启也能让系统识别到新容量,但需要给SCSI设备发一次重新扫描命令。比较通用的做法是:
bash复制for host in /sys/class/scsi_host/host*/scan; do
echo "- - -" | sudo tee "$host"
done
这条命令会遍历所有SCSI Host并触发重新扫描。执行完再用lsblk确认:
bash复制lsblk
如果sda的总容量已经变成100G,说明系统层已经识别到新磁盘。如果仍然是60G,先看一眼VMware侧是否真的扩展成功,然后检查是不是IDE总线的情况。确认完再回来继续。
关机扩展的情况更简单,开机后系统一般直接识别到新容量,lsblk里就能看到磁盘大小已经更新。
3.4 别急着往下走:确认新空间的呈现方式
识别到新容量后,用这条命令查看分区层级:
bash复制sudo parted /dev/sda print free
在输出末尾通常能看到一段Free Space区域,大小就是本次新增的容量。记住此刻磁盘末尾的“未分配空间”已经存在,但现有分区/dev/sda2的边界并没有自动延伸到那里。这一步确认好,下一步才是真正动手改分区表。
4. 核心链路:扩展分区、PV、VG、LV到文件系统
4.1 先把承载LVM的分区边界扩到磁盘末尾
很多人以为LVM扩容不需要动分区表,这个说法其实有个前提:如果你打算新增一个分区作为新PV,那确实可以完全不动原分区表;但如果是想把现有PV所在的/dev/sda2这块空间变大,就必须先把分区表里的分区终点往后扩。
比较友好的做法是用growpart,如果系统里没有这个命令,先安装:
bash复制sudo apt update
sudo apt install -y cloud-guest-utils
然后扩展分区编号为2的分区:
bash复制sudo growpart /dev/sda 2
这条命令会把/dev/sda2的结束位置调整到磁盘末尾,输出类似CHANGED: disk=/dev/sda original=...。如果没有growpart,也可以用parted完成同样的事:
bash复制sudo parted /dev/sda resizepart 2 100%
sudo partprobe /dev/sda
两种方式二选一即可。操作完成后,用lsblk查看,/dev/sda2的容量应该已经从59.5G变成了约99.5G。这一步做完,分区表的“外壳”才真正贴到了新容量的边界上。
还有一个更保守的思路:不动现有分区表,在磁盘末尾新建一个分区作为新PV并入VG。操作方式是用fdisk或parted新建一个Linux LVM类型分区,再pvcreate + vgextend合并进现有VG。这种方案的好处是完全不触碰原分区,坏处是多一个PV要管理,后面做物理卷相关操作时要多留一个心眼。我个人在简单环境里更倾向于growpart直扩,清晰简单。
4.2 pvresize:让物理卷认领新增分区
分区表扩展完后,物理卷的容量不会自动更新,需要主动执行:
bash复制sudo pvresize /dev/sda2
接着用pvs验证物理卷大小:
bash复制sudo pvs
如果一切正常,PV的PSize应该已经扩容到接近99G,PFree列会出现明显的新增空间。
这里要强调一下pvresize和pvcreate的区别:pvresize是让已有PV重新读取物理分区的新尺寸,不需要新建;pvcreate是初始化一个新的物理卷。实操中有人会在这一步误操作成pvcreate,导致原来的VG信息丢失,虽然可以重建,但没必要冒这个风险。看到PV已经是LVM状态,直接用pvresize就行。
4.3 用vgs确认卷组可用空间
物理卷扩大后,需要确认它所在卷组是否同步更新:
bash复制sudo vgs
输出里的VFree列就是卷组里尚未分配给任何逻辑卷的可用空间。以我的示例环境来说,扩容前VFree是0,扩容后应该变成40G左右。如果VFree仍然为0,说明上一步pvresize没有生效,先回头查分区表状态。
卷组这一层通常不需要额外操作,只要PV扩大,VG可用的总空间会自动跟着变。VG的本质就是PV的集合,PV变大,池子自然就大了。
4.4 lvextend:扩展逻辑卷
到这一步,才轮到你真正分配空间给根逻辑卷。两种写法:
bash复制# 方式一:按增量加,比如增加40G
sudo lvextend -L +40G /dev/ubuntu-vg/ubuntu-lv
# 方式二:把VG剩余空间全部给当前LV
sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
我非常推荐用带+号的写法,因为-L不带+号表示“目标大小”,带了+号才是“增加多少”。初学的人最容易在这里翻车,比如你原本想加40G,却写成了-L 40G,结果逻辑卷被直接缩到40G,轻则空间变小,重则引起文件系统不一致,相当危险。如果你想要更保险的分配策略,就用-l +100%FREE,把所有剩余空间都塞给当前LV,省心且不会写错。
执行后出现类似于“Size of logical volume ... changed from 39.5G to 79.5G”的输出,就说明逻辑卷层扩容成功。此时完成LVM层面的一半工作。
4.5 resize2fs或xfs_growfs:最后一步扩文件系统
逻辑卷扩容完成后,文件系统仍保持旧尺寸,这时使用df -h看容量不会有任何变化,会让人误以为没成功。接下来要针对文件系统类型执行对应工具。
对于ext4:
bash复制sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
resize2fs支持在线扩容,不需要卸载根分区,执行过程中会输出类似“Resizing the filesystem on /dev/mapper/ubuntu--vg-ubuntu--lv to 20833280 blocks”等信息。整个过程通常几十秒内完成。
对于xfs:
bash复制sudo xfs_growfs /
注意xfs_growfs的参数一般是挂载点,也可以传设备路径,但传挂载点更直观。xfs不支持缩容,只支持扩,好在扩充操作也是在线完成的。
这里还有个容易踩坑的点:怎么知道自己是什么文件系统?前面第一步就让看了df -hT的输出,/那行TYPE列如果是ext4就用resize2fs,如果是xfs就用xfs_growfs,千万不要混。曾经见过有人对xfs根分区执行resize2fs,系统直接报错找不到有效的ext4超级块,其实不是工具坏了,而是选错了工具。
4.6 验证四连:df、lsblk、vgs、lvs
全部执行完,验证环节必须做全,不要只看一个命令就下结论:
bash复制df -h /
lsblk
sudo vgs
sudo lvs
df看的是文件系统最终可用容量,lsblk看清楚磁盘→分区→LVM的层级关系,vgs看卷组剩余空间是否归零,lvs看逻辑卷实际大小。四个命令的输出相互印证,才算是真正把这次扩容闭环了。如果此时df -h已经显示新容量,就说明整条链路已经打通。
5. 扩容现场最容易翻车的几个“坑”与排查链路
5.1 现象一:pvresize之后pvs还是旧大小
用pvs看到PV的PSize没有变化,第一反应别急着重跑pvresize,而是先回查分区表:
bash复制sudo parted /dev/sda print free
如果/dev/sda2的结束位置仍然停留在旧边界,说明分区表根本还没扩,pvresize当然无米下炊。此时需要先执行第4.1节里的growpart /dev/sda 2或parted resizepart 2 100%,再回来跑pvresize。
这个坑的根因,往往是对LVM的“分区表无关”产生误解。LVM的灵活性是体现在“可以跨PV、可以动态分配”,但如果PV本身基于一个固定大小的分区,那分区表限制了PV读到的物理边界,它同样突破不了。
5.2 现象二:vgs明明有Free,lvextend却报no space
这种情况分两种典型原因。一种是你新增了PV但忘了vgextend把它并入VG,所以VG扩容量的动作根本没完成,Free归Free,LV拿不到。排查方法:
bash复制sudo pvs
sudo vgs
对比一下pvs里这个PV所属的VG是否与目标VG一致,以及是否所有PV都已经出现在VGS的#PV计数里。
另一种原因是操作对象错误,比如你想扩根LV,却不小心把命令写到了swap LV上,或写到了一个不存在的LV路径上。执行之前先sudo lvs看清楚所有逻辑卷名称,再对照要扩展的那个。
5.3 现象三:lvextend成功,df -h却纹丝不动
这个现象最常见,也是最容易让人误判的。如果你已经执行了lvextend,且sudo lvs里LV大小已经变化,但df -h还是旧值,说明文件系统本身还没扩。
之前有朋友在群里说“lvextend成功了,df没变,是不是哪里搞坏了”,我问了一句:“你执行resize2fs了吗?”对面沉默了一会儿。麻烦就麻烦在很多人会把lvextend和resize2fs当成同一个操作,其实LVM只负责把“卷”变大,文件系统是独立一层,必须专门扩展。这时候针对ext4执行sudo resize2fs /dev/mapper/xxx,执行完再看df -h,一般立刻生效。如果执行完仍然没变化,把输出贴出来检查是否有报错。
5.4 现象四:找不到lvextend、resize2fs命令
有些精简版Ubuntu或最小化安装环境,LVM2工具集可能没有完整安装,或者它们的二进制目录不在当前PATH里。如果提示command not found,先用全路径尝试:
bash复制/usr/sbin/lvextend
/usr/sbin/resize2fs
或者重新安装工具包:
bash复制sudo apt install -y lvm2
lvextend在/usr/sbin下是很常见的路径,普通用户执行时如果没有将sbin加入PATH就会出现“命令找不到”的错觉。这种情况多见于sudo环境或脚本环境里。
5.5 现象五:扩容后重启,系统进了initramfs
这是我遇到过最惊险的一种:所有扩容步骤看起来都没问题,但重启后Ubuntu停在initramfs/busybox界面,系统找不到根分区。
先别慌,逐项排查以下三种可能:
- 扩容过程中某个步骤顺序乱了,比如在文件系统已经占满的情况下继续写入;或者你直接用了
-L不带+号的写法把文件系统缩小了,造成元数据异常。 /etc/fstab里记录的根分区UUID或设备路径有问题,但一般LVM扩容不会改变UUID,所以这个可能性低。- 磁盘分区表或LVM元数据有部分损坏。在initramfs提示符下,可以尝试手动激活卷组:
bash复制lvm vgchange -ay
exit
如果能够进入系统,先备份数据,再检查卷组状态。如果没有快照可以回退,这种情况会非常被动。所以再一次强调,动手之前先打快照,这个习惯真的能救命。
5.6 现象六:在线扩展后lsblk看不到新磁盘
在线扩容后系统迟迟没识别到新容量,先确认VMware侧扩展是否真的完成,然后在Ubuntu里刷新SCSI设备扫描:
bash复制for host in /sys/class/scsi_host/host*/scan; do echo "- - -" | sudo tee "$host"; done
sync
如果还是不行,检查一下虚拟磁盘是否挂在IDE控制器上。IDE设备通常不支持热识别,只能关机再开机。这里有一个很小的细节:在线扩容操作完成后VMware界面可能显示成功,但系统侧SCSI缓存并未刷新,多执行几次扫描命令,或者干脆重启一次,比在那反复排查驱动要省时间得多。
5.7 给你的补充:为什么不要用fdisk直接删分区重建
网上有教程教你“直接fdisk删掉旧分区、再新建同样起点的分区”,这种方法对LVM来说虽然理论上可行,但风险极高。分区起点稍微偏移一点,整个PV元数据就会找不着,后续恢复相当痛苦。用growpart或parted resizepart这类专门工具,能在保持分区起点不变的前提下把终点往后扩,才是安全路径。
6. 收尾:我的扩容习惯和一个容易被忽略的动作
6.1 扩容前固定三件事
现在每次给LVM扩容前,我都固定做三件事:先打快照;然后跑一遍lsblk、df -hT、vgs、lvs把现状截图存档;最后确认宿主机磁盘剩余空间够用。这三件事做完,再动VMware界面。每次都花不了几分钟,但能在后续排错时省掉大把时间。
6.2 二次扩展同一个逻辑卷时的操作要点
如果你以后还要继续给这台Ubuntu扩容,比如从100G加到150G,新的链路是一样的:VMware扩展磁盘 → 系统识别 → growpart /dev/sda 2 → pvresize /dev/sda2 → lvextend -L +50G /dev/ubuntu-vg/ubuntu-lv → resize2fs。整套流程完全可以重复执行,这也是LVM方案比普通分区舒服的地方。
唯一要注意的是,第二次扩容时growpart和pvresize可能显示“nothing to do”之类提示,不要觉得奇怪,那是因为上次扩容已经把分区表或PV边界扩到当时磁盘末尾了,现在磁盘又变了,再扩一次就能吸收新空间。
6.3 记录扩容信息
最后,我习惯把每次扩容后的关键输出保存下来,包括lsblk、vgs、lvs和df -h的结果。尤其当虚拟机排错需要回看“上次扩容是什么时候、当前PV边界在哪”时,一份朴素的文字记录比翻聊天记录和截图要高效得多。如果这台机器后续要迁移或者复制克隆,这些信息也会让你对底层状况更有数。
VMware加LVM的组合,本质就是把“虚拟层”的弹性存储和“系统层”的动态卷管理叠加在一起。只要把链路顺序记牢:磁盘 → 分区 → PV → VG → LV → 文件系统,一层一层往下扩展,就再也不会出现“扩容完却依然没空间”的尴尬了。
