Linux服务器如何配置LVM逻辑卷?磁盘扩容与文件系统调整教程

服务器磁盘满了,这是运维最常遇到的问题之一。如果当初分区时用的是传统分区,扩容会非常麻烦:得停机、改分区表、还有数据丢失风险,很多时候只能加块新盘然后想办法把数据迁过去。但如果当初用的是 LVM(逻辑卷管理),扩容就是几条在线命令的事,业务不中断,几秒钟搞定。

LVM 之所以被几乎所有企业发行版默认采用,就是因为它把"物理磁盘"和"文件系统"之间加了一层抽象,让容量可以灵活组合、在线扩展、做快照。这篇文章讲清楚 LVM 的三个核心概念 PV/VG/LV 的关系,手把手演示创建、在线扩容、缩容(有风险)、快照,以及 pvmove 迁移数据,还会说明云盘和 LVM 怎么配合,以及那些必须注意的坑。看完你应该能独立管理一台用 LVM 的服务器,扩容不再求人。

LVM 是什么:PV、VG、LV 三层结构

传统分区是"一块磁盘切几刀,每刀固定大小",改不了。LVM 在磁盘和文件系统之间加了三个抽象层:

概念 全称 作用
PV Physical Volume(物理卷) 一块磁盘或分区,被 LVM 接管,作为"砖块"
VG Volume Group(卷组) 一个"砖块池",由一个或多个 PV 组成,统一分配容量
LV Logical Volume(逻辑卷) 从 VG 里切出来的"逻辑分区",上面建文件系统

打个比方:PV 是一块块硬盘,VG 是把这些硬盘拼成的一个大存储池,LV 是从池子里舀出来的一份,格式化后挂载使用。好处是:LV 的大小可以随时从 VG 的空闲空间里"再舀一点"扩容,只要 VG 里还有空余容量;VG 容量不够了,再加一块 PV 进去。

这三层的命名也体现在设备路径上,LV 的设备文件在 /dev// 或 /dev/mapper/-:

# 查看三层结构
sudo pvs        # 物理卷
sudo vgs        # 卷组
sudo lvs        # 逻辑卷

# 更详细的展示
sudo pvdisplay
sudo vgdisplay
sudo lvdisplay

# 用 lsblk 也能直观看到 LVM 结构
lsblk

lsblk 输出里,LVM2_member 类型的就是 PV,它下面缩进的是 LV:

sda
├─sda1            /boot
└─sda2            LVM2_member
  ├─vg0-root     /
  └─vg0-swap     [SWAP]

创建 LVM:从零开始

假设有两块新磁盘 /dev/sdb 和 /dev/sdc,要把它们做成 LVM 并建一个逻辑卷。

风险提示:下面所有涉及磁盘的操作都会清空目标磁盘上的数据。执行前务必用 lsblk 确认设备名,别把系统盘当成数据盘操作。

# 0. 确认磁盘(务必核对!)
lsblk
sudo fdisk -l /dev/sdb /dev/sdc

# 1. 创建物理卷 PV(直接对整块盘操作,也可以先分区再做 PV)
sudo pvcreate /dev/sdb /dev/sdc

# 2. 创建卷组 VG,比如叫 vg_data
sudo vgcreate vg_data /dev/sdb /dev/sdc

# 3. 在 VG 上创建逻辑卷 LV,比如 100G,名叫 lv_app
sudo lvcreate -L 100G -n lv_app vg_data
# 或者用全部剩余空间的百分比
sudo lvcreate -l 100%FREE -n lv_app vg_data

# 4. 格式化文件系统(注意选对文件系统类型)
sudo mkfs.xfs /dev/vg_data/lv_app
# 或
sudo mkfs.ext4 /dev/vg_data/lv_app

# 5. 挂载
sudo mkdir -p /data
sudo mount /dev/vg_data/lv_app /data

# 6. 查看结果
df -h /data
lsblk

写入 /etc/fstab 实现开机自动挂载,推荐用设备路径或 UUID:

# 方式一:用设备路径
echo '/dev/vg_data/lv_app /data xfs defaults 0 0' | sudo tee -a /etc/fstab

# 方式二:更稳妥,用 UUID
sudo blkid /dev/vg_data/lv_app
# UUID=xxxx-xxxx /data xfs defaults 0 0

# 校验 fstab(避免重启失败)
sudo findmnt --verify

fstab 写错会导致开机进 emergency 模式,改完一定用 findmnt --verify 校验,或给非关键挂载加 nofail。

在线扩容:加盘或扩卷

扩容分两种场景,弄清楚了就不会乱。

场景一:VG 里还有空闲空间,直接扩 LV

# 1. 先确认 VG 还有多少空闲
sudo vgs
# 看 VFree 那一列

# 2. 扩展 LV(比如增加 50G,或用 +100%FREE 吃掉全部剩余)
sudo lvextend -L +50G /dev/vg_data/lv_app
# 或扩到指定总大小
sudo lvextend -L 150G /dev/vg_data/lv_app
# 或占满剩余空间
sudo lvextend -l +100%FREE /dev/vg_data/lv_app

