1. 从一块“塞满的盘”说起
搞Linux运维的朋友,十有八九都经历过这种时刻:磁盘满了,应用直接宕掉,跑过去一看,df -h输出红字,/分区 100%,一堆日志和临时文件把/var堆到一点不剩。更头疼的是,当初装系统时图省事,所有空间全给了根分区,想扩容只能找停机窗口,拆机加盘,流程长还容易出岔子。我自己最早那几年就吃过这个亏,线上数据库的磁盘告警,扩容花了大半夜,从那时候起我就意识到,Linux 磁盘管理不能只靠“分区格式化挂载”三板斧,得把 LVM(Logical Volume Manager,逻辑卷管理)这套东西真正吃透,用它来解决动态扩容和灵活调整的痛点。
这篇文章以“Linux 磁盘管理与 LVM”为主线,不讲虚的,直接拆解底层概念、常用命令、完整实操流程,再附上我踩过的坑和排查经验。适用于刚接触 Linux 服务器管理的初学者,也适合正在准备运维面试、想把磁盘这块知识补全的中级学习者。看完这篇文章,至少你能做到:拿到一块新盘知道怎么分区、格式化、挂载;对现有 LVM 布局能一眼看懂;遇到扩容、缩容、快照这类需求,不再心里发怵。
2. 磁盘管理基本功:分区、格式化与挂载
2.1 分区工具怎么选:fdisk vs parted vs lsblk
Linux 下磁盘分区工具很多,但我实际用下来,日常维护主力还是fdisk和parted两个,lsblk则是我每次动手前必看的“地形图”。
fdisk:最经典的工具,交互式操作,适合 MBR 分区表,单盘容量 2TB 以下时够用。操作逻辑简单:n新建、d删除、w保存退出,用熟了全程盲打都行。parted:专门应对 GPT 分区表和大容量磁盘,2TB 以上必须用它,支持交互式和命令行两种模式。实际生产环境里,我更喜欢直接用parted /dev/sdb --script mklabel gpt这种非交互写法,方便写进脚本里批量操作,避免人工输入出错。lsblk:查看磁盘和分区关系的利器,树状结构一目了然。它能显示每个块设备的大小、挂载点和类型,排查“这块盘对应哪个设备名”的时候,比fdisk -l输出更直观。
选型背后的逻辑很简单:分区表类型决定上限。MBR 只能用四个主分区,GPT 几乎不受限,而且 GPT 是现在新服务器的默认选择。运维工作中,除非是接手老机器,必须兼容旧 BIOS,否则我强烈建议一律 GPT + parted。
2.2 格式化到底做了什么
分区只是把一块物理盘划分成多个独立的“空间段”,真正让它能被写入数据,必须做文件系统,也就是俗称的“格式化”。这个动作的本质是在分区上初始化一套数据结构,比如 inode 表、块组描述符、超级块等,内核通过这些结构来管理文件读写。
常用命令是mkfs.ext4 /dev/sdb1或mkfs.xfs /dev/sdb1,加-t可以指定类型确认,例如mkfs -t ext4。具体选 ext4 还是 xfs,我建议看场景:
| 文件系统 | 优点 | 适用场景 |
|---|---|---|
| ext4 | 兼容性最强,支持在线扩容和缩容(前提是未挂载时缩容也费劲) | 通用业务、老系统迁移 |
| xfs | 性能好,大文件处理强,扩容只需xfs_growfs | 大数据、数据库、高并发存储 |
| btrfs | 支持快照、压缩、校验和 | 实验环境、特殊存储需求 |
一个很容易被忽略的点:xfs 不支持在线缩容,只能扩不能缩。如果你预期后续要缩容,一开始就别选 xfs。这是个花了大代价换来的教训,我有一次在日志服务器上用了 xfs,后来空间分配不合理想缩容,只能迁移数据重建文件系统,相当痛苦。
2.3 挂载与永久挂载
格式化完的分区,要挂载到目录树里才能用。临时挂载用mount /dev/sdb1 /data,重启就失效;永久挂载得写进/etc/fstab。为什么不能只写mount?因为重启后,系统不会自动恢复未登记的挂载关系。
/etc/fstab每一行的格式是:设备名、挂载点、文件系统类型、挂载选项、dump 备份标记、fsck 检查顺序。实际操作我会建议别直接写设备名,比如/dev/sdb1,而是写 UUID,因为重启后设备名可能漂移,但 UUID 是稳定不变的。用blkid可以查到分区的 UUID。
典型的 fstab 行:
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults 0 2写完 fstab 后,务必用mount -a测试一遍。别问我为什么强调这个——我有一次改完 fstab 没验证,重启后系统因为挂载失败进不去,只能进 rescue 模式改回来,冷汗都下来了。加nofail选项可以在挂载设备不存在时跳过,避免这种问题,但核心还是写完后先测。
3. LVM 设计哲学:为什么你需要它
3.1 传统分区的瓶颈与 LVM 的解法
传统分区方案下,一个分区的边界一旦定死,想调整就只能删了重建,这在生产环境等于灾难。LVM 的核心思路是把物理磁盘抽象成“资源池”,你不再直接面对物理分区,而是面对逻辑卷,逻辑卷的大小可以动态调整,底层空间来自一个或多个物理磁盘聚合出的“池子”。
拿生活化例子类比:传统分区像一套固定隔间的出租房,每个隔间的墙都浇筑死了,想扩大某间屋,只能砸墙重砌;LVM 像一个仓库,里面堆着可移动货架,你随时可以调整某个区域的边界,甚至可以临时把隔壁区域的货架挪过来用。这个灵活性,就是 LVM 存在的最大价值。
LVM 的分层结构是理解一切命令的钥匙:
- PV(Physical Volume,物理卷):一块磁盘或分区,标记后就能被 LVM 使用。
- VG(Volume Group,卷组):多个 PV 聚合形成的资源池,相当于“总仓库”。
- LV(Logical Volume,逻辑卷):从 VG 里划出的具体空间,是最终格式化挂载使用的对象。
- PE(Physical Extent):PV 上的最小存储单元,默认 4MiB,类似文件系统里的块。LV 的分配就是按 PE 个数来计算的。
3.2 LVM 里的关键术语与数据流向
数据写入路径是这样的:进程 → LV → VG → PE → PV → 磁盘扇区。理解这个链路后,你就明白为什么 LVM 可以跨磁盘——一个 VG 里可以加入多块 PV,LV 的数据可以散布在多块物理盘上。
但这也带来一个隐患:如果某个 PV 故障,且它是 VG 里唯一的数据源,整个 VG 就危险了。所以生产环境往往用 RAID 或硬件阵列把多块盘先做成整列,再在其上建 LVM,这样既拿到 LVM 的灵活性,又保住数据可靠性。
pvcreate、vgcreate、lvcreate这三个命令是 LVM 的核心入口。pvcreate /dev/sdb1把分区初始化为 PV;vgcreate vg_data /dev/sdb1 /dev/sdc1把两个 PV 放入卷组;lvcreate -L 100G -n lv_data vg_data从卷组划出逻辑卷。每步完成后,用pvs、vgs、lvs三个简写命令查看状态,基本能覆盖 90% 的排查场景。
4. LVM 实操全流程:从初始化到扩容
4.1 场景设定与初始化操作
为了把流程串起来,我们假设一个常见需求:机器上新增了两块 500GB 的物理盘/dev/sdb和/dev/sdc,要把它们组合成一个卷组,划分出逻辑卷挂载到/data下,用于存放业务文件。
第一步,确认磁盘识别状态:
lsblk输出中能看到/dev/sdb和/dev/sdc,都是裸盘状态,未分区未格式化。
第二步,创建 PV:
pvcreate /dev/sdb /dev/sdc这里有个细节:可以直接把整个裸盘设为 PV,也可以分区后再设。用裸盘省事,但如果盘上已有分区表或数据痕迹,pvcreate会拒绝执行并要求加-f强制,这个操作有破坏性,生产环境务必先确认盘内数据不需要了。
第三步,创建 VG:
vgcreate vg_data /dev/sdb /dev/sdc默认 PE 大小是 4MiB,不需要动。用vgdisplay vg_data可以看到 VG 总大小和剩余空间,我这里应该显示约 931GB。
第四步,创建 LV 并格式化挂载:
lvcreate -L 800G -n lv_data vg_data mkfs.xfs /dev/vg_data/lv_data mkdir -p /data mount /dev/vg_data/lv_data /data这里故意留了约 131GB 空闲,后面扩容演示就是用这部分剩余空间。
把挂载写入 fstab 时,建议使用逻辑卷的路径而非/dev/vg_data/lv_data,因为系统启动时 LVM 的激活顺序由lvm2服务保证,直接写逻辑卷路径是安全的。更稳妥的做法是用blkid查逻辑卷的 UUID 后写入,两种方式我都在用,实测都没问题。
4.2 LV 在线扩容的正确姿势
扩容是 LVM 最吸引人的功能,但许多人第一次操作时容易搞错顺序。核心原则:先扩 LV,再扩文件系统,顺序反了会报错或者导致内核没有刷新识别新大小。
比如要把lv_data从 800G 扩到 900G,命令是:
lvextend -L +100G /dev/vg_data/lv_data或者直接指定扩容后大小:
lvextend -L 900G /dev/vg_data/lv_data然后看文件系统类型,xfs 用:
xfs_growfs /dataext4 用:
resize2fs /dev/vg_data/lv_dataxfs_growfs的参数是挂载点,而resize2fs的参数是设备路径,这个区别几乎每天都有新手问。xfs 不能在挂载状态下缩容,所以它对扩容方向特别友好;ext4 缩容必须在卸载状态下用resize2fs,而且有风险,千万别在挂载状态强行缩。
4.3 缩容与迁移:真到用时方知难
缩容比扩容复杂得多,因为要保证数据安全,必须先减小文件系统,再减小 LV。ext4 的流程是:
- 卸载文件系统:
umount /data - 检查文件系统:
e2fsck -f /dev/vg_data/lv_data - 缩文件系统:
resize2fs /dev/vg_data/lv_data 500G - 缩逻辑卷:
lvreduce -L 500G /dev/vg_data/lv_data - 重新挂载:
mount /dev/vg_data/lv_data /data
每一步都要确认成功再走下一步,特别是第 3 步和第 4 步的大小必须严格一致,不然逻辑卷比文件系统小,数据会被截断,那是灾难级的故障。
xfs 没有缩容能力,想缩小就只能备份数据、重建 LV、恢复数据。所以我再次强调,创建 xfs 文件系统前,先想清楚未来是否有缩容需求。
至于 LV 迁移,用pvmove /dev/sdb /dev/sdc可以将数据从一块故障盘迁移到另一块,这在磁盘预警后做热替换非常有用。我经历过的场景是某块物理盘 SMART 报警,但还没完全挂掉,就是靠pvmove把数据搬到新盘,然后vgreduce移除旧 PV,全程业务无感知。
4.4 LVM 快照:回滚的秘密武器
LVM 快照不是物理复制数据,而是基于 COW(Copy-On-Write,写时复制)机制。创建快照时,系统只记录原卷的元数据状态,实际数据不动;后续原卷有修改时,旧数据才被复制到快照区。因此快照空间占用远小于原始数据量,但快照区一旦被写满,快照就会失效,这点必须提前留出充足空间。
常用操作:
lvcreate -L 20G -s -n snap_lv_data /dev/vg_data/lv_data这里的-s表示 snapshot,-n指定快照名。回滚时,卸载原 LV,用lvconvert --merge /dev/vg_data/snap_lv_data把快照合并回去。这个操作我一般在业务发版前做一版快照,万一出问题,几十秒就能回到发布前状态,大大缩短回滚时间。
需要注意:快照期间,原卷的每次写入都会触发 COW,如果业务写入量大,快照区会迅速膨胀,一定要监控快照使用率,满了立即删除或扩容。
5. 常见故障排查与避坑手记
5.1 挂了但没挂上:fstab 与 UUID 问题
这是 Linux 磁盘管理最经典的坑。系统启动时报错进不去,多半是/etc/fstab里的设备名失效了。排查思路分三步:开机时查看日志确认哪行失败,进 rescue 模式把 fstab 里对应的行注释掉,正常启动后再用blkid核对 UUID 重新挂载。
还有一种情况是设备存在但挂载点写错,比如挂载点没创建就直接mount,系统会报 “mount point does not exist”。解决方案简单:先mkdir -p再挂。别笑,新手阶段我至少犯过三次。
5.2 pvdisplay 看不到 PV?先看分区类型
执行pvcreate成功,但重启后pvdisplay找不到 PV,这种情况通常和分区类型标识有关。如果 PV 建在分区/dev/sdb1上,分区 ID 应该是8e(Linux LVM 类型),用fdisk -l可以确认。如果是裸盘建 PV,不存在这个问题。
但更常见的原因是/etc/lvm配置文件里filter过滤规则设置了accept列表,把某些设备排除了。排查时用vgscan -v查看扫描过程,能定位到被过滤的设备。
5.3 快照空间不足导致锁死
快照写满后,原 LV 不会立刻损坏,但相关 I/O 会变慢甚至卡住。处理方式:立即删除快照lvremove -f /dev/vg_data/snap_lv_data,释放 COW 压力,原卷数据不受影响。如果业务需要保留快照,就得在创建时预留 20% 以上的空间,并且设置监控告警。
我在 KVM 虚机上做过一次实验,快照区只有 2G,业务写入高峰期半小时就写爆,当时数据库写入明显变慢,丢了两分钟监控数据,后续再也没敢把快照区设得太小。
5.4 常用排查命令清单
| 场景 | 命令 | 说明 |
|---|---|---|
| 查看空间 | df -h | 看挂载点使用率 |
| 查看磁盘 | lsblk | 看块设备树状结构 |
| 查看分区表 | fdisk -l | MBR/GPT 分区信息 |
| 查看 UUID | blkid | 获取设备唯一标识 |
| 查看 PV | pvs/pvdisplay | 物理卷状态 |
| 查看 VG | vgs/vgdisplay | 卷组状态和大小 |
| 查看 LV | lvs/lvdisplay | 逻辑卷状态 |
| 扫描 LVM | vgscan/lvscan | 重新识别 LVM 设备 |
| 查看挂载 | findmnt | 确认挂载关系 |
这些命令建议背下来,面试和技术答辩基本都会问到,平时排查也足够用了。真正的高手不是记住每个参数,而是能在出问题时快速定位是哪一层出了问题——是物理层、分区层、LVM 层,还是文件系统层。
5.5 性能问题的隐雷:LVM 不是万能的
最后说一个容易被忽视的坑。LVM 的条带化(striped)功能可以提升并发读写性能,但配置起来相当谨慎。lvcreate -i 2 -I 64k -L 100G vg_data表示在两个 PV 间做条带化,条带大小 64KiB。这种配置对顺序读写有明显帮助,但一旦其中一个 PV 故障,整个 LV 的数据都可能不可用,可靠性反而下降。
我个人的建议是:生产环境优先做 RAID 底层,LVM 只做逻辑管理;个人测试环境可以随意折腾条带化实验。性能不够,别急着上 LVM 条带,先去查文件系统挂载参数、IO 调度器、缓存策略,这些往往影响更大。
6. 面试高频题与实战复盘
很多人在准备 Linux 面试时会发现,磁盘管理和 LVM 是必考模块。最常被问的几个问题,这里直接给出我认为最到位的答法思路。
问题:请解释 PV、VG、LV 的关系,并说明 PE 的作用。
答题思路:先讲分层结构——PV 是物理卷,由物理磁盘或分区构成;多个 PV 组成 VG,VG 是资源池;LV 从 VG 划出,是对外可见的逻辑卷。PE 是 LVM 最小的分配单位,默认 4MiB,LV 的大小就是 PE 数量的整数倍。用一句话总结:PE 是 LVM 的“砖块”,PV 是“砖场”,VG 是“仓库”,LV 是“隔出来的房间”。
问题:怎么给根分区扩容?
答题思路:先说根分区能否扩,取决于当初是否用了 LVM。如果是标准分区且空间不足,要么迁移数据到新盘,要么用分区调整工具(如 gparted 的 LiveCD 方式),但风险高;如果根分区在 LVM 里,新增一块 PV 加入 VG,然后lvextend扩根分区对应的 LV,再扩容文件系统即可。关键在于向面试官展示你能分清楚“标准分区”和“LVM”两种场景的差异。
问题:xfs 和 ext4 的区别?
答题思路:xfs 适合大文件高并发,扩展性强,但不支持缩容;ext4 兼容性好,支持缩容但操作复杂。如果磁盘容量规划不明确,优先 ext4;如果确定未来只增不减且重视性能,选 xfs。回答时可以补一个实际案例,比如数据库日志目录用的是 xfs,普通业务数据目录用的是 ext4。
问题:在线扩容时,为什么必须先扩 LV 再扩文件系统?
答题思路:LV 是逻辑边界,文件系统是数据管理边界。如果先扩文件系统,文件系统尝试使用超出 LV 限定的空间,会立刻报错;如果只扩 LV 不扩文件系统,文件系统感受不到新增空间,也无法使用。顺序其实是系统设计上的强约束,理解了这一层,就不会再犯顺序颠倒的错误。
7. 实际操作中的一些个人习惯
文章快写完了,按惯例分享几个我个人多年养成的习惯,算不上什么标准答案,但确实帮我避免过几次事故。
第一,每次改 LVM 或 fstab 之前,先cp /etc/fstab /etc/fstab.bak.日期,改完用mount -a验证,确认没问题再继续。备份这件事在服务器管理里永远不嫌多,特别是牵涉到启动流程的文件,多一份备份就多一条退路。
第二,生产环境新建 LV 实际使用量不要超过 80%。LVM 虽然能在线扩容,但扩的时候需要 VG 有足够空闲空间,如果整块盘都分配完,再想扩就只能加新盘。预留 20% 的空间,既是性能冗余,也是操作空间。这个比例我在数据库服务器上甚至放到 30%。
第三,监控快照使用率。创建完快照后,我会挂一条 cron 或者写进现有监控脚本里,每小时检查一次/dev/mapper下的快照空间,超过 70% 立即处理。快照写满这件事不发生则已,一发生就是生产事故,预防成本比处理成本低太多了。
第四,熟悉 rescue 模式。不管用什么发行版,都值得花半小时练习进入 rescue 模式的路径。因为磁盘和 LVM 出问题时,很多时候系统起不来,你连命令都打不了,再强的知识也用不上。能把系统救起来,才有后续的修复操作。
Linux 磁盘管理和 LVM 是运维工程师的基本功,也是系统设计里最容易被低估的一环。很多人觉得“能用就行”,等真正空间不够、磁盘报警的时候,才后悔当初没好好规划。趁现在手上环境还能折腾,多建几个 PV、多切几个卷、多做几次快照回滚练习,这些操作熟练了,以后真遇上故障,心里就有底了。