先查进程占用和快照,再按磁盘格式做TRIM/UNMAP或离线压缩,最后确认精简置备和文件系统扩容是否到位。
为什么删了文件,虚拟机占用的空间却没降下来
很多人第一次遇到这种情况会愣住:在虚拟机里rm了一个几十GB的日志文件,df -h看容量确实少了,可宿主机上的vmdk、qcow2、vhdx文件大小纹丝不动,业内专家指出,这属于虚拟化存储的正常现象,不是系统坏了。
原因在于虚拟磁盘是一层“翻译”,虚拟机里的文件系统以为数据删掉了,但虚拟磁盘文件只负责记录块有没有被写过,不会主动把“空块”还给底层存储,想真正释放空间,得让三层都点头:文件系统层、虚拟磁盘层、底层存储层。
下面按常见场景拆开讲,每一步都给可验证的命令或操作路径。
虚拟机删除文件后磁盘空间没变小怎么办
这是最常见的疑问,先别急着压缩磁盘,按顺序排查三个点。
第一点:确认文件是真删了,还是进了回收站或快照
Windows虚拟机里删除文件默认进回收站,回收站不清空,空间当然不动,Linux桌面环境也可能有类似机制,更隐蔽的是快照:VMware、Hyper-V、KVM都支持快照,快照链会保留旧数据块。
- VMware:检查“快照管理器”,删除不需要的快照,等合并任务完成。
- Hyper-V:检查检查点,删除后等待合并。
- KVM/qcow2:
qemu-img info disk.qcow2看是否有backing file,快照链会让空间只增不减。
第二点:Linux下df和du对不上,先找“被删但仍被占用”的文件
这是运维现场的高频坑,文件被rm了,但某个进程还握着文件描述符,内核不会释放磁盘块。
lsof +L1 # 或 lsof | grep deleted
找到PID后,重启对应进程最稳妥,临时处理可以清空句柄:
: > /proc/<PID>/fd/<FD编号>
处理完再跑df -h确认,顺手看一眼inode:df -i,inode耗尽也会表现为“没空间”。
第三点:文件系统支持discard,但没开
ext4、XFS都支持TRIM/UNMAP,挂载时加discard可以让删除动作实时通知底层,但性能有损耗,更常见的做法是定期手动执行:
fstrim -av
如果fstrim报“不支持discard”,说明虚拟磁盘控制器或磁盘格式没开UNMAP,VMware需要虚拟机硬件版本和VMware Tools配合;KVM需要virtio-scsi并开启discard,行业共识认为,开启UNMAP是精简置备环境回收空间的前提。
VMware虚拟机磁盘空间不释放和厚置备对比
先看一张表,理解为什么有的磁盘“删了就能回收”,有的死活不动。
| 磁盘类型 | 空间分配方式 | 删除文件后能否自动回收 | 常用回收手段 |
|---|---|---|---|
| 厚置备延迟置零 | 创建时占满 | 不能 | 基本不回收,需迁移或重建 |
| 厚置备置零 | 创建时全量写零 | 不能 | 同上 |
| 精简置备 | 按需增长 | 开UNMAP可回收 | fstrim、Storage vMotion、vdiskmanager |
| qcow2 | 按需增长 | 需discard或离线压缩 | fstrim、qemu-img convert、virt-sparsify |
| Hyper-V动态磁盘 | 按需增长 | 需Optimize-VHD | 关机后压缩 |
厚置备和精简置备的差别不在“谁更高级”,而在空间什么时候被占住,厚置备图的是稳定和性能可预期,代价是删了文件也不退,精简置备图的是利用率,但必须把TRIM/UNMAP链路打通。
VMware环境实操:
- 确认虚拟机磁盘是精简置备:
vmkfstools -i查看,或在vSphere里看磁盘类型。 - 虚拟机内执行
fstrim -av(Linux)或对Windows磁盘做优化。 - ESXi侧手动UNMAP:
esxcli storage vmfs unmap -l <datastore名称>,VMFS6默认自动UNMAP,VMFS5需要确认。 - 离线压缩vmdk(需关机):
vmware-vdiskmanager -k disk.vmdk。 - 实在不回收,用Storage vMotion迁到另一数据存储,目标盘选精简置备,迁移过程会重写磁盘。
KVM虚拟机qcow2磁盘空间回收怎么做
qcow2是文件,不是块设备,回收思路更直接:要么让guest发discard,要么离线重写。
先看实际占用:
qemu-img info disk.qcow2
disk size是文件大小,virtual size是虚拟机看到的容量,两者差距大,说明有空洞可回收。
在线方案是给虚拟机磁盘挂discard=unmap,guest内定期fstrim -av,离线方案更彻底:
# 关机后 virt-sparsify --compress disk.qcow2 disk-new.qcow2 # 或 qemu-img convert -O qcow2 -c disk.qcow2 disk-new.qcow2
转换会只保留有效数据块,文件明显变小,操作前备份,别直接覆盖原盘。
云服务器虚拟机磁盘扩容后空间不释放
云上还有一类“看起来没释放”的情况,其实是扩容没做全,控制台把云盘从100GB调到200GB,lsblk看到磁盘大了,但df -h还是100GB,这不是回收问题,是分区和文件系统没扩。
Linux典型步骤:
growpart /dev/vda 1 resize2fs /dev/vda1 # ext4 xfs_growfs / # XFS
Windows在“磁盘管理”里扩展卷即可,近年来云厂商文档普遍把“扩容云盘”拆成扩容容量、扩容分区、扩容文件系统三步,少一步都看不到变化,另一个容易忽略的点是云盘本身多为精简置备,guest内删文件后需要TRIM/UNMAP支持才会反馈到云存储层,具体看云厂商是否透传discard。
Windows虚拟机空间回收的实操细节
Windows guest的坑集中在回收站、卷影副本和休眠文件。
- 清空回收站,再检查“卷影副本”:
vssadmin list shadowstorage。 - 关闭休眠可释放与内存等大的
hiberfil.sys:powercfg -h off。 - 页面文件
pagefile.sys不会因删文件变小,需要调整虚拟内存设置。 - 零填充空闲块再压缩:Sysinternals的
sdelete -z C:,然后关机执行Optimize-VHD -Mode Full(Hyper-V)。
Hyper-V动态磁盘压缩:
Optimize-VHD -Path D:\VMs\test.vhdx -Mode Full
虚拟机需关机或挂载后处理,压缩前确认没有检查点,否则合并会把空间吃回去。
一套可以照着走的排查清单
遇到“虚拟机文件释放后空间未释放”,按这个顺序走,基本不会绕远路:
- 虚拟机内确认删除生效:
df -h、df -i、回收站。 - 查被删仍占用:
lsof +L1,重启相关进程。 - 查快照/检查点/备份残留,先合并或删除。
- 确认磁盘格式:厚置备、精简置备、qcow2、vhdx。
- Linux执行
fstrim -av;Windows做磁盘优化。 - 存储侧确认UNMAP/TRIM是否开启,VMFS手动unmap。
- 仍不降则关机离线压缩:
vmware-vdiskmanager -k、qemu-img convert、Optimize-VHD。 - 云盘场景补做分区和文件系统扩容。
据SNIA对SCSI UNMAP/TRIM的标准定义,这类命令的本质是告诉底层“这些块不再使用”,但执不执行、什么时候执行,由存储和虚拟化层决定,所以别指望删完立刻见效,按链路逐层确认才靠谱。
关于虚拟机磁盘空间回收的常见问题
虚拟机磁盘空间回收后,宿主机文件为什么还是原来大小
先看虚拟磁盘是不是厚置备,厚置备创建时就占满,删文件不会退,再看UNMAP链路是否打通:guest文件系统、虚拟磁盘控制器、存储层任一处不支持discard,回收都不会发生,最后确认没有快照或备份残留。
fstrim执行了,空间还是没释放是什么原因
fstrim -av只对支持discard的块设备有效,如果虚拟磁盘是IDE控制器、厚置备、或存储未开UNMAP,命令可能成功但底层无动作,可以看lsblk -D确认discard能力,再检查虚拟化平台侧的UNMAP配置,离线压缩是兜底方案。
删除快照后虚拟机空间多久会释放
删除快照会触发磁盘合并,合并期间空间可能不降反升,合并完成后才释放,合并耗时与快照大小、存储性能有关,大快照在机械盘上跑数小时并不罕见,合并任务没结束前不要重复操作,也不要做新的快照。