虚拟机磁盘满了,最快的解决思路是“先清理、后扩容”:先用日志清理、包管理器缓存清理和du命令定位大文件这三板斧释放空间,若仍不够,再通过虚拟机管理平台在线扩容磁盘并扩展分区。
为什么虚拟机磁盘说满就满?先分清“真满”还是“假满”
很多人遇到报错第一反应是“扩容”,但多数情况下磁盘满不是容量规划失误,而是运行期垃圾堆积的结果,你登录服务器执行df -h,看到/dev/mapper/centos-root使用率100%,这时候先别急着加硬盘,有些“满”是假象。
常见原因有三类:
- 日志文件失控:Nginx、Tomcat、Docker容器日志,单个能长到几十GB。
- 包管理器缓存残留:
yum clean all和apt autoclean很少有人定期做,缓存越积越多。 - 临时文件与旧内核:
/tmp下未清理的临时文件,以及升级后残留的多余内核,都会悄悄占空间。
还有个容易被忽略的点:inode耗尽。df -h显示还有余量,但df -i显示100%,这是因为小文件数量超过上限,常见于消息队列积压或邮件队列堆积,判断方法很简单,两条命令都看一眼。
三步快速清理:从定位到释放的实操路径
第一步:直击大文件,不要全盘翻找
在根目录执行du -ah --max-depth=1 / | sort -rh | head -20,直接从大到小排列,一秒锁定元凶,更精确的定位用ncdu(需要先yum install ncdu或apt install ncdu),交互式界面比du更直观。
重点检查这几个路径:
/var/log/var/lib/docker(如果跑容器)/home下各用户的隐藏文件/opt和下的应用产物/usr/local
第二步:清理日志,但别用rm -rf了事
直接删除正被进程占用的日志文件,空间不会释放,因为句柄还开着,正确姿势是:
cat /dev/null > /var/log/messages
或者用> /var/log/nginx/access.log,保留文件本身,想从根源控制日志大小,修改/etc/logrotate.conf,把日志轮转周期改为daily,保留份数设为7,这样单日日志撑爆磁盘的情况会大幅减少。
第三步:清理包管理器和Docker遗留物
- CentOS/RHEL系:
yum clean all && yum autoremove - Ubuntu/Debian系:
apt autoclean && apt autoremove - Docker环境:
docker system prune -a会删除所有悬空镜像和停止的容器,能回收的空间相当可观,如果确认关闭容器,docker system prune --volumes可以顺带清理未挂载的卷。
旧内核清理也是常被忽略的一项uname -r查看当前内核,然后用yum remove删除列表中其他版本(Ubuntu用dpkg --list | grep linux-image配合apt purge)。
虚拟机磁盘扩容的两种主流操作路径
内部清理后如果使用率仍然在80%以上,就该考虑扩容了,操作路径取决于你用的虚拟化平台,这里拆开说。
VMware vSphere/Workstation环境下Linux虚拟机扩容
行业共识认为,先扩虚拟磁盘,再进系统扩展分区,顺序不能反,具体步骤是:
- 关闭虚拟机(支持热添加的场景可跳过)。
- 编辑虚拟机设置,调整硬盘大小,比如从100GB扩到200GB。
- 开机进入系统,用
lsblk确认新空间是否已识别。 - 如果是LVM卷组,直接
lvextend -l +100%FREE /dev/mapper/centos-root,然后(XFS文件系统)或xfs_growfs /
resize2fs /dev/mapper/centos-root(ext4)。 - 如果不是LVM,而是/dev/sda3这样的普通分区,用
growpart /dev/sda 3再resize2fs /dev/sda3。
整个过程风险等级中等,操作前建议对虚拟机做快照,万一执行resize2fs时断电,至少能回滚。
KVM/libvirt虚拟化下的扩容思路
如果你的环境是KVM,virsh blockresize --path /var/lib/libvirt/images/xxx.qcow2 --size 200G 虚拟机名可以支持在线扩容,不过qcow2格式扩容之后,宿主机上的文件系统不一定自动感知客户机的分区变化,同样需要进虚拟机内部执行分区扩展。
云服务器(简米云、酷番云) 的场景类似但入口不同,控制台里“磁盘扩容”后在控制台点“云盘扩容”,本质上也是对块设备的resize操作,云服务商提供的操作文档里会明确说是需要“创建快照后在线扩容”。
用swap文件救急:不扩容也能扛一阵
临时加一个swap文件,能缓解内存压力但不是释放磁盘空间,不过有一种特殊情况:如果你确认只是内存不足导致进程OOM,与磁盘满无关,可以跳过这项,这里提到它的原因是在无法立刻扩容且磁盘有余量的情况下,临时swap文件能避免服务宕机,为你争取维护窗口期:
dd if=/dev/zero of=/swapfile bs=1M count=2048 chmod 600 /swapfile mkswap /swapfile swapon /swapfile
给虚拟磁盘做“瘦身”:清理快照与精简磁盘
完成扩容后,还有一步很多人没做检查虚拟机快照,VMware和KVM的快照会以差量文件形式占额外空间,旧快照堆积会让磁盘占用虚高,在vSphere中右键虚拟机,进入“快照管理器”,确认不需要的旧快照点“删除”。
KVM的qcow2格式还有个特性:删除内部文件后,qcow2文件本身不会自动缩小,因为块未释放,需要执行
virt-sparsify --in-place /var/lib/libvirt/images/xxx.qcow2来回收空间,这个操作能把几十GB的空闲空间释放回宿主机,另外确认磁盘接口是virtio-scsi而非virtio-blk,前者对在线扩容的支持更友好。
虚拟机磁盘满了相关的常见问题解答
虚拟磁盘扩容后df -h显示容量没变化,是没生效吗?
大概率是分区没做扩展,扩容虚拟磁盘只是给“房子”加了面积,但“隔断墙”(分区表)还没来得及动,检查lsblk看/dev/sda整体容量是否变大了,如果变大了说明底层已识别,执行分区扩展命令即可,XFS文件系统用xfs_growfs /,ext4用resize2fs /dev/sdaX,执行完成后df -h就会显示新容量。
频繁清理日志太麻烦,有什么一劳永逸的办法吗?
从根上解决有几个方向:一是配置logrotate全局策略,让所有日志按天轮转并保留固定份数;二是将日志目录单独挂载一块数据盘,即使日志涨满也不会影响系统盘;三是部署日志采集服务,把日志实时推送到远端存储,本地只留近几日日志,多数情况下考虑成本,方案二最常见给/var/log挂一块独立磁盘,彻底和系统盘隔离。
用LVM精简置备(Thin Provisioning)有什么坑吗?
瘦置备的好处是,你给虚拟机分配了200GB,但实际只占用60GB,宿主机上节省空间,坏处是,后续磁盘利用率高了之后,如果未启用自动回收(discard),文件删除后空间不会返还宿主机,需要确保虚拟机内启用了fstrim定时任务(systemd timer),或者用fstrim -av手动执行,才能让瘦置备的回收机制正常工作。瘦置备适合测试环境,生产环境建议禁用自动精简,用厚置备延迟置零更稳妥。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/618473.html




