虚拟机Linux磁盘扩容全攻略:从VMware到文件系统一步到位
发布时间:2026/10/8 2:54:15 锦皓数字建站

在虚拟机里跑Linux我最怕看到的画面不是服务挂了而是df -h刷出来一行红字容量直接100%。前阵子VMware里一台Ubuntu服务器跑着跑着突然写不进日志nginx报错、定时任务全卡住一查就是根分区被占满了。当时第一反应是清理垃圾但清完发现底层的虚拟磁盘本身已经不够用——这时候最彻底的解法就是给虚拟机做磁盘扩容。很多朋友以为“虚拟机Linux磁盘扩容”就是把VMware的硬盘调大然后开机完事实际上这只是一个起点。完整链路涉及三层虚拟化层把虚拟磁盘调大→ 分区层让分区表用上新空间→ 文件系统层让文件系统真正吃到容量任意一层漏了都会出现“硬盘明明调大了但系统里还是老容量”的迷惑现象。这篇文章就按这个链路把每一步讲透同时把容易翻车的细节和我实战中踩过的坑一并放出来适合所有在用VMware、VirtualBox或KVM跑Linux的运维和开发朋友参考。1. 先给磁盘做“体检”搞清楚满在哪、当前是什么分区方案扩容之前一定要先诊断这不是走流程而是为了避开后面的大坑。很多人在没弄明白分区表类型、文件系统类型、是不是LVM的情况下直接下手结果扩容到一半发现方式和预期完全不一样甚至把数据搞丢。1.1 用df和du定位真实占用情况第一步永远是df -Th注意带上-T参数可以顺带显示文件系统类型df -Th输出里能看到所有挂载点、容量、已用、可用和文件系统类型。我先看到/dev/sda2挂载在/ext4容量占满。这里要区分两种情况一种是磁盘本身还有剩余空间只是某个目录特别大另一种是分区容量确实到了上限比如根分区只有20G但数据已经19.8G。如果磁盘整体还有空间但某个分区满了优先用du找到大目录sudo du -sh /var /home /tmp /var/log /opt /usr 2/dev/null | sort -h我在生产环境里最常见的大户是/var/logjournald日志不清、/var/lib/docker容器镜像和overlay2堆积、/home下的构建缓存。实在挤不出空间再考虑扩容因为扩容虽然是常规操作但能少一次就少一次。1.2 判断分区布局与文件系统类型看结构用lsblk -f这个命令会输出块设备树、挂载点、文件系统类型和UUIDlsblk -f这是判断“接下来走哪条路”的关键。常见情况有三种非LVM、单一根分区比如/dev/sda2直接挂载到/扩容目标是把sda2分区扩大再扩文件系统。LVM逻辑卷结构输出里能看到─ubuntu--vg-ubuntu--lv之类实际挂载在/的设备可能是/dev/mapper/ubuntu--vg-ubuntu--lv这时候分区层只要pvresize然后把逻辑卷扩大再扩文件系统。多分区表MBR/GPTfdisk -l可以判断分区表类型。再配合pvdisplay、vgdisplay、lvdisplay确认LVM的信息sudo pvdisplay sudo vgdisplay sudo lvdisplay1.3 为什么这个预判能避免白折腾因为Linux扩容在不同场景下命令完全不同ext4文件系统用resize2fsxfs要用xfs_growfs两者混用大概率报错。不是LVM的话分区层要用growpart或fdisk手动扩分区LVM则必须执行pvresize顺序错了逻辑卷也看不到新空间。分区表是MBR还是GPT会直接影响fdisk操作时的警告和步骤GPT分区表在删除重建时容易出现备份表不同步的问题。我见过一位朋友在非LVM的Ubuntu Desktop上直接敲lvextend系统提示找不到逻辑卷他还以为是命令没安装。其实只要lsblk -f看一眼是sda2直挂还是mapper设备就全明白了。所以这一步别省两分钟的事后面能省两个小时。2. 虚拟化层扩容先把“虚拟硬盘”本身做大确认好结构后第二步是回到宿主机把虚拟磁盘的总容量调大。这一步不涉及Linux内部操作但在不同的虚拟化平台上细节略有差异。2.1 VMware Workstation/Player的扩展操作VMware系列我用得最多操作路径如下关闭虚拟机必须关机VMware不支持在开机状态下扩展虚拟磁盘。右键虚拟机 → 设置 → 硬盘 → 实用工具 → 扩展。输入目标磁盘大小注意是“最终总大小”不是“增加多少G”。比如原来是40G想加20G这里填60G。等待VMware完成扩展完成后点确定。如果是纯命令行环境可以用vmware-vdiskmanagervmware-vdiskmanager -x 60GB /path/to/vmdisk.vmdk-x表示扩展磁盘目标大小写清楚单位。这个命令扩展VMDK在虚拟机离线状态下执行。2.2 VirtualBox与KVM/libvirt的对应操作VirtualBox扩展比较简单路径是菜单栏“文件” → “虚拟介质管理器” → 选中虚拟磁盘 → “属性” → “大小”拖动滑块或直接输入新容量点应用。VirtualBox对VDI格式支持在线调整但我仍习惯在关机状态下操作稳一点。KVM/libvirt环境用qemu-imgqemu-img resize /var/lib/libvirt/images/ubuntu.qcow2 40Gqcow2格式同样要注意目标总大小。调整完虚拟机的XML不需要改因为磁盘大小由镜像文件控制。部分图形化界面virt-manager也能在磁盘属性里直接调整。2.3 扩容前务必做的两件事快照与备份说到这必须强调在虚拟化层调大磁盘之前先拍快照或备份分区表。VM虚拟磁盘的调整虽然极少失败但一旦失败往往伴随分区表不可读而对生产环境来说最贵的不是磁盘空间是恢复可用状态的时间。VMware里直接在开机前为虚拟机拍一个快照VirtualBox可以在“生成备份”里做当前状态备份。哪怕是个人测试机我也建议花这一步。另一个容易被忽略的是宿主机的磁盘剩余空间。扩展虚拟磁盘时VMware会在宿主机上为新增长度分配块如果宿主机本身磁盘快满了扩展可能完成得极其缓慢甚至失败。我自己遇到过宿主机只剩1.2G空间强行扩展20G卡了半小时最后报错的情况。所以先看一眼宿主机的df -h留足余量再动手。3. 分区层处理让Linux内核“看见”新增空间虚拟化层做完绝大多数人会直接开进系统看容量——然后疑惑“怎么还是老样子”。这很正常因为虚拟磁盘变大了但Linux的分区表里分区的边界还停留在原来的位置系统不会自动把新空间并进已有分区。这一步要处理的是分区表。3.1 新空间为什么不会自动生效用lsblk看一下就能发现规律磁盘整体大小已经变成60G但/dev/sda2分区还是40G后面多出来的20G显示为未分配空间。内核虽然知道磁盘变大了却不知道这个“新区域”应该属于哪个分区。所以需要把分区的物理边界往后推才能让分区用满新空间。方案有两种一是用growpart自动调整分区边界推荐优先二是用fdisk手动删除分区再重建操作得当也可靠但风险略高。3.2 growpart一步扩展分区边界推荐在Ubuntu等系统上先安装工具sudo apt update sudo apt install -y cloud-guest-utils然后执行sudo growpart /dev/sda 2注意命令格式是growpart [磁盘] [分区号]中间没有/dev/前缀。执行后可以看到类似“CHANGED: partition2 start... old size... size...”的输出。如果磁盘是GPT分区表growpart可能会提示需要修正备份分区表确认即可。执行完用lsblk检查分区大小是否已经变化。growpart的本质是自动计算新的结束扇区并改写到分区表全过程不需要手工输入数字能最大程度避免人为失误。3.3 手动fdisk删除重建分区的老办法有些老系统没装growpart又不方便联网安装这时可以用fdisk手动操作。过程不复杂但有一个红线重建分区时起始扇区必须和原来一致。sudo fdisk /dev/sda交互过程如下p查看当前分区表记下目标分区的“起始扇区”和“结束扇区”。d删除分区如果只有一个分区就是2按实际输入分区号。n新建分区分区号保持原来一致。起始扇区直接回车使用默认值——这时默认值通常就是刚才删除前的起始扇区只要确认没变就行。结束扇区直接回车使用默认值最大可用空间或输入新的大小。如果提示是否移除签名signature选N不删除分区上的文件系统标记。w保存退出。保存后用partprobe /dev/sda刷新分区表或直接重启。这里一定要强调fdisk法最危险的步骤就是重启后分区UUID变了。MBR分区表删除再重建时分区系统ID和UUID可能变化如果/etc/fstab里用UUID挂载很可能开机直接进emergency mode。所以不是万不得已我优先用growpart因为它只改结束边界不重算UUID。3.4 LVM场景的专属分区处理路径如果lsblk -f看到的是LVM结构比如Ubuntu Server默认的ubuntu--vg-ubuntu--lv那分区层只需做一件事把物理卷扩展到新分区边界上。sudo pvresize /dev/sda2这里假设/dev/sda2是LVM物理卷所在分区。执行后pvdisplay或pvs能看到Physical Volume的PE数和大小已经变化。如果分区本身还没扩展比如growpart没跑那pvresize扩的也只是分区内已有空间所以LVM场景下正确的顺序是growpart /dev/sda 2扩展分区边界pvresize /dev/sda2让物理卷感知新空间lvextend -l 100%FREE /dev/mapper/xxx把空闲空间全部分配给逻辑卷扩容文件系统下一步这里有个小细节lvextend可以只加一部分而不是全加比如lvextend -L 10G /dev/mapper/xxx。生产环境里我喜欢预留一部分空间在卷组里方便以后某个卷紧急扩。不过测试环境直接100%FREE最省事。3.5 分区表操作遇到的警告与应对扩分区时最常见的一个提示是GPT分区表的警告GPT PMBR size mismatch或Not all of the space available to /dev/sda appears to be used...。遇到这种提示别慌通常意味着分区表和实际磁盘大小不一致。最稳妥的做法是用gdisk或parted修复。用gdisk修复很简单sudo gdisk /dev/sda进入交互界面后输入w写回分区表它会自动修正备份GPT表然后退出。这里注意gdisk的w操作会直接保存前提是你确认当前分区表内容没毛病。4. 文件系统层收尾ext4和xfs必须分开处理分区边界扩展完了逻辑卷也大了但文件系统本身还不知道最后一步是让文件系统用满新空间。这一步的坑最多因为ext4和xfs的操作命令完全不同。4.1 ext4系一条resize2fs在线搞定Ubuntu Desktop和很多Debian系默认用ext4。对于ext4直接在线执行sudo resize2fs /dev/sda2如果分区结构是LVM设备路径就是/dev/mapper/xxxsudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lvresize2fs默认会扩展到设备的最大可用空间输出会显示文件系统从多少block扩到了多少block。ext4的好处是支持在线扩容挂载状态下执行没问题这也是我用它做根分区时的首选。4.2 xfs系只能用xfs_growfs且不支持缩容红帽系RHEL/CentOS/Rocky默认用xfs很多朋友会下意识敲resize2fs然后收到“resize2fs: Bad magic number in super-block”之类的报错这时候应该用xfs专用命令sudo xfs_growfs /注意xfs_growfs的参数是挂载点不是设备路径。也可以指定设备sudo xfs_growfs -d /dev/mapper/centos-root-d表示扩大到最大值xfs在线扩容没问题但xfs不支持缩容这个特性在规划磁盘大小时要想好一次性给够空间避免后面要缩回来。下面这个表每次遇到都值得贴出来参考文件系统扩容命令是否支持在线是否支持缩容ext4resize2fs /dev/xxx支持支持离线xfsxfs_growfs /挂载点支持不支持btrfsbtrfs filesystem resize max /支持支持swapswapoff后重新mkswap否可重做4.3 LVM与文件系统的完整组合流程演示以一台Ubuntu ServerLVM ext4为例完整命令串如下方便直接套用# 1. 扩展分区边界 sudo growpart /dev/sda 2 # 2. 让物理卷感知新的分区大小 sudo pvresize /dev/sda2 # 3. 逻辑卷使用卷组中所有剩余空间 sudo lvextend -l 100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv # 4. 扩展文件系统到最大 sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv # 5. 验证 df -Th如果是RHEL系xfs把第4步换成sudo xfs_growfs /注意逻辑卷设备路径可能带--比如ubuntu--vg-ubuntu--lv这是因为卷组和逻辑卷名里含有-时会转义成双连字符以lsblk显示为准。4.4 顺带处理swap分区扩容很多虚拟机初始只有2G的swap跑编译或大数据任务时经常被打满。swap扩容和根分区扩容是两条路径但可以一起做。思路是先建一个新的swap分区或用swap文件启用后移除旧分区。简单的方法是swap文件无需动分区表sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile持久化写入/etc/fstabecho /swapfile none swap sw 0 0 | sudo tee -a /etc/fstab如果想复用原来的swap分区流程是swapoff /dev/sda3→fdisk删除旧swap分区重建出更大分区或growpart→mkswap /dev/sda3→swapon /dev/sda3同时记得更新/etc/fstab里的UUID。swap分区扩容中间有一次交换空间清零对内存吃紧的机器要挑业务低峰操作。5. 扩容后的验证与翻车实录扩容完成并不意味着结束必要的验证和几个高频翻车点我专门放在这节讲。毕竟我这些经验都是真金白银换来的。5.1 怎么确认扩容真正成功判断成功的标准有三个全部满足才算完成lsblk -f # 分区大小正确 df -Th # 挂载点容量显示新大小 mount | grep / # 挂载参数正常UUID没有漂移如果df里显示的还是旧容量最大可能是文件系统层没执行到位如果lsblk里分区大小没变说明分区层没执行成功。按这个顺序倒查能快速定位问题在哪一层。5.2 “resize2fs: Device or resource busy”是什么意思我见过不少朋友扩容LVM时卡在这里。其实报错的意思是设备忙文件系统无法安全调整。ext4在挂载状态下通常能在线扩容但某些情况比如挂载选项带nouser_xattr等特殊参数或对根文件系统时仍可能提示busy。处理办法先确认是不是命令用错了设备比如拿/dev/sda2在LVM环境扩设备其实应该是mapper路径。如果是普通分区且能卸载可以启动到live环境离线resize但虚拟机场景重启又快没必要非得在线。如果确实要在线检查挂载参数必要时先mount -o remount,rw /dev/xxx /再试。实际上对根分区最省事的方式是确保分区层已经扩好直接用resize2fs在线扩绝大多数ext4都没问题。这个报更多出现在xfs文件系统被错误执行resize2fs报错类型不一样但同样让人头大。5.3 GPT备份表不一致导致的认盘异常有次我用fdisk手动扩展GPT分区保存时报了一堆警告重启后系统差点起不来原因就是备份GPT表还保留旧结构。应急修法是用gdisk修复sudo gdisk /dev/sda进入后不用改任何设置直接输入w它会自动重建备份GPT表。如果系统卡在grub界面还能用e2fsck修复文件系统。这也就是为什么我前面强调growpart优先——它对GPT的处理更规范手动fdisk虽然能成但每多一次手工操作就多一分风险。5.4 扩容完成后fstab失效的经典问题MBR分区表删除重建之后分区的UUID可能变了/etc/fstab还按旧UUID找设备开机直接失败。遇到这种情况先用live系统或紧急模式把根分区只读挂载起来查看blkid拿到新UUID然后更新/etc/fstab。更好的办法是从一开始就避免如果fstab里用的是UUID而不是设备路径/dev/sda2手动fdisk重建分区前一定要把原UUID记下来重建后用mkswap -U或直接保留原分区类型重新指定UUID。ext4可以这样保留sudo tune2fs -U 原UUID /dev/sda2但我真实建议还是优先growpart它不会改变分区UUID省掉这整个风险。5.5 一些实操中的小习惯与体会我个人的习惯是给虚拟机扩容前先用lsblk -f disk_layout.txt把分区结构存一份档真的出问题时能对照找回原始布局。扩容顺序一定是“先快照、再虚拟化层、再分区层、再文件系统层”每一步用对应的命令验证一次不要一股脑全部跑完。很多朋友一次跑完所有命令中间某一步失败后反而不知道去哪排查。最后再分享一个小技巧如果虚拟机里跑的是Docker扩容后记得看下/var/lib/docker占用docker的overlay2层经常占用超出预期。有时候“磁盘满了”不是容量不够而是镜像和日志堆积——先清理再扩容能让扩容这件事的效果维持更久。扩容不是万能药量出为入、定期清理才是虚拟机Linux长期稳定运行的核心。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。