做Linux运维和服务器管理磁盘管理是永远绕不开的基本功。而只要涉及“动态扩容”“灵活调整”这类需求LVM逻辑卷管理几乎就是默认答案。网上讲LVM的教程不少但大多数只停留在“敲命令能跑通”的层面真正到生产环境遇到卷组满了、磁盘掉了、系统重启后卷不认了才发现自己对LVM的理解还是皮毛。这篇文章围绕最核心的三个命令——pvcreate、vgcreate、lvcreate把LVM从裸盘到业务挂载的完整链路捋一遍。我会把每一步背后的设计逻辑、参数取舍、实际运维中容易踩的坑都讲清楚。适合刚接触LVM的初学者也适合那些用过LVM但遇到问题只能靠百度解决的运维朋友。1. LVM整体设计与核心思路很多人第一次接触LVM时最大的困惑是明明fdisk分区、mkfs格式化、mount挂载就能用为什么还要多出PV、VG、LV这一堆概念这个问题的答案恰恰是LVM存在的根本意义。1.1 传统分区的痛点在哪里用传统分区方式管理磁盘最大的问题在于“分区的边界是固定的”。比如你给/home分了500G结果数据涨得飞快500G不够用了而/data分区还剩200G空闲。这时候你想把200G挪给/home做不到。传统分区不支持在线调整大小就算用resize2fs配合fdisk调整也得先卸载分区、重新划分边界极其痛苦而且有数据丢失风险。我见过不少业务事故就是磁盘扩容时操作失误导致数据损坏。用LVM之后这种“拆东墙补西墙”的问题基本不存在了因为LVM把物理磁盘和最终呈现给业务的逻辑空间彻底解耦了。1.2 三层架构与核心概念LVM把磁盘管理抽象成三层PVPhysical Volume物理卷最底层本质是把整块磁盘或磁盘分区初始化为LVM可识别的格式相当于把磁盘“格式化”成LVM的原料。VGVolume Group卷组由多个PV聚合成一个“空间池子”VG就是磁盘空间的中转仓库。你可以随时往VG里加PV也可以把PV从VG里移走。LVLogical Volume逻辑卷从VG池子里切割出来的“虚拟分区”这才是最终格式化和挂载给业务使用的对象。打个比方PV是你买回来的面粉原材料VG是你的厨房储物柜LV是你从柜子里取出来、和好面准备蒸的那屉馒头。面粉多了就塞进柜子柜子里的空间可以随时调整蒸多少馒头不需要把已经蒸好的馒头回炉重做。1.3 核心抽象PE与LELVM底层还有两个容易被忽略的概念——PE和LE。PEPhysical Extent物理扩展块PV空间被划分成等大的小块这个块的大小在创建VG时指定。LELogical Extent逻辑扩展块LV空间同样被划分成等大的小块一个LE对应一个PE。实际上LVM管理空间的最小单位不是MB或GB而是PE。VG里的空间就是由一个一个PE组成的LV分配空间时本质是“从VG中领取若干个PE”。理解这点对后面理解lvcreate的-l参数特别重要因为-l参数指定的就是“领多少个PE”或者“占VG总PE数的百分之多少”。1.4 有了LVM能做什么总结下来LVM带来的核心能力就三个在线扩容VG容量不够时加新硬盘或新分区vgextend把空间加入池子再lvextend给LV扩容整个过程不用卸载分区、不用重启系统。在线缩容虽然生产环境我强烈不建议对在线文件系统做缩容但LVM至少在技术层面支持对ext4等文件系统进行缩容操作。灵活组合多块大小不一的磁盘通过LVM可以拼成一个大的VG然后按需切分给不同的业务目录空间利用率远高于传统固定分区。接下来我们就从最基础的pvcreate开始一路到lvcreate把这条命令链路完整走一遍。2. 核心命令实操pvcreate、vgcreate、lvcreate详解这一章是全文的重头戏。我会把三个命令的适用对象、参数含义、典型使用场景逐一拆解同时把实际操作中容易踩的坑全部标出来。2.1 实操前提与环境准备在敲任何命令之前先确认两件事目标磁盘确实没有被使用以及分区表状态是否满足LVM需求。先看一下当前磁盘情况[rootlocalhost ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 100G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 8:2 0 99G 0 part / sdb 8:16 0 100G 0 disk sdc 8:32 0 100G 0 disk这里sdb和sdc是两块全新的空盘没分区也没挂载非常适合用来演示。如果你是给已有分区的磁盘做PV建议先用fdisk把分区类型改成LVMHex code 8e这个操作很多人容易忽略。以sdb为例使用fdisk修改分区类型fdisk /dev/sdb进入交互界面后依次输入n创建新分区一直回车使用默认值t修改分区类型输入8e表示Linux LVM类型w保存退出修改完执行partprobe让内核重新读取分区表partprobe2.2 pvcreate把物理磁盘变成LVM原料pvcreate的作用就是把一整块磁盘或一个磁盘分区初始化为LVM的物理卷。[rootlocalhost ~]# pvcreate /dev/sdb /dev/sdc Physical volume /dev/sdb successfully created. Physical volume /dev/sdc successfully created.这一步实际上是往磁盘头部写入LVM元数据metadata标记这块磁盘“归LVM管理了”。执行后用pvs或pvdisplay查看[rootlocalhost ~]# pvs PV VG Fmt Attr PSize PFree /dev/sdb lvm2 --- 100.00g 100.00g /dev/sdc lvm2 --- 100.00g 100.00g这里有几个细节值得注意pvcreate可以直接针对整块磁盘也可以针对分区比如/dev/sdb1。直接对整块盘做PV省去了分区步骤但后期如果要做LVM之外的操作会麻烦一点。PV的元数据默认存放在磁盘开头的特定区域。如果做完PV后用pvremove /dev/sdb可以清除元数据、把磁盘恢复成普通状态。执行pvcreate前务必确认这块磁盘上没有任何业务数据。因为一旦做了PV原有的分区信息和文件系统结构会被LVM元数据覆盖。2.3 vgcreate把物理卷聚合为卷组有了PV之后下一步就是把一个或多个PV组合成一个VG。[rootlocalhost ~]# vgcreate vg_data /dev/sdb /dev/sdc Volume group vg_data successfully created这里vg_data是我给卷组起的名字命名规则和普通变量类似建议起得有意义——比如按用途分vg_data、vg_log、vg_backup后期看到卷组名就能知道它服务于哪个业务。创建后用vgs或vgdisplay查看[rootlocalhost ~]# vgs VG #PV #LV #SN Attr VSize VFree vg_data 2 0 0 wz--n- 199.99g 199.99gVG原始容量是200G因为LVM自身会占用少量元数据空间所以显示199.99G正常现象。关于vgcreate最重要的一个参数是-s即PE大小[rootlocalhost ~]# vgcreate -s 16M vg_data /dev/sdb /dev/sdcPE大小直接决定了VG里空间分配的最小粒度。如果不指定默认是4MB。什么场景需要调整呢比如你的VG特别大单个LV动辄几十TB用默认4M的PE会导致LV内部的“块数量”巨大可能带来一定性能损耗此时可以把PE调大比如16M或32M。相反如果空间规划很细碎、经常要做小容量分配就保持4M甚至更小。注意PE大小一旦确定后期无法直接修改。想改只能重建VG所以创建VG前务必想清楚。2.4 lvcreate从卷组切割逻辑卷VG创建完成后就可以用lvcreate从VG中切出LV了。2.4.1 按容量创建最直观的用法是按指定容量创建[rootlocalhost ~]# lvcreate -L 20G -n lv_data1 vg_data Logical volume lv_data1 created.-L 20G表示创建20G大小的逻辑卷-n lv_data1指定逻辑卷名字。创建后设备路径是/dev/vg_data/lv_data1也可以通过/dev/mapper/vg_data-lv_data1访问。2.4.2 按PE数量创建如果需要更精细地控制空间可以改用-l参数指定从VG中分配多少个PE[rootlocalhost ~]# vgdisplay vg_data | grep Total PE Total PE 12799 [rootlocalhost ~]# lvcreate -l 1280 -n lv_data2 vg_data如果PE大小是16M1280个PE就恰好是20G。还有一种更省心的写法直接按百分比分配[rootlocalhost ~]# lvcreate -l 30%VG -n lv_data3 vg_data这条命令表示从VG总空间里取30%给新LV非常适合不确定VG具体容量、只想按比例分配的场景。2.4.3 跨PV分配的行为当VG里有多块PV时lvcreate默认会在多块PV上“摊开”分配空间。比如上面创建的lv_data1它的空间可能一部分落在sdb上、一部分落在sdc上这种特性天然实现了类似RAID0的条带化写入提升了I/O性能但物理上任何一块磁盘故障都会导致LV不可用。如果想尽量把某个LV的空间留在同一块PV上可以用-C y参数开启连续分配策略但代价是可能浪费其他PV上的空间。实际生产中除非你这个VG本身就是由多块数据盘组成、且业务能容忍单盘故障风险否则不必过度纠结这个细节。2.5 格式化与挂载LV创建成功并不代表可以直接使用还需要格式化文件系统并挂载[rootlocalhost ~]# mkfs.xfs /dev/vg_data/lv_data1 [rootlocalhost ~]# mkdir /data1 [rootlocalhost ~]# mount /dev/vg_data/lv_data1 /data1想让重启后自动挂载把下面这行写入/etc/fstab/dev/vg_data/lv_data1 /data1 xfs defaults 0 0如果你用的是ext4文件系统创建命令对应mkfs.ext4。xfs和ext4在后续扩容操作上有区别这个下文会有详细说明。3. 实战演练从两块裸盘到业务挂载的完整链路这一章我以一台测试服务器为例模拟真实业务场景新加两块300G磁盘需要做成LVM最终挂载给一个文件服务目录使用并且预留扩展能力。3.1 环境规划与磁盘准备业务需求给一个图片上传服务准备存储目录当前预计需要200G但后续可能迅速增长要求能在线扩容。操作思路两块300G磁盘都加入LVM创建一个VG先给业务分配200G的LV剩余空间留作后续扩容池。检查磁盘状态[rootlocalhost ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 300G 0 disk sdb 8:16 0 300G 0 disk两块盘都是裸设备直接创建PV[rootlocalhost ~]# pvcreate /dev/sda /dev/sdb [rootlocalhost ~]# pvs PV VG Fmt Attr PSize PFree /dev/sda lvm2 --- 300.00g 300.00g /dev/sdb lvm2 --- 300.00g 300.00g3.2 创建VG并制定PE大小考虑到后续要频繁创建LV且业务容量跨度较大我把PE设置为16M[rootlocalhost ~]# vgcreate -s 16M vg_images /dev/sda /dev/sdb [rootlocalhost ~]# vgdisplay vg_images --- Volume group --- VG Name vg_images System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 2 Act PV 2 VG Size 599.98 GiB PE Size 16.00 MiB Total PE 38399 Alloc PE / Size 0 / 0 Free PE / Size 38399 / 599.98 GiB注意到PE Size已经是16MiBTotal PE是38399个这意味着后续所有LV空间分配都是以16M为最小单位展开的。3.3 创建LV并初始化文件系统为业务创建200G的逻辑卷[rootlocalhost ~]# lvcreate -L 200G -n lv_upload vg_images Logical volume lv_upload created.查看LV状态[rootlocalhost ~]# lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert lv_upload vg_images -wi-a----- 200.00g格式化并挂载[rootlocalhost ~]# mkfs.xfs /dev/vg_images/lv_upload [rootlocalhost ~]# mkdir /srv/upload [rootlocalhost ~]# mount /dev/vg_images/lv_upload /srv/upload [rootlocalhost ~]# df -h /srv/upload Filesystem Size Used Avail Use% Mounted on /dev/mapper/vg_images-lv_upload 200G 33M 200G 1% /srv/upload到这里一条从裸盘到业务可用存储的完整链路就跑通了。3.4 在线扩容文件系统增长的关键操作图片服务跑了一周200G快用完了。现在需要把lv_upload扩容到300G全程不卸载文件系统。第一步扩展LV本身[rootlocalhost ~]# lvextend -L 100G /dev/vg_images/lv_upload Size of logical volume vg_images/lv_upload changed from 200.00 GiB (12800 extents) to 300.00 GiB (19200 extents). Logical volume vg_images/lv_upload successfully resized.第二步扩容文件系统。这一步必须根据文件系统类型区别对待xfs文件系统使用xfs_growfs[rootlocalhost ~]# xfs_growfs /srv/uploadext4文件系统使用resize2fs[rootlocalhost ~]# resize2fs /dev/vg_images/lv_upload执行后再看df -h会发现文件系统已扩容到300G业务无感知。这就是LVM在生产环境最核心的价值。注意xfs文件系统只支持扩容不支持缩容ext4虽然支持缩容但强烈不建议在生产环境对在线缩容风险极高。3.5 卷组扩容VG空间不够时怎么办如果整个VG的空间都不够了比如上面的ve_images已经用了450G剩余150G不够业务下一个阶段的扩容需求就需要往VG里加新磁盘。假设新加了一块500G磁盘sdc[rootlocalhost ~]# pvcreate /dev/sdc [rootlocalhost ~]# vgextend vg_images /dev/sdc [rootlocalhost ~]# vgs VG #PV #LV #SN Attr VSize VFree vg_images 3 1 0 wz--n- 1.07t 620.00g之后继续lvextend按需扩容即可整个过程链条非常顺。4. 常见问题与排查技巧实录这一章的内容是我多年运维生涯里积累的经验合集。看起来都是小问题但在生产环境出问题时每一个都可能让人抓狂。4.1 删除顺序与残留清理LVM设备删除顺序必须严格遵循“先LV、再VG、最后PV”不能乱来。正确删除流程# 1. 卸载LV挂载点 umount /srv/upload # 2. 删除LV lvremove /dev/vg_images/lv_upload # 3. 删除VG vgremove vg_images # 4. 删除PV pvremove /dev/sda /dev/sdb如果直接执行pvremove而VG还引用着该PV系统会报PV仍被VG使用阻止删除。这是LVM的保护机制不要把报错当成故障。4.2 千万别在挂载状态下删LV我见过一个真实案例某同事直接对挂载中的LV执行lvremove以为空出空间就好结果删完发现文件系统彻底损坏数据没法恢复。LVM虽然会尝试阻止删除已挂载的LV但在某些版本、某些文件系统状态下仍然可能造成不可逆转的数据丢失。一定要先确认umount成功、lsof确认无进程占用再做删除操作。4.3 重启后卷不认了系统重启后发现VG不在了、LV挂载不了连/dev/vg_images/lv_upload路径都不存在。这种情况大概率是LVM元数据没有被正确扫描到。先用pvscan扫描所有磁盘的PV[rootlocalhost ~]# pvscan PV /dev/sda VG vg_images lvm2 [300.00 GiB / 300.00 GiB free] PV /dev/sdb VG vg_images lvm2 [299.98 GiB / 299.98 GiB free]如果发现某块盘没有被PV列表识别但磁盘上明确做过LVM可以手动指定设备扫描[rootlocalhost ~]# pvscan --cache /dev/sdc如果因为系统启动顺序问题导致PV设备节点还没创建LVM通常会在boot阶段自动扫描所有磁盘设备。实在不行检查一下/etc/lvm/lvm.conf中的filter配置看是不是把这块磁盘设备过滤掉了。4.4 卷组满了先看VG再找LV遇到“无法创建新LV”或者“lvextend失败”的情况不要直接怀疑磁盘坏了先按下面的排查顺序走一遍# 1. 看VG总容量和空闲容量 vgs # 2. 看具体PV的空间使用 pvdisplay # 3. 看具体LV的容量 lvs # 4. 看文件系统是否真的满了 df -h很多情况下VG里还有充足空闲空间而是某个LV的文件系统容量没跟上。比如LV已经扩容了但ext4没执行resize2fs业务就仍然看到旧容量。4.5 LVM快照功能简述lvcreate除了创建正常LV之外还可以为已有LV创建快照[rootlocalhost ~]# lvcreate -L 20G -s -n snap1 /dev/vg_images/lv_upload快照不是备份它依赖原LV的数据一旦原数据块发生修改LVM会先把原数据复制到快照区域。如果快照空间满了快照就会失效无法继续提供一致性视图。生产环境做数据库一致性备份前可以用快照来保证备份文件一致性但千万别把快照当成长期备份方案。4.6 磁盘移机后如何恢复VG当某块PV被换到另一台机器上只要这块PV之前存在于某个VG中并且元数据信息完整可尝试以下流程[rootnew-host ~]# pvscan [rootnew-host ~]# vgscan [rootnew-host ~]# vgchange -ay vg_imagesvgchange -ay会激活VG重新生成LV设备节点前提是VG内所有PV都能被识别并且元数据没有损坏。5. 最后再分享几点实操经验做LVM管理这么多年有几个心得体会写在这里给各位参考第一VG和LV的命名一定要有业务语义。vg_images、lv_upload一眼能懂但vg01、lv001这样的名字后期维护时根本想不起它对应哪个业务。生产环境上一个好的命名习惯能在故障排查时节省大量时间。第二不要把PE大小设得过大。我曾经图省事把所有VG的PE都设成64M结果后面有个业务只需要500M空间一个PE就占了64M空间浪费得很心疼。小颗粒度的PE虽然会增加元数据开销但灵活性更好。生产环境默认的4M其实已经很合理除非你明确知道为什么要改大。第三时刻关注VG剩余空间。LVM的优势在“弹性”但这个弹性是建立在VG有足够空闲PV空间的前提上。最好的做法是在业务磁盘使用率到达70%时就开始规划扩容而不是等到磁盘满了才手忙脚乱去加盘。结合计划任务定期把vgs、df -h的结果汇总一下给自己的服务器做一个空间趋势基线你会发现运维压力小很多。LVM这套工具链并不复杂核心命令就是pvcreate、vgcreate、lvcreate这三个“三板斧”。真正决定运维水平高低的往往是对底层原理的理解和那些文档里不会写的实操细节。希望这篇记录能让你少踩几个坑至少在下次磁盘告警时能从容不迫地敲出那几行命令。