关键:lvextend 只扩了"逻辑卷"这个容器,文件系统并没有跟着变大,必须再扩文件系统。 这是新手最容易漏的一步——扩完 df -h 一看没变化,以为失败了。其实没失败,是文件系统层还没扩。

# 3. 扩展文件系统(在线,无需卸载)
# XFS 文件系统(只能扩不能缩)
sudo xfs_growfs /data
# 或指定挂载点
sudo xfs_growfs -d /data

# ext4 文件系统
sudo resize2fs /dev/vg_data/lv_app
# 或指定挂载点
sudo resize2fs /dev/vg_data/lv_app

# 4. 验证
df -h /data

注意 XFS 和 ext4 的区别:XFS 只能在线扩大,不能缩小;ext4 可以扩大也可以缩小(缩小要先卸载)。所以用 XFS 的话,扩容是安全的,缩容是不支持的。

lvextend 还有更方便的 -r(或 --resizefs)选项,可以一步同时扩 LV 和文件系统,省掉单独执行 resize2fs/xfs_growfs:

# 一步到位:扩 LV 并同步扩文件系统
sudo lvextend -r -L +50G /dev/vg_data/lv_app

推荐用 -r,但要知道它背后做了两件事,出问题时好定位。

场景二:VG 空间不够,先加新盘

# 1. 把新盘做成 PV
sudo pvcreate /dev/sdd

# 2. 加入现有 VG
sudo vgextend vg_data /dev/sdd

# 3. 确认 VG 空闲空间增加
sudo vgs

# 4. 再按场景一扩 LV 和文件系统
sudo lvextend -r -l +100%FREE /dev/vg_data/lv_app
df -h /data

云服务器上,扩容通常是先在控制台把云盘容量调大,然后在系统里让内核重新识别磁盘大小,再扩 PV:

# 云盘在控制台扩容后,让内核重新读取磁盘容量
# 注意:如果 PV 直接建在整块盘上
sudo pvresize /dev/vdb            # 让 PV 识别到磁盘变大了
sudo vgs                          # 确认 VFree 增加
sudo lvextend -r -l +100%FREE /dev/vg_data/lv_app
df -h /data

# 如果 PV 建在分区上,可能需要先用 growpart 扩分区
sudo growpart /dev/vdb 1          # 需 cloud-utils-growpart 包
sudo pvresize /dev/vdb1

growpart 和 pvresize 是云环境扩容的关键两步,很多云镜像还配了 cloud-init 自动做这件事,但手动扩容时要记得。

缩容:有风险,必须谨慎

缩容比扩容危险得多,因为顺序错了会丢数据。缩减的黄金法则是:先缩文件系统,再缩逻辑卷;扩容则相反,先扩 LV,再扩文件系统。

前提:XFS 不支持缩容。如果文件系统是 XFS,就别想缩容了,只能备份数据后重建。下面以 ext4 为例:

# 1. 必须先卸载文件系统(缩容不能在线做)
sudo umount /data

# 2. 强制文件系统自检(重要!)
sudo e2fsck -f /dev/vg_data/lv_app

# 3. 先缩文件系统到目标大小(比如 80G)
sudo resize2fs /dev/vg_data/lv_app 80G

# 4. 再缩逻辑卷到相同或更大一点的大小
sudo lvreduce -L 80G /dev/vg_data/lv_app

# 5. 如果 lvreduce 警告大小不匹配,重新检查
sudo e2fsck -f /dev/vg_data/lv_app

# 6. 重新挂载
sudo mount /data
df -h /data

风险提示:lvreduce 如果缩到比文件系统还小,会直接破坏数据。务必先缩文件系统。整个过程要卸载,意味着业务中断,生产环境做缩容要在维护窗口,并提前备份。lvreduce 会要求确认,操作时看清楚提示。回滚方式基本没有——数据损坏了就很难恢复,所以备份是唯一保险。

快照:备份和回滚的利器

LVM 支持创建快照(snapshot),它利用 COW(写时复制)机制,快照创建瞬间几乎不占空间,之后只有原卷被修改的块才会被记录到快照空间里。快照的典型用途:

  • 备份:对数据库做一致性备份时,先打一个快照,再对快照做备份,避免备份期间数据变化;
  • 测试/回滚:升级前打快照,出问题快速回滚。
# 创建快照,分配 10G 给快照空间(存放变化数据)
sudo lvcreate -L 10G -s -n lv_app_snap /dev/vg_data/lv_app

# 查看快照
sudo lvs
# 快照的 LSize 是分配的空间,Data% 是已用比例

# 挂载快照查看(只读或读写都可以,一般只读挂载)
sudo mkdir -p /mnt/snap
sudo mount -o ro /dev/vg_data/lv_app_snap /mnt/snap
ls /mnt/snap

快照空间会被写满:如果原卷变化的数据超过快照分配的空间,快照就失效了(状态变成 Invalid)。所以给快照分配的空间要足够大,通常不低于原卷变更量的两倍。用 lvs 的 Data% 监控快照使用率,超过百分之七十就要警惕。

# 监控快照使用情况
sudo lvs -o +snap_percent

