云盘扩容后磁盘空间没变化?在线扩展分区与文件系统实操指南
1. 先搞清楚一个前提你说的“扩容”到底扩的是什么很多人第一次碰上这个问题时都挺懵的明明控制台提示扩容成功订单也走完了钱也扣了登录服务器执行df -h一看磁盘空间依然江山未改于是第一反应就是“阿里云是不是没给我扩”或者“是不是要重启才生效”其实这不一定是阿里云的锅更大概率是“扩了盘”但“没扩分区”和“没扩文件系统”。这里有一个非常基础但特别容易混淆的概念云磁盘上实际存在两层空间状态。第一层是云盘本身的大小相当于一块物理硬盘的容量。你在控制台看到的“XX G”、“扩容到 XX G”改的是这一层改了之后云盘硬件层面的可用容量变大了。第二层是操作系统里的分区表、分区大小、文件系统逻辑大小。操作系统真正能用的空间是由这一层决定的。你df -h读到的不是云盘硬件状态而是文件系统状态。所以一句话概括就是控制台扩容只是给硬盘“加量”但电脑里的“C盘”还没把新容量吸收进来分区表还是旧的文件系统也还是旧的自然怎么查都是老样子。还有另外一种情况要区分开就是“服务器实例规格”扩容和“磁盘”扩容。比如突然做活动访问量上来CPU和内存跑满你在控制台把ECS实例从2核4G升到4核8G这是实例规格扩容。如果只是CPU内存变了磁盘空间本来就不该有变化那不存在“扩容后磁盘无变化”这个命题。只有你确实对云盘做了磁盘容量扩容才会遇到下面这种“容量翻倍但系统没感知”的现象。所以遇到问题先确定你到底扩的是实例规格还是云盘容量。如果确认是云盘容量扩容那我们接下来要解决的才是分区和文件系统的扩展问题。2. 为什么扩容后操作系统完全感知不到新空间先看一条实际命令的输出假设原来是一块100G的云盘控制台扩容到了200G服务器上执行df -h$ df -h 文件系统 容量 已用 可用 已用% 挂载点 /dev/vda1 100G 60G 40G 60% /再看分区和块设备情况$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 253:0 0 200G 0 disk └─vda1 253:1 0 100G 0 part /注意看lsblk的输出vda 这个“盘”已经变成200G了但 vda1 这个“分区”还是100G。这个信息非常重要它直接证明了扩容已经生效到了云盘硬件层面但系统里的分区表还停留在扩容之前的状态。操作系统按分区表读分区大小所以挂载的文件系统也依然是100G。那为什么分区表没跟着变因为没有人告诉OS去更新这个状态。阿里云控制台的“扩容”操作只负责把底层块存储的容量扩大至于虚拟机内部的“分区表要不要改、怎么改、文件系统要不要跟着长、用什么工具长”这些属于操作系统的变更操作必须由你在系统内部执行。云平台如果直接去改你系统里面的分区表反而危险因为一旦自动操作遇到文件系统类型不匹配或者分区有LVMLogical Volume Manager逻辑卷管理叠层很容易把数据搞坏。这里顺便提一下几个常见的“扩容后没变化”的具体原因基本都是这个“内外部两层”模型的具体表现**原因A只是云盘变大了分区没扩大。**这是最常见的。得到lsblk中分区大小没有变化的输出就是这种情况。**原因B分区扩了但文件系统没扩大。**比如你手动用 growpart 把分区从100G扩到了200G但文件系统还是100G的ext4df -h仍旧无变化。这种情况常见于对顺序不理解的人或者文件系统类型特殊比如xfs和ext4对应的扩展工具不一样。**原因C使用了LVM逻辑卷管理物理卷、逻辑卷、文件系统三层都需要处理。**只扩了底层云盘还要pvresize把物理卷扩大再lvextend扩展逻辑卷最后resize2fs或xfs_growfs扩展文件系统缺一步空间都不会出现在df -h里。**原因DMBR分区表的限制。**如果磁盘是MBR分区表格式单分区最大只能处理2T容量超过2T后果比较麻烦可能需要转换成GPT格式。这个属于特殊情况普通场景不常见但如果你的盘非常大就要特别注意。提醒一下df -h显示的是文件系统层的容量lsblk显示的是块设备层的容量fdisk -l显示的是分区表层的容量。排查“扩容后没变化”时这三者的输出要对照着看看到底哪一层卡住了。很多人说“我已经重启了服务器但还是没变化”。重启服务器会重新读取分区表但要注意的是——重启顶多让分区表被重新加载它不会主动把你云盘新分配出来的空间自动并入现有分区和文件系统。除非你用的是阿里云的“自动扩容”功能特定情况下系统会自动执行普通手动扩容场景下重启解决不了这个问题必须手动执行扩容分区和文件系统的指令。所以别把重启当万能药。3. 实操前先判断你的数据盘是“裸盘”还是“带分区”的处理方式既然核心操作是“扩分区 扩文件系统”那第一步依然是搞清楚当前磁盘的环境。这里我单独把判断方法拎出来说因为后边动作的差异都在这一步。登录服务器后先执行$ lsblk $ df -hT $ blkid这三条命令分别回答三个问题块设备长什么样、文件系统有多大以及挂载在哪、文件系统是什么类型。比如输出可能这样$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 253:0 0 200G 0 disk ├─vda1 253:1 0 100G 0 part / ├─vda2 253:2 0 1M 0 part vdb 253:16 0 100G 0 disk └─vdb1 253:17 0 100G 0 part /data这是比较典型的场景两块云盘vda是系统盘扩容了vdb是数据盘暂时没动。你扩容的是哪块盘就去处理哪块盘。再看blkid$ blkid /dev/vda1 /dev/vda1: UUIDxxxx TYPEext4这告诉我们文件系统类型是ext4。不同文件系统类型对应不同的扩容工具ext系列ext2/ext3/ext4用resize2fsxfs 用xfs_growfsbtrfs 用btrfs filesystem resize很多人在这里翻车明明是 xfs 文件系统却拿 resize2fs 去扩工具直接报错不让操作反过来 ext4 用 xfs_growfs 也不认。工具不匹配不仅操作失败还可能带来不必要的风险。关于lsblk的形态我给你一个简单的判断标准如果磁盘设备名如vda下面直接跟着挂载点如/dev/vda1说明走的是“分区后挂载”的经典路径。如果磁盘设备名下没有任何分区子设备而整体作为一个文件系统直接挂载使用这就是“裸盘直接用”的场景有些环境初始化时直接就格式化整个/dev/vdb做文件系统不建分区表。这两种形态的处理方式不同后面操作时我会分别说明。4. 在线扩容的标准操作流程从控制台到系统内全走一遍4.1 控制台侧的扩容操作控制台这边其实没什么难度的但有几个点是很多人忽略的。登录阿里云控制台后找到“云盘”或者直接在ECS实例的“本实例磁盘”入口选择目标云盘点“扩容”按新容量大小走流程。这里有几个经验第一扩容前先把服务器关机吗不一定。阿里云的控制台通常支持在线扩容不停机的情况下直接扩容量但有部分磁盘类型比如某些高效云盘或本地盘在扩容时可能要求实例处于“运行中或已停止”状态。最稳妥的建议是操作前先看控制台上是否有“此操作不会影响您实例中运行的业务”之类的提示。如果有这个提示说明支持在线扩容。但如果你对当前环境的操作不熟或者磁盘上跑着的是数据库之类的重要应用我建议你还是挑个业务低谷期先做快照再操作避免万一出现意外情况时没法回滚。第二一定要先做快照。这是我反复踩坑后的强烈建议。虽然在线扩容本身不擦数据但你在系统内执行 growpart / resize2fs 这类的操作时如果中途断电或者误操作还是存在损坏风险的。快照相当于给你的云盘上了一道保险。不少第一次操作的人图省事不做快照结果分区表操作失败数据读不出来后悔都来不及。风险低不代表零风险尤其是带重要生产数据的盘快照的成本远低于出问题后的抢救成本。第三确认扩容后的目标容量。别在控制台一顿操作后发现容量买小了。扩容理论上只能升不能降主流云厂商都不支持在线缩容虽然现在有些类型支持容量减少但那是有严格限制的。确定好要扩到的目标大小一次性买够反复折腾又浪费时间又增加风险。4.2 系统内第一步确认扩容到货控制台扩容完成后回到服务器里跑一遍lsblk确认底层盘大小已经变化了这是首要的确认工作$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 253:0 0 200G 0 disk └─vda1 253:1 0 100G 0 part /看到vda已经是200G了但是/dev/vda1仍然是100G这就是“盘已扩分区未扩”的典型状态也正好对应着标题里说的“扩容后磁盘空间无变化”。如果你执行lsblk后看到vda依然还是100G那不用往下看了控制台扩容可能还没真正生效。比如有些操作默认在“下一时间点生效”或者订单虽走完但底层变更还没完成。遇到这种情况等一会儿再刷新看看再不行提工单查底层状态。4.3 系统内第二步扩展分区表在确认盘体已扩容到200G后就需要把分区表里的分区大小扩大让系统“承认”这块盘多出来的空间。这里我们用的核心命令是growpart。它做的事情就是把分区的终止扇区位置扩展到磁盘的最大可用扇区位置让分区大小等于磁盘大小。操作如下$ growpart /dev/vda 1这个命令的参数是设备名和分区号中间用空格隔开不是写成/dev/vda1这种合并形式。如果你把命令写成了/dev/vda1它会把“1”当作设备名去解析直接报错。执行成功的输出类似CHANGED: partition1 start2048 old: end209715199 end419430399看到“CHANGED”就说明分区表已经变更了。如果提示“NOCHANGE”说明分区大小与磁盘大小一致没有可扩的空间如果提示“failed to find partition”先确认分区号是否正确。还有的情况是磁盘扩容后growpart找不到可操作设备多半是分区表类型不兼容或者GPT/MBR格式导致后面排查部分会细说。执行growpart后再跑一次lsblk$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 253:0 0 200G 0 disk └─vda1 253:1 0 200G 0 part /分区已经是200G了下一步就是扩展文件系统了。注意growpart工具在较新的系统里通常自带属于cloud-utils-growpart包没有就自己装不同的发行版装法不同常见的是# Debian/Ubuntu $ apt install cloud-guest-utils # CentOS/RHEL 7/8 $ yum install cloud-utils-growpart有些精简镜像里可能没装这玩意提前装好别到现场才发现缺工具。补充一个特殊场景如果前面lsblk显示磁盘下面没有分区节点整块/dev/vdb直接就是文件系统无分区表形态那growpart这步就可以省掉。例子$ lsblk vdb 253:16 0 100G 0 disk /data看到这种输出说明这块盘的整个盘面都被建成了文件系统没有分区表。你把云盘从100G扩到200G后只要在文件系统层直接扩大就行不需要走分区扩展。所以判断“是否需要 growpart”就看lsblk里磁盘下面有没有“分区子项”这是非常清晰的判断标准。4.4 系统内第三步扩展文件系统分区扩大到200G之后文件系统还停留在100G所以系统内的第三步是让文件系统“吸收”掉新增的空间。这里分两种类型处理。ext4 文件系统用 resize2fs$ resize2fs /dev/vda1如果文件系统无错误输出类似resize2fs 1.46.2 (28-Feb-2021) Filesystem at /dev/vda1 is mounted on /; on-line resizing required old_desc_blocks 13, new_desc_blocks 25 The filesystem on /dev/vda1 is now 52428800 (4k) blocks long.看到类似“now ... blocks long”的输出说明文件系统扩展成功。用df -h验证$ df -h 文件系统 容量 已用 可用 已用% 挂载点 /dev/vda1 200G 60G 140G 30% /一切正常200G已经出现在我们的眼前了。需要特别注意的是resize2fs在文件系统挂载状态下执行是支持在线扩展的ext系列可以你不用停机操作。但如果文件系统里有损坏它会拒绝执行。遇到提示先跑$ e2fsck -f /dev/vda1修复完再重新resize2fs。千万别在没做e2fsck的情况下强制 resize那样很可能把文件系统搞坏。xfs 文件系统用 xfs_growfsxfs 的扩容工具是xfs_growfs它不能像resize2fs那样直接指定块设备名而是要指定挂载点$ xfs_growfs /data它会自动读取挂载点对应文件系统的当前逻辑大小并向底层可用空间扩展。输出类似meta-data/dev/vdb1 isize512 agcount4, agsize6553600 blks data blocks changed from 26214400 to 52428800看到blocks changed大部分时候就说明成功了再用df -h检查容量即可。注意xfs_growfs命令后面跟的是挂载点目录不是设备节点。写错路径它会直接提示你“is not a mount point”之类的错误。xfs 文件系统不支持缩容这也是为什么挂载 xfs 的盘在规划容量时特别要留余量的原因之一。4.5 裸盘无分区场景下的处理回到前面说的“裸盘直接用”形态也就是lsblk直接看到vdb挂载在/data底下没有分区子设备的这种情况。这种盘扩容之后不需要 growpart直接根据文件系统类型扩展即可# ext4 $ resize2fs /dev/vdb # xfs $ xfs_growfs /data因为整个磁盘设备本身就是一个文件系统云盘底层容量变大后文件系统扩展工具能直接从整块设备上看到新的可用空间。这里用resize2fs /dev/vdb而不是/dev/vdb1这一点要搞清楚别套用分区场景的命令路径。有的初始化脚本还可能在/etc/fstab里直接写了/dev/vdb对应/data那blkid输出里看到的也是/dev/vdb的UUID判断方式其实和分区形式一样只是少了“分区表”这一层概念。4.6 LVM逻辑卷特殊场景如果你的环境里用的是LVM那上面的“扩展分区然后扩展文件系统”这种顺序就变成了一个三层任务物理卷PV、逻辑卷LV、文件系统FS每一层都要处理少一步都不行。常见环境是这样的$ lsblk vdc 253:32 0 200G 0 disk └─vdc1 253:33 0 100G 0 part └─vgdata-lvdata 252:0 0 100G 0 lvm /data云盘从100G扩容到200G后你做完growpart /dev/vdc 1把/dev/vdc1分区扩到200G但此时LVM的物理卷大小还是旧值逻辑卷大小还是旧值文件系统当然也没变。你需要依次执行$ pvresize /dev/vdc1 $ lvextend -l 100%FREE /dev/vgdata/lvdatapvresize是把物理卷“吃掉”新扩出来的空间lvextend -l 100%FREE是把逻辑卷扩展到物理卷的所有可用空间。最后再根据文件系统类型扩展文件系统# ext4 $ resize2fs /dev/vgdata/lvdata # xfs $ xfs_growfs /data在LVM场景下操作有个好处整个逻辑卷的扩展过程都是在线完成的业务基本不中断这也是LVM的价值所在。但坏处是坑也更多比如lvextend时-l和-L参数的区别很容易搞混。-l的粒度是PE物理扩展块的数量级也可以直接用百分比-L的粒度是容量大小比如-L 100G表示增加100G容量。如果不小心把-l 100%FREE写成-L 100%FREE命令会直接报错%在-L下不是合法值虽说不至于损坏但也确实让人慌乱一阵。建议不熟的人先看lvs和pvs确认当前状态再执行。5. 已经扩坏了分区怎么排查和补救扩容操作本身不复杂但实际操作中总会碰到一些特殊情况。下面把高频问题整理成速查表可以直接照着排查。5.1 常见问题速查表现象可能原因解决方法df -h容量不变但lsblk盘体已变大分区表未扩展执行growpart扩展分区后再扩展文件系统growpart提示 NOCHANGE分区大小已等于磁盘大小或磁盘未真正扩容检查控制台是否有待生效变更或确认是否已执行过扩容resize2fs执行失败ext文件系统有错误或文件系统类型不是ext系列先执行e2fsck -f修复确认blkid类型后再操作xfs_growfs提示不是挂载点参数写成了设备节点而非挂载点按xfs_growfs /挂载点路径格式重试磁盘超过2T分区扩展异常MBR分区表限制考虑用parted转换GPT格式操作前一定先快照重启后空间依然没变化没有执行系统内分区/文件系统扩展按本文步骤重启不是扩容的手段5.2 关于MBR和GPT的深水区如果磁盘分区表是MBR格式当需要扩容到2T以上时会出现比较棘手的问题。MBR分区表最多支持2T的寻址空间超过这个限制分区表本身会变得不可靠。遇到容量超过2T的场景最稳妥的做法是数据备份后重新分区为GPT格式挂载或者直接在新盘上使用GPT初始化。在云服务器场景中系统盘一般在创建实例时就已自动处理为合适的分区表格式数据盘有大容量需求时建议在购买初期就选择GPT格式避免后续扩容越界带来额外操作。不过这个场景在中大型数据盘上确实会碰到比如准备把数据盘从2T扩到3T或者一上来就买了3T数据盘。growpart遇到MBR时会提示不支持超大容量或者分区扩展后文件系统无法正确识别。这时候不要硬来先把数据快照备份好然后评估是转GPT还是重新初始化。有些环境可以直接用gdisk转GPT但转换有风险最好在测试环境演练过、确认数据无碍后再在生产上操作。5.3 在线扩容时的挂载状态问题还有一类偏门场景扩容时文件系统处于异常挂载状态比如之前异常关机后系统进入了只读模式或者挂载点被人为卸载了。如果文件系统处于只读挂载状态resize2fs会提示无法在线调整因为只读状态下不能修改文件系统元数据。遇到这种情况先排查系统日志确认磁盘是正常的读写挂载状态再扩。还有一种是根分区/满了连扩容工具都跑不动的极端场景。此时建议增购一块临时数据盘做中转或者先清理一些占空间的文件把基础的操作空间腾出来再执行扩容操作。这也是为什么我一直感叹磁盘扩容这种操作应选择在业务压力小的时候做别等只剩几百M空间的时候再手忙脚乱去搞。5.4 阿里云的自动扩容工具以阿里云为例部分新的ECS实例类型在控制台磁盘扩容后会对系统盘自动执行扩容操作所以有些用户会发现“我什么都没做重启后df -h就有变化了”这是因为底层有自动脚本在接管。但这条链路依赖特定环境支持并不是所有实例都有这个能力。一旦你的实例不在自动扩容的支持范围内就必须按照上面第4节的方法手动处理。补充一个省事技巧扩容完成后如果系统里装了cloud-init而且版本比较新有时会在下次启动时尝试自动扩展根分区你可以用cloud-init status看下它是否跑了相关模块。但如果业务重要别指望自动机制宁可手动处理图个心里踏实。6. 实操心得经历多次扩容后的体会我现在处理扩容流程基本上固化成了一个习惯分享出来供你参考先确认需求再挂快照再控制台扩容回到系统里跑lsblk确认盘体变化然后判断有没有分区表层有就growpart接着blkid确认文件系统类型按类型选择 resize2fs 或 xfs_growfs最后df -h验证。熟练之后这个过程几分钟能走完但每一步都不要跳一旦跳过某一步空间一定不会出现在df -h里。关于工具链我再多一句嘴很多刚从传统物理机切到云服务器的朋友习惯用fdisk扩展分区但fdisk对在线扩展的支持并不好而且交互式的操作容易错我一般是用growpart一步到位简洁清晰出错概率低。如果不小心用fdisk改了分区表记得执行partprobe让内核重读分区表否则即使分区表改了系统也认不到。有一些老内核的场景里扩展根分区后甚至建议尽快重启一次确保内核和设备状态完全同步。最后再聊聊扩容时机。我见过不少人在业务跑得正酣的时候扩容扩容过程中控制台变化倒是没影响但执行resize2fs时由于文件系统层面要重新计算元数据CPU 和 I/O 会有短暂上升极端情况下业务写入会感受到轻微抖动。所以扩容这种“有后手”的运维操作我的原则是能做快照就做快照能错峰就错峰能少动生产就少动生产。这套原则在阿里云、其他云平台、甚至物理机环境里都通用。如果你按这套流程操作完依旧看不到空间变化大概率是底层变更没生效比如控制台流程有延迟或者分区表/文件系统类型比较特殊。这种时候就老老实实把lsblk、df -hT、blkid的输出收集齐对照上面速查表逐层排查能解决的自己解决解决不了就带着这些信息提工单效率也会高很多。