LVM 基础:云盘只给 40G,根分区在线扩容怎么做
「40G 不够用了,不想重装系统,能在线把根分区变大吗?」——用 LVM,能,而且不用重启、不用卸载文件系统。反过来,想缩小时基本得停机。方向不对称这件事,决定了你该怎么规划磁盘。
多数云服务器镜像已经默认装了 LVM,很多人却从没碰过它,只在「磁盘满了」那天第一次听说 lvextend。这篇把三层结构讲清楚,再给一条从云盘扩容到根分区变大的完整命令链。
先搞懂三层结构:PV、VG、LV
LVM 在物理磁盘和文件系统之间加了一层抽象,三个概念层层堆叠:
| 层 | 名称 | 类比 | 管理命令族 |
|---|---|---|---|
| 底层 | PV(物理卷) | 一块盘或一个分区 | pvcreate / pvs / pvdisplay |
| 中层 | VG(卷组) | 一个存储池 | vgcreate / vgs / vgextend |
| 顶层 | LV(逻辑卷) | 可以格式化的「虚拟分区」 | lvcreate / lvs / lvresize |
VG 内部的最小分配单位是物理扩展块(PE,Physical Extent),默认 4 MiB。LV 由一串 PE 组成,PE 可以来自 VG 里的任意一块 PV。
这一层抽象带来三个分区表给不了的能力:
- 在线扩容。LV 变大不依赖它在磁盘上的物理位置,也不用管旁边有没有别的分区挡路。ext4、XFS 都支持挂载状态下扩文件系统。
- 跨盘合并。两块 20G 的盘可以合成一个 40G 的 VG,再按需切分。
- 快照。对 LV 做写时复制快照,几秒生成一个冻结视图,备份或升级前回滚都用得上。
代价也要心里有数:装了 LVM 多一层软件,排障时多一层要查;双系统场景下 Windows 读不了 LVM 卷;跨盘合并是把双刃剑——两块没有冗余的盘并成一个 VG,任何一块坏掉,整个 VG 里所有 LV 都可能报废,包括那块好盘上的数据。个人服务器盘位不多,跨盘合并要慎重。
三步搭一个最小可用卷组
新盘从裸设备到可挂载,三步:pvcreate → vgcreate → lvcreate。
sudo apt install lvm2
# 1. 把整块盘初始化为物理卷
sudo pvcreate /dev/sdb
# 2. 用它创建卷组 vgdata
sudo vgcreate vgdata /dev/sdb
# 3. 从卷组里切一个 10G 的逻辑卷
sudo lvcreate -L 10G vgdata -n lvapp
格式化并挂载:
sudo mkfs.ext4 /dev/vgdata/lvapp
sudo mkdir -p /srv/app
echo '/dev/vgdata/lvapp /srv/app ext4 defaults 0 2' | sudo tee -a /etc/fstab
sudo mount -a
设备路径建议统一写 /dev/vgdata/lvapp(或 /dev/mapper/vgdata-lvapp,两者等价),fstab 里也这么写。
验证:
lsblk # 能看到 vgdata-lvapp 挂在 /srv/app
-L 10G 指定绝对大小;想一次吃掉卷组全部剩余空间,用 -l 100%FREE(小写 -l 接百分比,大写 -L 接绝对容量,两者别混)。
在线扩根分区:完整命令链
现在回到开头的问题。假设云服务商控制台里已把系统盘从 40G 扩到 80G(这一步在各家面板操作,块设备大小变了,分区和文件系统不会自动跟着变),接下来在机器上分三段处理。
第 1 段:把分区扩大到整个磁盘。 Ubuntu 24.04 自带 cloud-guest-utils,growpart 对 GPT 分区在线生效:
sudo apt install cloud-guest-utils
sudo growpart /dev/vda 1 # 把 /dev/vda 的第 1 个分区扩到盘尾
第 2 段:把新空间灌进 PV 和 VG。
sudo pvresize /dev/vda1 # PV 自动撑满底层设备
vgs # VFree 一栏应多出约 40G
pvresize 支持在线操作,不用卸载任何东西。VG 拿到空闲容量后,剩下的就是把空间分给哪个 LV。
第 3 段:扩 LV,同时扩文件系统。
sudo lvresize -l +100%FREE -r /dev/ubuntu-vg/ubuntu-lv
-r(--resizefs)会让 LVM 先扩 LV、再调文件系统工具扩 ext4/XFS,一步到位。分两步手敲(先 lvextend 后 resize2fs)也行,但 -r 少一次手滑机会——忘了扩文件系统是 LVM 扩容最常见的翻车点:df -h 看到的容量纹丝不动,新人往往以为扩容失败,其实只是文件系统没跟上。
验证:
df -h / # Size 应接近 80G
只扩固定大小的话用 -L +20G;-l +100%FREE 是「把剩余全给它」。根分区建议留一点余量别吃满:ext4 的在线检查工具 e2scrub 需要 VG 里有空闲 PE 才能跑,通常留 256 MiB 以上。
缩小是逆操作,而且危险得多
扩容在线、随意;收缩要停机、有数据风险。XFS 只能扩不能缩;ext4 能缩,但必须先卸载(根分区得进 rescue 环境),且顺序固定:先缩文件系统,再缩 LV,反过来直接丢数据。
lvresize -r 对缩小同样有效,它会自动先调 resize2fs 缩文件系统、再缩 LV。但即便有 -r 保护,操作前也务必确认文件系统实际用量远小于目标值,并留好备份。
快照:升级前的后悔药
快照是 CoW(写时复制):创建瞬间只记录指针,几乎零耗时;之后原始数据块被改写时,旧块先拷进快照空间。所以快照卷只需要容纳「快照创建后被改写的数据量」,给 2G 空间就能保护一个 40G 卷的低写入场景。
# 给根 LV 拍快照,预留 2G 写入空间
sudo lvcreate --size 2G --snapshot --name root_snap /dev/ubuntu-vg/ubuntu-lv
# 出问题,回滚到快照时刻(原 LV 活跃时合并会推迟到下次重启)
sudo lvconvert --merge /dev/ubuntu-vg/root_snap
两条使用注意:
- 快照不是备份。它和原始数据在同一块盘上,盘坏了或扇区损坏,快照跟着一起没。它的定位是「升级/改配置前的瞬时回滚点」,异地备份还得靠 rsync 或对象存储那套流程。
- 快照空间写满后快照失效,保护窗口结束。拍摄前评估改动了多大,别给 100M 空间去保护一次系统大版本升级。
常见问题
Q:vgdisplay 看到有 Free PE,lvextend 还是报 insufficient space?
A:多半是 LV 创建时带了连续分配策略(-C y)。连续分配要求新 PE 物理相邻,VG 有零散空闲也用不上。先 lvchange --alloc inherit <vg>/<lv> 放开策略再扩。
Q:lvextend 成功了,df -h 容量没变?
A:文件系统没扩。LV 和文件系统是两层,lvextend 只动了上层块设备。补一句 sudo resize2fs /dev/<vg>/<lv>(XFS 用 sudo xfs_growfs /挂载点),或者下次直接用带 -r 的 lvresize。
Q:能直接把一块新盘加进现有卷组吗?
A:能。pvcreate /dev/sdc 后 vgextend <vg> /dev/sdc,VG 容量立刻变大。但记住前面说的冗余问题:无冗余盘并入生产 VG,一块坏全组遭殃。给临时数据或明确接受风险时再用。
Q:怎么删掉一个不要的逻辑卷?
A:先 umount 挂载点,再 lvremove <vg>/<lv> 确认 y。记得同步清掉 fstab 里对应行,否则下次开机 fsck 卡住。
Q:Ubuntu 24.04 装机时没选 LVM,还能补救吗? A:能,思路是把数据迁过去:新盘建 VG 和 LV,rsync 全量数据过去,fstab 切到新 LV 路径,重启验证后再释放旧分区。纯根分区原地转换风险高,不值得。