Docker根分区爆满?CentOS LVM在线扩容实战指南

发布时间:2026/10/21 12:41:26
Docker根分区爆满?CentOS LVM在线扩容实战指南
1. 从一次告警说起为什么容器主机的根分区总是不够用凌晨两点监控面板上那条代表磁盘使用率的曲线又一次顶到了95%的红线。登录到宿主机上一看df -h的输出里/dev/mapper/centos-root这个挂载点已经吃掉了将近全部空间而 Docker 的镜像层、容器可写层、日志文件还在源源不断地往里写。这种场景对跑容器的人来说几乎算是必修课——你以为给虚拟机分了200G很宽裕结果半年不到就被镜像和日志啃得干干净净。这篇文章要聊的就是这个具体问题在 CentOS 系的宿主机上当 Docker 把根分区撑爆之后怎么给/dev/mapper/centos-root做在线扩容。它不是什么高深技术但涉及 LVM 逻辑卷、文件系统、分区表这几层概念任何一层搞错顺序都可能把数据搞没。适合两类人看一类是刚接手容器运维、第一次遇到根分区告警的新手另一类是知道大概流程但每次操作都心里发虚、想彻底搞明白为什么是这个顺序的从业者。我先把结论摆出来方便你对照自己的情况如果卷组VG里还有剩余空间扩容就是三步——扩逻辑卷、扩文件系统、验证全程在线不用重启如果卷组也没空间了那得先扩物理卷所在的分区或加新磁盘这一步才是真正容易出事的地方。下面我会把这两种情况拆开讲透包括每一步背后的原理、命令的每个参数在干什么、以及我自己踩过的几个坑。在动手之前有一个前置动作必须做而且我要把它放在最前面强调先确认你的文件系统类型。CentOS 7 默认是 XFSCentOS 6 默认是 ext4这两者的扩容命令完全不同XFS 只能扩不能缩ext4 可扩可缩。用df -T或者lsblk -f一眼就能看出来。我见过有人照着 ext4 的教程去操作 XFSresize2fs直接报错还好没造成损坏但白白折腾了半小时。提示任何磁盘操作之前哪怕是在线扩容这种相对安全的操作也请先对关键数据做一次快照或备份。LVM 本身很稳但稳不等于零风险尤其是涉及分区表修改的时候。2. 动手前必须搞懂的 LVM 三层结构很多人扩容失败或者不敢操作根源在于没理清 LVM 的分层关系。我用一个生活化的类比来讲把 LVM 想象成一套积木收纳系统。最底层是物理卷PVPhysical Volume它可以是整块硬盘也可以是硬盘上的一个分区。这相当于你手里的一块块积木。往上一层是卷组VGVolume Group它把多个物理卷合并成一个大池子相当于把所有积木倒进一个大收纳箱。最上层是逻辑卷LVLogical Volume它从卷组这个池子里切出一块来用相当于你从收纳箱里取出一些积木搭成一个具体的造型——/dev/mapper/centos-root就是这么一个逻辑卷。理解了这个结构扩容的逻辑就顺理成章了你要给 root 扩容本质上是要从卷组这个池子里再切一块空间给 root 这个逻辑卷。所以第一步永远是问一句池子里还有没有剩的空间用vgs命令就能看到卷组的剩余空间输出里的VFree那一列就是答案。如果VFree大于0恭喜你扩容非常简单直接跳到第3节。如果VFree是0说明池子也空了你得先往池子里加积木——要么扩底层分区要么加新硬盘这就是第4节的内容。这里有个细节值得说清楚/dev/mapper/centos-root这个路径里的centos是卷组名root是逻辑卷名。不同系统上卷组名可能不一样有的叫clCentOS 8 默认有的叫vg00之类。所以你在敲命令前先用vgs和lvs确认一下自己系统上的实际名字别照抄教程里的centos。我见过有人直接复制粘贴结果报volume group not found还以为是命令错了。另外补充一个判断依据用lsblk看整个块设备树能直观地看到磁盘、分区、LVM 之间的父子关系。比如你会看到sda下面有sda2sda2下面是centos-root和centos-swap。这个树状图对理解空间从哪来、往哪去特别有帮助建议每次操作前都看一眼。3. 卷组还有余量时的在线扩容全流程这是最常见也最简单的情况。假设vgs显示VFree还有 50G你想把这 50G 全给 root操作分三步走。3.1 第一步扩展逻辑卷本身命令是lvextend。有两种写法一种是指定要增加多少一种是指定扩到多大。我个人更推荐增加多少的写法因为不容易算错lvextend -L 50G /dev/mapper/centos-root如果你想把卷组剩余空间全部用上可以用-l 100%FREElvextend -l 100%FREE /dev/mapper/centos-root这里的-L后面跟的是绝对大小50G 表示增加50G-l后面跟的是逻辑扩展单元LE数量100%FREE是个百分比写法意思是把剩余空间全拿走。这两个参数别混用-L和-l是互斥的。执行完这一步逻辑卷的容器变大了但文件系统还没变大。这是新手最容易困惑的点为什么lvextend成功了df -h看还是原来的大小因为逻辑卷和文件系统是两个层次的东西逻辑卷是地文件系统是地上盖的房子你只是把地扩了房子还没跟着扩。3.2 第二步扩展文件系统这一步要分文件系统类型。先确认类型df -T /dev/mapper/centos-root如果是 XFS用xfs_growfs注意它接的是挂载点而不是设备路径xfs_growfs /如果是 ext4用resize2fs它接的是设备路径resize2fs /dev/mapper/centos-root这两个命令的参数差异是很多人踩的坑。xfs_growfs后面跟/挂载点resize2fs后面跟/dev/mapper/centos-root设备。记混了就会报错。我自己的记忆方法是XFS 的growfs里带个fs它关心的是文件系统挂在哪所以给挂载点resize2fs关心的是哪个设备所以给设备路径。好消息是这两个命令都支持在线扩容不需要卸载文件系统不需要重启业务无感知。这也是 LVM XFS/ext4 组合在生产环境受欢迎的核心原因。3.3 第三步验证结果扩容完一定要验证别嫌麻烦df -h / lvsdf -h看文件系统层面是否真的变大了lvs看逻辑卷层面的大小。两个数字应该对得上。如果df没变八成是第二步命令用错了或者没执行。注意xfs_growfs默认会把文件系统扩到逻辑卷的当前大小不需要指定目标大小。如果你只想扩一部分得用-D参数指定块数但生产上几乎没人这么干都是直接扩满。4. 卷组也满了扩分区还是加硬盘如果vgs显示VFree为0说明卷组这个池子也空了。这时候有两条路扩底层分区如果分区后面还有未分配空间或者加新硬盘。前者风险高后者更稳妥。4.1 先判断底层分区后面有没有空闲空间用fdisk -l /dev/sda看分区表。重点看sda2的结束扇区是不是紧挨着磁盘末尾。如果sda2后面还有未分配的空闲扇区理论上可以扩分区。但这里有个大坑如果sda2是 LVM 分区扩它需要先删掉再重建分区表项而删除分区这个动作本身有风险。具体来说流程是fdisk /dev/sda进入交互用d删除sda2再用n新建一个分区起始扇区必须和原来完全一致结束扇区设到磁盘末尾最后把分区类型改回8eLinux LVM。这个操作只要起始扇区填错一位整个 LVM 就废了。所以我一般不建议新手在生产环境这么干除非你确认有完整备份。扩完分区后还要让 LVM 重新识别pvresize /dev/sda2然后vgs就能看到VFree有空间了接着回到第3节的流程。4.2 加新硬盘是更稳的选择如果宿主机还能挂新盘虚拟化环境直接加一块虚拟磁盘就行这是最省心的方案。假设新盘是/dev/sdbpvcreate /dev/sdb vgextend centos /dev/sdb第一行把新盘初始化成物理卷第二行把它加入centos这个卷组。执行完vgs就能看到卷组变大了VFree有空间了。然后照旧走lvextendxfs_growfs的流程。这个方案的好处是全程不碰现有分区表风险极低。坏处是需要有物理或虚拟磁盘资源。在云主机上很多平台支持在线扩容云盘扩完之后在系统里用growpart把分区撑大再pvresize也能达到同样效果。4.3 两种方案的风险对比方案操作复杂度风险等级是否需要停机适用场景扩底层分区高高否但风险大分区后有连续空闲空间且无备份条件加新硬盘低低否有可用磁盘资源推荐首选云盘在线扩容中低否云主机环境我个人的排序是加新盘 云盘扩容 扩分区。扩分区永远是最后选项因为它对操作精度要求太高一个扇区填错就是灾难。5. 那些教程不会告诉你的坑这一节是我这些年实际操作中攒下来的经验很多是文档里不会写的。第一个坑lvextend成功但df没变别慌。这是正常的因为你只扩了逻辑卷没扩文件系统。新手经常在这里以为操作失败了然后反复执行lvextend结果把空间重复分配。记住lvextend和xfs_growfs或resize2fs是两步缺一不可。第二个坑XFS 不能缩小。如果你哪天想给 root 缩容XFS 是做不到的只能备份数据、重建文件系统。所以扩容时别一次性扩太猛虽然扩多了不浪费LVM 层面可以再调整但 XFS 的只增不减特性意味着你扩出去的空间很难收回来。ext4 虽然支持缩容但也必须先卸载文件系统在线缩容是不存在的。第三个坑/dev/mapper/centos-root和/dev/centos/root是同一个东西。前者是设备映射器路径后者是 LVM 的符号链接路径指向同一个逻辑卷。用哪个都行但脚本里建议统一用/dev/mapper/开头的更直观。第四个坑Docker 的日志和镜像才是空间杀手。扩容只是治标治本要配置 Docker 的日志轮转。默认情况下容器的 json 日志文件会无限增长一个跑久了的容器日志能吃掉几十G。在/etc/docker/daemon.json里加上{ log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 } }这样每个容器日志最多占 300M能省下大量空间。改完要重启 Docker 服务且只对新创建的容器生效老容器得重建。第五个坑pvresize之后vgs没变化。有时候扩完分区执行pvresizevgs里的VFree还是0。这通常是因为分区表变了但内核没重新读取。用partprobe /dev/sda强制内核重读分区表再执行pvresize就好了。第六个坑操作顺序不能乱。正确的顺序永远是先扩底层分区/物理卷→ 再扩卷组 → 再扩逻辑卷 → 最后扩文件系统。从下往上一层一层来。反过来操作必然失败。这个顺序背后的逻辑是上层空间来自下层下层没空间上层就无从谈起。6. 一套可以抄作业的完整命令清单最后我把整个流程整理成可以直接复制的命令序列分两种场景。执行前请把centos和/dev/sda2替换成你自己系统上的实际名称用vgs和lsblk确认。场景A卷组有余量最常见# 1. 确认文件系统类型和卷组余量 df -T / vgs # 2. 扩展逻辑卷增加50G或全用剩余空间 lvextend -L 50G /dev/mapper/centos-root # 或 lvextend -l 100%FREE /dev/mapper/centos-root # 3. 扩展文件系统二选一看类型 xfs_growfs / # XFS resize2fs /dev/mapper/centos-root # ext4 # 4. 验证 df -h / lvs场景B卷组也满了加新硬盘# 1. 确认新盘 lsblk # 2. 创建物理卷并加入卷组 pvcreate /dev/sdb vgextend centos /dev/sdb # 3. 确认卷组已扩大 vgs # 4. 后续同场景A的第2、3、4步 lvextend -l 100%FREE /dev/mapper/centos-root xfs_growfs / df -h /场景C扩底层分区高风险谨慎# 1. 查看分区表和空闲空间 fdisk -l /dev/sda # 2. 交互式操作d删除sda2n新建起始扇区必须一致t改类型为8ew保存 fdisk /dev/sda # 3. 让内核重读分区表 partprobe /dev/sda # 4. 扩展物理卷 pvresize /dev/sda2 # 5. 后续同场景A提示场景C的第2步是整个流程里唯一可能造成数据丢失的操作。如果你对fdisk交互不熟强烈建议先用一台测试机练手或者直接选场景B。生产环境里能用加盘解决的就别动分区表。我个人在实际操作中的体会是LVM 这套东西设计得其实很优雅扩容本身并不难难的是搞清楚当前处于哪一层、哪一层还有空间。把vgs、lvs、lsblk、df -T这四个命令用熟每次操作前先看一眼基本就不会出问题。真正需要警惕的永远是分区表那一层其他步骤都是可以放心在线执行的。另外扩容只是应急把 Docker 日志轮转和镜像清理做成定期任务才是让根分区不再告警的根本办法。