ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

VMware Ubuntu虚拟机根目录爆满?从vmdk到resize2fs全流程扩容指南

VMware Ubuntu虚拟机根目录爆满?从vmdk到resize2fs全流程扩容指南 前两天我打开那台放了很久的 Ubuntu 虚拟机准备装个编译环境结果一个df -h敲下去直接傻眼/dev/sda1挂载的根目录已经 100% 使用连 apt 清理日志都腾不出多少空间。这不是我第一次遇到 Linux 根目录爆满之前总靠删缓存硬撑这次干脆一步到位把 VMware 虚拟机的磁盘从 20GB 扩到 60GB把整套扩容流程完整梳理了一遍。这篇文章解决的就是 VMware Workstation或 Player里跑 Ubuntu 虚拟机、根目录挂在/dev/sda1、空间不够用时的扩容问题。整个过程分三段先在 VMware 层把虚拟磁盘调大再进入 Ubuntu 扩展分区最后扩展文件系统。每一步我都会解释为什么这么做也会把实际环境中容易踩的坑写清楚。如果你对 Linux 分区操作心里没底跟着这篇文章走一遍基本能顺利搞定。1. 扩容前先搞清楚你缺的到底是磁盘空间还是分区空间1.1 VMware 的磁盘大小和 Ubuntu 里的分区大小是两回事很多人第一次扩容都会栽在同一个误区里在 VMware 设置里把磁盘从 20GB 改成 60GB然后进系统一看df -h还是老样子于是以为操作失败了。其实 VMware 改的是虚拟磁盘的大小相当于给虚拟机换了一块更大的物理硬盘而 Ubuntu 看到的/dev/sda1是这块硬盘上的分区分区不会因为你把硬盘调大就自动变大。打个比方你给房子扩建了地基但没砌新的隔墙房间面积当然不会变。想让根目录真正变大必须在虚拟机里把分区和文件系统也一起扩了三件事缺一不可。所以完整的扩容链路是VMware 层扩大.vmdk虚拟磁盘文件的上限容量分区层让/dev/sda1分区使用新增加的空间文件系统层让 ext4/xfs 文件系统扩展到整个分区1.2 用三条命令给系统做个体检动手之前先把当前状态摸清楚。登录 Ubuntu 后依次执行df -h df -i lsblkdf -h看的是文件系统使用率df -i看 inode 使用率lsblk看磁盘和分区结构。我见过不少根目录爆满的情况其实不是空间满了而是 inode 耗尽文件删不掉也写不进症状和磁盘满几乎一样。所以先确认根因别盲目扩容。典型输出长这样NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 20G 0 disk ├─sda1 8:1 0 19G 0 part / ├─sda2 8:2 0 1K 0 part └─sda5 8:5 0 1G 0 part [SWAP]从这个输出能看出几个关键信息磁盘总大小 20GB/dev/sda1是根分区后面还有一个扩展分区sda2里面套着 swap 逻辑分区sda5。这种布局在 MBR 分区表的老式 Ubuntu 安装里非常常见也是扩容时最容易出问题的布局后面我会专门讲。1.3 判断你的分区表类型MBR 还是 GPT以及是否 LVM接着用 fdisk 确认分区表类型sudo fdisk -l /dev/sda如果看到Disklabel type: dos说明是 MBR看到Disklabel type: gpt则是 GPT。这两类分区表的操作细节略有不同但主流扩容思路一致后面的章节里我会分别说明注意事项。另外还要留意lsblk的输出里有没有 LVM 的影子。如果根目录不是直接挂在/dev/sda1上而是挂在/dev/mapper/ubuntu--vg-ubuntu--lv这种路径下说明系统用了 LVM。LVM 的扩容流程和普通分区完全是两套逻辑我放在最后一节单独讲。这里先记住一句话本文主流程适用于根目录直接挂在 /dev/sda1 上的情况先对照 lsblk 看清楚再往下走。2. 动刀之前先把备份和快照这关过了2.1 快照会锁住 vmdk扩容前必须合并掉VMware Workstation 的快照功能很好用但它有一个和扩容直接冲突的特性只要虚拟机存在快照对应的 vmdk 就会被锁定磁盘扩展按钮通常是置灰的或者操作时会直接报错。这其实不是 bug而是 VMware 的保护机制——快照链里的每个 vmdk 都有依赖关系贸然扩展会让整个快照链失效。所以如果这个虚拟机之前打过快照先打开虚拟机 - 快照 - 快照管理器把快照全部删除让磁盘回到单一 vmdk 的状态。删除快照的过程本质上是把快照中的数据合并回父磁盘文件需要一定时间耐心等它跑完。合并完成后确认快照列表为空再继续下一步。2.2 关闭虚拟机并复制一份 vmdk 才是真正的兜底快照虽然删了但扩容这个操作本身还是有风险尤其是后面涉及手动改分区表的时候一旦中途断电、敲错参数系统可能直接起不来。所以我的习惯是关机状态下把整个虚拟机目录复制一份到另一块硬盘或者至少把正在使用的 vmdk 文件复制出来。复制 vmdk 要注意如果虚拟磁盘被分割成了多个 2GB 的小文件需要把所有的-s001.vmdk、-s002.vmdk这些分片一起复制缺一个都不行。另外复制前确认虚拟机是已关机状态而不是已挂起。挂起状态恢复时会有内存状态文件直接拿这种 vmdk 做备份恢复出来可能不一致。复制完先简单验证一下在 VMware 里用备份文件新开一个虚拟机如果能正常启动到登录界面说明备份可用这时候再对原虚拟机动刀心里踏实得多。2.3 哪些场景可以跳过备份如果你只是拿这台虚拟机测试某个软件坏了随时能重新装那备份环节确实可以省。我自己折腾全新环境时也经常懒得复制 vmdk直接把快照删了就开始扩容。但只要是里面存了代码、数据库、或者配置了很久的开发环境我强烈建议花几分钟做一次备份。扩容操作做错一次的成本远远高于备份需要的时间。另外提醒一句如果虚拟机里跑了数据库服务备份 vmdk 前最好先把服务停掉保证文件系统处于干净状态。3. VMware 层面扩容把物理硬盘变大3.1 图形界面改磁盘大小注意按钮置灰的原因这一步在 VMware Workstation 里很简单确认虚拟机处于关机状态。打开虚拟机设置 - 硬件 - 硬盘。在右侧找到磁盘大小把数值改大比如从 20GB 改成 60GB。点击确定等待系统提示扩展完成。如果你开着虚拟机操作会发现磁盘大小这一项是置灰的无法修改。这就是 VMware Workstation 的限制之一不支持在线扩大磁盘容量。ESXi 里可以热添加但 Workstation/Player 不行老老实实关机。如果按钮能点但点完没反应多半是快照没删干净回到上一章检查快照管理器。还有一点扩容时填的是总容量不是增加多少。比如原来是 20GB想多加 40GB直接填 60GB别填 40GB。3.2 命令行用 vmware-vdiskmanager -x 扩容如果你习惯命令行操作或者需要批量处理虚拟机可以用 VMware 自带的vmware-vdiskmanager。Windows 主机上完整命令示例C:\Program Files (x86)\VMware\VMware Workstation\vmware-vdiskmanager.exe -x 60GB D:\VMs\Ubuntu\Ubuntu.vmdk命令参数解释-x 60GB指定扩容后的目标容量单位必须是 MB 或 GB且大小写敏感。后面跟的 vmdk 路径要用英文引号包起来因为路径里通常有空格。如果 vmdk 被拆成了多个分片不需要手动处理这个工具会自动完成合并与扩展。执行过程中会输出进度看到Grow: 100% done才算成功。整个过程同样要求虚拟机处于关机状态而且不能有其他程序占用 vmdk 文件。3.3 这一步做完为什么 Ubuntu 里还是老样子无论是用图形界面还是命令行扩容完成后再启动 Ubuntu执行lsblk或者fdisk -l通常会发现磁盘总容量已经是 60GB但/dev/sda1依然只有 19GB 左右挂载点使用率还是老样子。这是预期内的结果不用慌。因为 VMware 只是把硬盘变大了硬盘上的分区表还没来得及利用新空间。接下来要做的是在 Ubuntu 里把/dev/sda1这个分区扩展让它覆盖到新增的空间。这一步是整个扩容过程中最关键、也最容易出错的环节。4. 在 Ubuntu 里扩展分区把新空间划给 /dev/sda14.1 重启确认新磁盘容量并判断 sda1 是否最后一个分区扩容后第一件事是重启虚拟机让系统重新扫描 SCSI 设备。虽然有些场景下可以通过echo 1 /sys/class/scsi_device/...在线重扫但实测中最省心、最没有副作用的还是直接sudo reboot。重启后执行sudo fdisk -l /dev/sda看到Disk /dev/sda: 60GB之类的输出说明 VMware 层扩容已经生效。接着重点看/dev/sda1后面的分区布局如果sda1是磁盘上最后一个分区后面没有sda2、sda5之类的分区那么恭喜你可以直接用 growpart 一路扩展流程最顺畅。如果sda1后面还有扩展分区和 swap 分区情况会复杂一些跳到 4.4 节先处理 swap 再回来。为什么这么在意最后一个分区因为扩展分区本质上是把分区的结束位置往后挪如果目标分区后面还紧跟着别的分区直接扩展会把后面的分区覆盖掉。growpart 工具会自动把结束位置停在下一个分区起始扇区之前但可用的新空间就会被隔开无法并入根分区。4.2 growpart最推荐的分区扩展方式Ubuntu 里扩展分区我的首选是 growpart它是cloud-guest-utils包的一部分设计目标就是安全扩展分区。先安装sudo apt update sudo apt install -y cloud-guest-utils然后执行sudo growpart /dev/sda 1注意/dev/sda和1之间有空格这是 growpart 的固定参数格式设备名空格分区号。执行成功的输出类似CHANGED: partition1 start2048 old: size... end... new: size... end...growpart 的原理是读取分区表中该分区的起始扇区然后把结束位置扩展到下一个分区之前或磁盘末尾整个过程不会删除分区、不会重建分区所以相当安全。对新手来说这比手动 fdisk 稳妥太多。如果输出NOCHANGE说明分区已经是最大状态可能是 VMware 层没扩容成功或者磁盘空间确实没变化。回到第 3 章排查。4.3 手动 fdisk 扩展分区应急方案和风险控制有些老系统装不上 cloud-guest-utils或者你不想装额外工具这时可以用 fdisk 手动操作。但请务必谨慎我只在特殊场景下推荐手动方式。操作步骤如下sudo fdisk /dev/sda进入交互界面后输入p打印分区表记下/dev/sda1的 Start 扇区通常是2048。输入d删除分区输入1选择删除sda1。输入n新建分区分区号默认1First sector 输入刚才记下的2048Last sector 直接回车使用默认值磁盘末尾。如果提示检测到 ext4 签名问是否移除签名输入N保留。输入w写入分区表。这里有几个致命细节First sector 必须和原来完全一致。填错哪怕一个扇区系统都可能直接无法启动。让 Last sector 使用默认值的前提是sda1后面没有其他分区。如果后面有 swap默认值会覆盖到 swap 上造成数据丢失。fdisk 删除分区只是删除分区表条目并没有抹掉数据但一旦中途断电或误操作恢复难度会非常大。所以我的结论是能装 growpart 就用 growpartfdisk 手动法只作为理解工具原理的手段。真到了必须手动操作的时候操作前一定把fdisk -l的输出截图或记下来尤其是 Start 扇区和分区顺序。4.4 如果 /dev/sda1 后面还有 swap 分区先处理 swap回到 1.2 节那个典型布局sda1根分区 sda2扩展分区 sda5swap。这种情况下新增的磁盘空间在sda5后面growpart 无法直接把它并入sda1因为中间隔着一个扩展分区。我有两种应对思路思路一新增空间单独建分区挂载到/var、/home等目录。这种方案风险最低但根目录本身没有变大只是把部分目录挪到了新分区严格来说不算根目录扩容。思路二删掉 swap 分区和扩展分区把sda1扩展到整个磁盘末尾再用 swap 文件替代原来的 swap 分区。如果你想真正扩大根目录这是更彻底的做法。操作前先确认 swap 的状态swapon --show cat /etc/fstab | grep swap确保你的 swap 是/dev/sda5这类独立分区然后在 fdisk 中依次删除/dev/sda5、/dev/sda2再按照 4.3 节的方式删除并重建/dev/sda1让它的结束位置覆盖整个磁盘。最后重启执行resize2fs。swap 分区没了之后用 swap 文件重建sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile然后在/etc/fstab里加一行让开机自动挂载/swapfile none swap sw 0 0swap 文件相比 swap 分区的好处是位置灵活以后调整大小不需要再碰分区表。这个方案我实操过多次只要严格按照顺序操作数据安全是有保障的但如果你对 fdisk 交互不熟我建议还是先备份再操作。4.5 GPT 分区表的额外注意事项如果你的fdisk -l显示Disklabel type: gpt那扩容思路和 MBR 一样但有两个额外注意点。第一growpart 对 GPT 分区表的支持很完善强烈建议直接用它避免手动 fdisk。手动 fdisk 删除重建 GPT 分区时默认会生成新的分区 GUID少数依赖分区 GUID 的系统组件可能会受影响。操作前可以用sgdisk --backuppartition.gpt /dev/sda备份分区表。第二MBR 分区表对单块磁盘有 2TB 的容量上限。如果你扩容后的虚拟磁盘超过了 2TBMBR 无法使用超出的空间需要把分区表转换成 GPT。这个转换操作有风险建议另开专题学习日常虚拟机扩容很少遇到。5. 扩展文件系统根目录才会真正变大5.1 ext4 用 resize2fs 在线扩容分区扩展完成之后文件系统还没有意识到分区变大了。此时查看df -h/dev/sda1的大小可能还是原来的值。这是因为文件系统的元数据记录的是旧的块数量需要执行扩展文件系统的命令。Ubuntu 默认根文件系统是 ext4命令很简单sudo resize2fs /dev/sda1resize2fs会把文件系统扩展到整个分区。它支持在线扩容也就是说根目录挂载状态下可以直接执行不需要重启、不需要进入救援模式。这一点对扩容根目录来说太重要了因为根目录理论上没法用umount卸载在线扩容几乎是唯一方便的路径。执行成功的输出大概是这样resize2fs 1.46.5 (30-Dec-2021) Filesystem at /dev/sda1 is mounted on /; on-line resizing required old_desc_blocks 1, new_desc_blocks 2 The filesystem on /dev/sda1 is now 13106900 (4k) blocks long.看到now ... blocks long就说明文件系统已经扩好了。5.2 xfs 要用 xfs_growfs别搞混如果你的 Ubuntu 在安装时选择了 XFS 文件系统那上面这条命令就不适用了。XFS 的扩展命令是xfs_growfs而且它的参数是挂载点不是设备名sudo xfs_growfs /注意这里传的是/不是/dev/sda1这是和resize2fs最大的区别。搞混的话会直接提示参数错误。判断文件系统类型可以用lsblk -f /dev/sda1FSTYPE 一列会显示ext4还是xfs。不过 Ubuntu 默认安装走 ext4只有手动分区选择过 XFS 才会出现这种情况。5.3 扩容后的验证、UUID 与 fstab扩展完成后执行df -h lsblkdf -h里根目录的大小应该已经变成新值比如从 19GB 变成 59GB。再用blkid确认一下sudo blkid /dev/sda1你会发现/dev/sda1的 UUID 没有变化。这是因为 growpart 只是修改了分区的结束位置resize2fs 只是修改了文件系统的块数量两者都不会重写 UUID。UUID 没变就意味着/etc/fstab里按 UUID 挂载的配置不需要改动开机后系统依然能正常找到根分区。这也是为什么扩容流程里不需要动/etc/fstab的原因。很多人担心分区变了之后挂载失效实际完全不会。6. 扩容过程中的常见坑与排查思路6.1 VMware 提示需要删除快照或扩展按钮置灰这个我在 2.1 节提过但值得再强调一次。如果你在 VMware 设置里发现磁盘大小改不了或者点了扩展按钮后弹出快照相关提示不用怀疑肯定是快照链还没清理干净。去快照管理器把所有快照删掉等合并完成再重新设置磁盘大小。还有一种情况是虚拟机处于挂起状态虽然看起来像是关机但 VMware 仍旧认为磁盘被占用。处理方式是选择开机再关机让它彻底关停然后再扩容。6.2 growpart 不生效或报错growpart 报错常见有两种一种是unexpected input多半是参数格式错了记住sudo growpart /dev/sda 1设备和分区号之间必须有空格写成/dev/sda1反而不对。另一种是NOCHANGE表示分区已经达到最大值。先检查 VMware 层是否真的扩容成功用fdisk -l看磁盘总容量如果总容量已经变大但 growpart 说没法扩展很可能就是 4.4 节讲的情况——sda1后面还隔着扩展分区。这时要么先处理 swap要么改用新增空间挂载目录的方案。6.3 resize2fs 后 df -h 没变化这种情况我也遇到过排查顺序通常是先看分区有没有变大sudo fdisk -l /dev/sda如果/dev/sda1的大小还是原来的说明分区扩展环节没成功回到第 4 章。再看文件系统状态sudo resize2fs /dev/sda1会提示文件系统已经是多少块如果显示 The filesystem is already X blocks long说明文件系统已经扩展过了df -h应该已经显示新值。如果分区没变、文件系统也没变在 VMware 层扩容后忘记重启过一次内核仍然使用旧的分区信息。重启再重新执行 growpart 和 resize2fs。另外如果扩容前根目录已经满到 100%执行 resize2fs 时可能会因为文件系统元数据需要临时空间而报错。这种情况下先做一轮清理腾出几个 GB 空间再扩容成功率更高。6.4 根目录快满时的临时急救先清理再扩容扩容不是解决根目录爆满的唯一手段而且扩容前往往需要先腾出一些操作空间。我常用的急救清理手段sudo apt clean sudo apt autoremove sudo journalctl --vacuum-time3dapt clean清理的是/var/cache/apt/archives里的安装包缓存经常一下子能腾出几个 GB。journalctl --vacuum-time3d把三天前的系统日志归档删除日志文件积累也是根目录空间的天敌。另外用du -h --max-depth1 / 2/dev/null | sort -h快速扫一遍根目录下哪些目录占空间最大重点检查/var/log、/tmp、/var/lib/docker这类容易膨胀的目录。清理之后再执行扩容整个流程会顺滑很多。6.5 如果用的是 LVM扩容流程完全不同最后特别提醒一种情况很多 Ubuntu Server 安装时默认启用 LVM你会发现lsblk输出里有sda1但根目录挂载点却是/dev/mapper/ubuntu--vg-ubuntu--lv这样的路径。这时候用 growpart 和 resize2fs 是无效的LVM 扩容需要的是另一套命令sudo pvresize /dev/sda1 sudo lvextend -r -l 100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv先用pvresize让物理卷感知到扩容后的分区大小再用lvextend -r把逻辑卷扩展到卷组剩余的全部空间-r参数会自动扩展文件系统不需要手动执行 resize2fs。这也是 LVM 在运维中受欢迎的原因——扩展空间非常灵活。但如果你的系统没有 LVM这套流程千万不要乱套。就我个人这几年的使用感受来说扩容最不容易出错的路径永远是确认布局、备份、关机扩 vmdk、growpart、resize2fs 这五步走完。遇到sda1后面跟着 swap 的情况先处理 swap 再扩展别硬来。只要每一步执行完都用lsblk和df -h验证一下状态基本就不会有意外。希望这篇记录能帮你少走点弯路。
返回列表