回滚到快照:把原卷还原到快照时刻的状态。这一步会丢弃快照之后的所有修改,务必确认。

# 1. 卸载原卷和快照
sudo umount /mnt/snap
sudo umount /data

# 2. 执行合并(把快照合并回原卷)
sudo lvconvert --merge /dev/vg_data/lv_app_snap

# 3. 重新挂载,数据回到快照时刻
sudo mount /data

风险提示:lvconvert --merge 会覆盖原卷数据,合并后快照被删除。合并前一定要确认盘上没有需要保留的新数据,最好先对当前状态再打一个快照做双重保险。

pvmove:把数据从一块盘迁到另一块盘

当某块磁盘要更换、要下线,或者发现某块盘性能好想把数据挪过去,可以用 pvmove 在线迁移 VG 里某个 PV 上的数据:

# 1. 确认目标 VG 里有其他 PV 且有足够空闲空间
sudo pvs
sudo vgs

# 2. 把 /dev/sdb 上的数据全部迁到同 VG 的其他 PV
sudo pvmove /dev/sdb

# 3. 迁移完成后,把空出来的 PV 从 VG 移除
sudo vgreduce vg_data /dev/sdb

# 4. 如果不再作为 LVM 使用,可以清空 PV 标记
sudo pvremove /dev/sdb

pvmove 是在线操作,业务不中断,但会占用 I/O,建议在低峰期做。数据量大时可能持续较长时间,可以用另一个终端观察进度(命令本身会显示百分比)。迁移时目标 PV 必须有足够空间。

云盘与 LVM 的配合

现在很多服务器用的是云盘,LVM 在云环境下的使用方式略有不同:

好处:云盘可以随时扩容(控制台调整容量),配合 LVM 实现在线扩容。典型流程是:控制台扩云盘 → 系统里 growpart(如果 PV 在分区上)→ pvresize → lvextend -r → df -h 确认。这套流程可以脚本化,大部分云厂商镜像支持扩容后自动执行。

注意云盘的两类:一类是"一块云盘当一块盘用",另一类是"多块小云盘组成 VG"。后者虽然灵活,但要注意:VG 跨多块云盘时,任意一块盘故障都可能影响整个 VG。如果云盘本身没有冗余(比如本地盘),别把关键数据跨盘组 VG。

快照配合:云厂商通常提供磁盘级快照,它对应的是"云盘"这一层;而 LVM 快照是"逻辑卷"这一层。两者可以互补:云盘快照做整盘冷备,LVM 快照做卷级热备和回滚。

常见问题

扩了 LV 但 df -h 没变化?

因为只扩了逻辑卷,没扩文件系统。再执行对应文件系统的扩容命令:XFS 用 xfs_growfs /挂载点,ext4 用 resize2fs /dev/vg/lv。或者一开始就用 lvextend -r 一步到位。

XFS 能缩容吗?

不能,XFS 官方不支持缩小文件系统。如果文件系统是 XFS 且确实需要缩小,只能备份数据、删除 LV、重建一个更小的、再恢复数据。规划容量时宁可留有余量,也别指望事后缩容。

快照为什么突然变成无效(Invalid)?

快照空间被写满了。快照分配的空间不足以容纳原卷的变化量,LVM 会自动让它失效。要么重建快照并分配更大空间,要么缩短快照存活时间、加快备份节奏。用 lvs -o +snap_percent 监控。

pvmove 中途断了怎么办?

pvmove 支持断点续传,重新执行 pvmove /dev/sdb 会从断点继续。迁移过程中不要动相关磁盘。如果卡住,检查目标 PV 是否有足够空间、磁盘是否健康。

云盘扩容后 pvresize 报错?

多半是 PV 建在分区上,而分区还没扩。先 growpart /dev/vdb 1 扩分区,再 pvresize /dev/vdb1。如果 PV 直接建在整块盘上,直接 pvresize /dev/vdb 即可。另外注意有些云盘扩容后需要先让内核重读磁盘大小。

总结

  • LVM 用 PV(物理卷)、VG(卷组)、LV(逻辑卷)三层抽象,把容量变成可灵活分配的资源,扩容和快照是它最核心的价值。
  • 扩容顺序是"先扩 LV 再扩文件系统",用 lvextend -r 可一步完成;扩文件系统时 XFS 用 xfs_growfs、ext4 用 resize2fs,注意 XFS 只能扩不能缩。
  • 缩容顺序相反,必须"先卸载、检查、缩文件系统、再缩 LV",且 XFS 不支持缩容;缩容前务必备份,生产环境在维护窗口做。
  • 快照基于 COW,创建快即、占地小,但分配空间不足会失效,要监控 snap_percent;lvconvert --merge 回滚会丢弃后续数据,操作前确认并再做保险。
  • 换盘或下线磁盘用 pvmove 在线迁移;云盘扩容流程是控制台扩容量 → growpart/pvresize → lvextend -r,跨多块盘的 VG 要注意单盘故障风险。
  • 涉及 pvcreate、lvcreate、lvreduce、mkfs 等会清空或破坏数据的操作,执行前必须 lsblk 核对设备、做好备份,改 fstab 后用 findmnt --verify 校验。