Linux LVM 逻辑卷管理
一、概念与原理
1. 为什么需要 LVM
传统分区方式下,一块硬盘 /dev/sdb 直接分区(/dev/sdb1)后格式化挂载,分区大小固定,想改大改小非常麻烦:
- 扩容:分区表边界固定,需删除重建或借助第三方工具,风险高
- 跨盘:两块盘各自分区,空间无法合并使用
- 数据不灵活:无法做快照、无法在线迁移
LVM(Logical Volume Manager,逻辑卷管理器)解决这些问题:它把多块磁盘(或分区)先"化整为零"再"聚合成池",然后从池里自由切块,做到:
- 空间跨多块盘合并(4 块 1T 盘 = 一个 4T 池)
- 在线动态扩容、缩容(文件系统支持时)
- 快照备份(秒级生成一致性副本)
- 在线迁移数据(pvmove)
1.2 三层核心对象
LVM 分三个层次,由下往上:
┌─────────────────────────────────────────────┐
│ LV Logical Volume 逻辑卷(可格式化挂载) │
├─────────────────────────────────────────────┤
│ VG Volume Group 卷组(存储池,可合并盘) │
├─────────────────────────────────────────────┤
│ PV Physical Volume 物理卷(磁盘/分区) │
├─────────────────────────────────────────────┤
│ 底层:磁盘 /dev/sdb、/dev/sdc ...(或分区) │
└─────────────────────────────────────────────┘
| 对象 | 全称 | 说明 | 典型操作 |
|---|---|---|---|
| PV | Physical Volume 物理卷 | 由磁盘或分区初始化而来,打上 LVM 标记 | pvcreate |
| VG | Volume Group 卷组 | 一个或多个 PV 合并成的存储池 | vgcreate |
| LV | Logical Volume 逻辑卷 | 从 VG 中划出的一块空间,格式化后挂载 | lvcreate |
1.3 最小单元:PE / LE
- PE(Physical Extent)物理扩展块:PV 被切割成等大小的小块,PE 是 LVM 分配的最小单位,默认 4 MiB(可用
-s指定 1/2/4/8/16/32/64MiB,整个 VG 统一) - LE(Logical Extent)逻辑扩展:LV 对应的小块,与 PE 一一映射
说白了:VG 是一大箱 PE,LV 是向箱子领走若干 PE 装进自己的口袋。扩容就是再领几个 PE,缩容就是退回几个 PE。
PE 大小影响:PE 越小,管理越精细但元数据越多;默认 4M 足够,通常不需要改。
1.4 LVM 元数据与设备名
- 每块 PV 头部写入 LVM 元数据(Label Header),记录 PV/VG 信息
- VG 元数据默认有自动备份:
/etc/lvm/backup/(最新)和/etc/lvm/archive/(历史),可用于vgcfgrestore恢复 - LV 创建后设备名:
/dev/卷组名/逻辑卷名(软链接到/dev/mapper/卷组名-逻辑卷名)
lvcreate -L 10G -n lvdata vgdata
# 生后设备:
# /dev/vgdata/lvdata ← 习惯用这个
# /dev/mapper/vgdata-lvdata ← 底层真实设备
ls -l /dev/vgdata/lvdata # 能看到符号链接
1.5 与 RAID 的区别
| LVM | RAID(mdadm/硬件) | |
|---|---|---|
| 目的 | 弹性管理(扩缩容、快照) | 性能 + 冗余(坏盘不丢数) |
| 是否冗余 | 否,磁盘坏了 LV 就丢 | 是(RAID1/5/6/10) |
| 组合使用 | 可先用 RAID 再建 LVM | 可 LVM 做 RAID(LVM RAID) |
生产常用:底层 RAID → 上面 LVM → 便于扩容。LVM 不提供数据冗余,无 RAID 的 LVM 坏盘=数据丢失。
二、创建 LVM 全流程(从零到挂载)
2.1 前置:查看磁盘
lsblk # 推荐,直观看出磁盘/分区/挂载
fdisk -l # 传统查看
假设新增一块盘 /dev/sdb,目标是建一个 20G 的逻辑卷挂到 /data。
2.2 步骤 1:分区(可选,不分区也可直接做 PV)
fdisk /dev/sdb
# 交互内依次:
# n 新建分区
# p 主分区
# 1 分区号
# 回车 回车(默认全盘)
# t 改分区类型
# 8e ← Linux LVM 类型(MBR 分区表)
# w 保存
GPT 分区表类型码略有不同(fdisk 内输入 t 后输入 lvm 或查 8e00)。
注意:整块盘直接用,也可跳过分区,直接把 /dev/sdb 当 PV(缺点:整盘被 LVM 占用,无法再分区;迁移更简单)。
2.3 步骤 2:创建 PV
pvcreate /dev/sdb1 # 分区
# 或整盘
pvcreate /dev/sdb # 整块盘
pvs # 查看所有 PV(推荐)
pvdisplay /dev/sdb1 # 详细查看单个
2.4 步骤 3:创建 VG
vgcreate vgdata /dev/sdb1
# 如果一次性合并多块盘:
vgcreate vgdata /dev/sdb1 /dev/sdc1 /dev/sdd1
vgs # 查看 VG 概览
vgdisplay vgdata # 详细
2.5 步骤 4:创建 LV
# 指定大小创建
lvcreate -L 20G -n lvdata vgdata
# 用尽 VG 剩余全部空间
lvcreate -l 100%FREE -n lvdata vgdata
# 查看
lvs
lvdisplay /dev/vgdata/lvdata
-L 是大小(20G/20GiB),-l 是百分比或 PE 数(100%FREE、50%VG)。
2.6 步骤 5:格式化
# ext4(可扩容、可缩容)
mkfs.ext4 /dev/vgdata/lvdata
# 或 xfs(可扩容、不可缩容,大文件性能好)
mkfs.xfs /dev/vgdata/lvdata
2.7 步骤 6:挂载 + 开机自动挂载
mkdir -p /data
mount /dev/vgdata/lvdata /data
df -h /data
写入 /etc/fstab(推荐写 UUID,磁盘路径变化不慌):
blkid /dev/vgdata/lvdata # 查 UUID
# 编辑 /etc/fstab,追加:
UUID=xxxx-xxxx-xxxx /data ext4 defaults 0 0
注意:fstab 中如用设备名,用
/dev/mapper/vgdata-lvdata比/dev/vgdata/lvdata更稳(LVM 提供的软链接在引导早期可能不存在,mapper 路径由 udev 生成)。
三、常用命令速查(pv / vg / lv 三套)
| 功能 | PV(物理卷) | VG(卷组) | LV(逻辑卷) |
|---|---|---|---|
| 查看概览 | pvs |
vgs |
lvs |
| 查看详情 | pvdisplay |
vgdisplay |
lvdisplay |
| 扫描发现 | pvscan |
vgscan |
lvscan |
| 创建 | pvcreate /dev/sdb1 |
vgcreate vg /dev/sdb1 |
lvcreate -L 10G -n lv vg |
| 扩容 | — | vgextend vg /dev/sdc1 |
lvextend -L +5G /dev/vg/lv |
| 缩容 | — | vgreduce vg /dev/sdc1 |
lvreduce -L 5G /dev/vg/lv |
| 通用调整 | — | — | lvresize(扩缩一体) |
| 删除 | pvremove /dev/sdb1 |
vgremove vg |
lvremove /dev/vg/lv |
| 激活/停用 | — | vgchange -ay / -an |
lvchange -ay / -an /dev/vg/lv |
| 改名 | — | vgrename |
lvrename |
| 重设 PE 大小 | — | vgcreate -s 8M vg ... |
— |
3.1 查看信息的输出重点
vgs
# VG #PV #LV #SN Attr VSize VFree
# vgdata 1 2 0 wz--n- 99.99g 79.99g
# #PV 组里有多少块物理卷
# #LV 组里有多少个逻辑卷
# VSize 组总容量 VFree 剩余可用
3.2 删除顺序
lvremove /dev/vg/lv # 先删 LV(已挂载需先 umount,加 -y 免确认)
vgremove vg # 再删 VG
pvremove /dev/sdb1 # 最后删 PV(清除 LVM 标记)
四、扩容实战(最常用)
4.1 场景 A:VG 有剩余空间 → 直接扩 LV
# 查 VFree 够不够
vgs
# 扩容 LV(+5G = 增加 5G)
lvextend -L +5G /dev/vgdata/lvdata
# 或直接扩到指定总大小
lvextend -L 25G /dev/vgdata/lvdata
# 或一次性用完所有剩余
lvextend -l +100%FREE /dev/vgdata/lvdata
4.2 扩容后同步文件系统(关键,易漏)
# ext4:
resize2fs /dev/vgdata/lvdata
# xfs(必须挂载后执行,且目标写挂载点):
xfs_growfs /data
校验:
df -h /data确认容量变大了。
4.3 场景 B:VG 空间不够 → 先扩 VG 再加盘
# 新加一块盘 /dev/sdc(建议先分区类型 8e,或直接用整盘)
pvcreate /dev/sdc1
vgextend vgdata /dev/sdc1
vgs # 确认 VFree 变大
# 然后回到场景 A 扩 LV + resize
4.4 一次到位:lvextend -r
-r(resize)让 LVM 自动联动扩容文件系统(ext4/xfs 均可自动处理):
lvextend -r -L +5G /dev/vgdata/lvdata
# 等价于 lvextend + resize2fs/xfs_growfs 两步
五、缩容(xfs 不能缩,ext4 才行)
⚠️ xfs 不支持缩容。如果卷是 xfs,想缩小必须「备份 → 删 LV → 重建更小 → 恢复数据」。
ext4 缩容顺序严格:先缩文件系统 → 再缩 LV(顺序反了会损坏数据)。
# 1. 卸载(不能在挂载状态下缩)
umount /data
# 2. 强制检查文件系统
e2fsck -f /dev/vgdata/lvdata
# 3. 先把文件系统缩小到目标值(比如从 25G 缩到 15G)
resize2fs /dev/vgdata/lvdata 15G
# 4. 再把 LV 缩小到目标值
lvreduce -L 15G /dev/vgdata/lvdata
# 提示是否确认,输 y
# 5. 重新挂载
mount /data
df -h /data
缩容先备份!
resize2fs缩的每一步都应确认数据量远小于目标大小(df -h已用 < 目标值)。
缩容出错概率高,生产环境能缩尽量缩,不要缩成"正好"。
六、快照(Snapshot)
LVM 快照基于 COW(Copy-On-Write,写时复制):创建瞬间不复制全量数据,只记录"原卷被修改前的旧块",因此秒级完成、占用空间小。
创建快照前:原卷数据块 A B C ...
快照瞬间: 记录一个"快照点",指向原卷
之后原卷被修改块 A→A':把旧 A 拷入快照区
快照内容 = 原卷数据 + 快照区旧块 = 创建瞬间的完整数据
6.1 创建快照
# -s 快照,-L 指定快照区大小(要覆盖"快照存活期间被修改的数据量")
lvcreate -s -L 5G -n snap_lvdata /dev/vgdata/lvdata
lvs # 能看到 snap_lvdata,Attr 显示 s
快照空间一般给原卷的 20% 左右,若写满会自动失效/损坏(写入会失败),生产上需监控。
6.2 挂载快照做备份
mkdir -p /mnt/snap
mount /dev/vgdata/snap_lvdata /mnt/snap # 快照只读挂载,别写
tar -czf /backup/data.tar.gz -C /mnt/snap .
umount /mnt/snap
6.3 删除快照
umount /mnt/snap
lvremove /dev/vgdata/snap_lvdata
6.4 回滚:用快照恢复原卷
umount /data
# --merge 把快照内容合并回原卷(原卷数据被快照时刻覆盖)
lvconvert --merge /dev/vgdata/snap_lvdata
mount /data
合并后快照消失;合并要求原卷未挂载(或挂载在只读时可能失败),建议先 umount。
七、数据迁移:pvmove
把数据在物理盘之间搬走(常用于:替换坏盘、把某块盘从 VG 摘除、盘扩容):
# 把 /dev/sdb1 上的所有 PE 数据搬到同组其他 PV
pvmove /dev/sdb1
# 指定目标盘
pvmove /dev/sdb1 /dev/sdc1
# 搬完后从 VG 移除空盘,再抹掉 PV 标记
vgreduce vgdata /dev/sdb1
pvremove /dev/sdb1
# 此时 /dev/sdb 可拔盘/重新分配
在线进行,无需停机,中途可 pvs -o+dev 观察进度(移动中显示部分)。
八、常见问题与排障
8.1 重启后挂载失败 / LV 找不到
现象:/etc/fstab 挂载报错,或 /dev/vg/lv 不存在。
原因之一:系统启动时 VG 未激活(少见,常见于 initramfs 缺 lvm2)。
vgscan # 重新扫描发现 VG
vgchange -ay # 激活所有 VG(-ay = activate yes)
vgdisplay vgdata # 确认 active
根治:重新生成 initramfs(RHEL 系):
dracut -f或mkinitrd -f;确认 lvm2 已装:yum install -y lvm2。
8.2 VG 元数据损坏 / 恢复
# LVM 每块 PV 都存元数据备份,查看历史:
vgcfgrestore -l vgdata # 列出可恢复的时间点
vgcfgrestore -f /etc/lvm/archive/vgdata_xxx vgdata # 恢复
8.3 xfs 卷扩了但 df 没变
忘记 xfs_growfs(resize2fs 对它无效)。执行:
xfs_growfs /data(挂载点,必须挂载)。
8.4 删除 LV 前须知
lvremove 不回收文件系统,先 umount,必要时先 vgcfgbackup;删除动作不可逆,删除前确认里面没重要数据。
8.5 PV 显示 unknown / 设备路径变化
PV 存的是磁盘路径,改名后 pvscan 报 “unknown device”。
解决:vgreduce --removemissing vg 或先恢复原设备名/符号链接。
九、磁盘规划建议
- 分区 vs 整盘:单盘独立做 PV 用整盘即可;盘上还想放别的就分区(8e)
- PE 大小:默认 4M,非特殊需求不调
- VG 规划:一个 VG 尽量只放一类用途(如
vgdata、vgbackup),命名带含义 - LV 规划:预留 VFree 20% 左右,方便随时扩;不要把所有盘塞满
- xfs vs ext4:xfs 大文件/性能好但不能缩容;ext4 灵活可缩容。虚拟化/镜像场景 xfs 常见
- 快照:备份时间点优先于全量复制,快照区别给太小
- 备份 fstab/UUID:用 UUID 而非 /dev/sdX 路径,避免盘序变化
十、速查命令汇总(复制即用)
# ---- 查看 ----
lsblk; pvs; vgs; lvs
pvdisplay; vgdisplay /dev/vg; lvdisplay /dev/vg/lv
# ---- 创建 ----
fdisk /dev/sdb # 分区 → 8e → w
pvcreate /dev/sdb1
vgcreate vg /dev/sdb1
lvcreate -L 20G -n lv vg
mkfs.ext4 /dev/vg/lv # 或 mkfs.xfs
mount /dev/vg/lv /data
# ---- 扩容 ----
vgextend vg /dev/sdc1 # 先加盘(可选)
lvextend -r -L +5G /dev/vg/lv # 自动扩文件系统
# ---- 缩容(仅 ext4)----
umount /data
e2fsck -f /dev/vg/lv
resize2fs /dev/vg/lv 15G
lvreduce -L 15G /dev/vg/lv
mount /data
# ---- 快照 ----
lvcreate -s -L 5G -n snap /dev/vg/lv
mount /dev/vg/snap /mnt
lvremove /dev/vg/snap
# ---- 清理整组 ----
umount /data
lvremove /dev/vg/lv
vgremove vg
pvremove /dev/sdb1
核心心法:建:盘→PV→VG→LV→文件系统→挂载;扩:LV→文件系统;缩:文件系统→LV(且 ext4 only)。
- 点赞
- 收藏
- 关注作者
评论(0)