VMware Thin卷VMDK空间回收:停机与在线两方案

发布时间:2026/10/25 0:41:03
VMware Thin卷VMDK空间回收:停机与在线两方案

简介:这份文档面向使用 VMware 虚拟化平台、受精简置备磁盘“占而不放”问题困扰的运维人员与虚拟化学习者,聚焦 vmfs5 文件系统不支持自动回收空间这一常见痛点,给出可落地的空间回收思路。包内仅含 1 个 docx 文件,压缩包约 408KB,篇幅精炼、便于随查随用。文档以实际案例切入,先描述磁盘实际使用 27.8G、VMDK 却占用 36.7G 的典型现象,再分别讲解两条路径:一是借助 SDelete 的 sdelete64.exe –z 清空空闲空间,随后关机并通过 SSH 登录 ESXi 主机执行 vmkfstools –K 回收;二是通过 Storage VMotion 在线迁移,先将磁盘转为厚置备延迟归零,再迁回并选回 Thin 格式,兼顾不停机场景。文档还补充了 Thin 格式的优缺点、精简卷管理与 ESXi 存储功能说明,配有操作界面截图与进度示意,便于对照排查、快速复现。目前已有 2021 人学习下载,适合需要处理存储容量告警、优化虚拟磁盘占用的读者参考。

1. 从 36.7G 的 VMDK 说起:Thin 卷删了文件为什么还不掉空间

一台 Windows Server 2012 R2 虚拟机,Guest 里看 C 盘实际只用了 27.8G,数据存储上的 VMDK 却占着 36.7G。文件确实删了,回收站也清了,VMDK 就是不掉。这不是系统抽风,而是 VMware 精简磁盘空间回收里最典型的一幕:Thin 卷按块分配,Guest 删除文件只改文件系统元数据,VMFS 并不知道哪些块已经变成空洞。这份文档把两条回收路线写在一起:一条是停机后用 SDelete 零填充再执行vmkfstools -K,另一条是在线用 Storage vMotion 换磁盘格式把空洞挤掉。适合手里有 Thin 卷、数据存储余量告急、又必须把停机窗口算清楚的运维人员。先别急着敲命令,下面把三条链路拆开,再落到可复现的步骤和踩坑点。

2. 三条链路的判断:Guest 空闲块、VMFS 块与 VMDK 粒度

2.1 删除文件只改了 Guest 的元数据

Guest 文件系统删除文件时,通常只把索引项标记为空闲,数据块内容还在。对物理机来说,这不算大问题,新文件会覆盖旧块;对 Thin 虚拟磁盘来说,问题被放大:VMDK 只知道“这个块曾经写过”,不知道 Guest 已经把它标成空闲。于是 Guest 里空间越用越少,VMDK 却只增不减。SDelete 的-z参数做的事很直接:把 Guest 逻辑卷上的空闲块全部写成零。零块在后续vmkfstools -K扫描时可以被识别并收缩,Thin 磁盘才有机会把“写过但已空闲”的块还回去。这里的关键不是清理文件,而是把 Guest 的空闲状态翻译成 VMFS 能看懂的零块。

2.2 vmfs5 的手动回收缺口在哪里

这套环境里的 vmfs5 文件系统没有把自动回收跑通。Guest 删除文件后,VMFS 块不会立刻变成可复用空间,数据存储余量自然对不上。手动回收分两段:第一段在 Guest 内把空闲块零化,第二段在 ESXi 层对 VMDK 做收缩。缺少任何一段,VMDK 都可能只瘦一点或者完全不动。原料里给的vmkfstools –K *.vmdk是第二段的命令,但它有前提:虚拟机关机、快照合并干净、目标 VMDK 是基础盘而不是快照盘。现场最容易翻车的地方,就是把通配符当成省事写法,结果把-000001.vmdk之类的快照盘也带进去。

2.3 选停机零填充还是在线迁移

两条路线不是谁替代谁,而是按停机窗口和目标存储余量选。SDelete 加vmkfstools -K的优点是回收直接、不需要额外数据存储;缺点是必须停机,而且零填充会吃 CPU 和磁盘 IO,大磁盘要留足时间。Storage vMotion 的优点是可以在线迁移,VM 不停机;缺点是目标存储必须能放下迁移后的磁盘,第一跳选厚置备延迟归零时目标会按最大容量分配,容量不够就直接卡住。常见做法是:能接受停机、目标存储紧张,走方法一;不能停机、有第二块数据存储,走方法二。要是目标存储只剩一点余量,别硬上 Storage vMotion,先清空间或者加临时存储。

2.4 动手前的四条检查命令

维护窗口开始前,先上 ESXi 主机把虚拟机 ID、快照、VMDK 实际占用和数据存储余量查一遍。下面几条命令是我一般在 SSH 里先跑的,目的不是炫技,而是避免后面把快照盘当基础盘收缩。

# 列出虚拟机并找到目标 VM 的 vmid vim-cmd vmsvc/getallvms | grep -i "VM01" # 查目标 VM 的快照,输出为空才适合做收缩 vim-cmd vmsvc/get.snapshotinfo <vmid> # 看目标目录下 VMDK 的实际占用和文件名 cd /vmfs/volumes/datastore1/VM01 ls -lsh *.vmdk # 看数据存储余量,回收前先留出安全余量 df -h /vmfs/volumes/datastore1

vim-cmd vmsvc/getallvms用来拿 vmid,后面的快照查询要用它;get.snapshotinfo输出为空说明没有快照,有快照先合并,不要直接收缩。ls -lsh里第一列是实际占用,别只看文件逻辑大小;df -h看的是数据存储余量,回收前至少留出一成以上的安全空间。Guest 内也要确认磁盘使用量,Windows 下用Get-PSDrive C看已用空间,Linux 下用df -h。这四条检查不做,后面很容易出现“命令跑完了但 VMDK 没变”的假故障。

3. 方法一落地:SDelete 零填充加 vmkfstools -K 的停机回收

3.1 维护窗口里先确认四件事

方法一不是上来就敲sdelete64.exe。先把四件事确认掉:Guest 内没有正在跑的大批量写入,Windows 更新和备份任务已经停掉;虚拟机没有快照,快照盘和基础盘不要混在一起;数据存储余量足够支撑收缩过程中的临时 IO;停机窗口覆盖零填充和vmkfstools -K两段时间。原料里那台机器 Guest 实际用了 27.8G,VMDK 占了 36.7G,差额接近 9G,这种量级在小盘上不算大,但零填充仍然会扫全盘空闲块,盘越大越要留时间。我一般会把 SDelete 放在维护窗口前半段跑,跑完立刻关机做 ESXi 层收缩,避免中间又产生新写入。

3.2 SDelete 的参数与执行观察

把sdelete64.exe放到 C 盘根目录,用管理员权限打开 CMD。原料里给的命令是sdelete64.exe –z C:,注意这里是大写盘符加冒号,-z表示零化空闲空间,不是删除文件。执行后会出现进度条,进度条走完不代表 VMDK 立刻变小,它只完成了 Guest 侧的空闲块零化。

:: 以管理员身份打开 CMD 后执行 :: -z 零化空闲空间,C: 是目标卷;多分区环境要按实际卷逐个处理 C:\sdelete64.exe -z C:

参数说明:-z是零化空闲块,专门为虚拟磁盘收缩场景准备;C:是 Guest 内要处理的卷。测试环境只有一个分区,所以只跑 C 盘;生产环境如果有 D、E 盘,要按实际卷分别执行,否则未处理卷的空洞还在。执行期间不要中断,也不要同时跑磁盘碎片整理。SDelete 跑完后,Guest 内空闲空间内容已经变成零块,但 VMDK 还是原样,接下来必须关机。

3.3 关机后定位 VMDK 并执行 vmkfstools -K

虚拟机关机后,通过 SSH 登录 ESXi 主机,进入虚拟机目录。原料里写的是vmkfstools –K *.vmdk,我建议先把*.vmdk列出来确认,只对基础盘执行,不要对快照盘执行。下面命令里VM01.vmdk要换成实际基础盘文件名,带空格的路径要加引号。

# 进入虚拟机目录,路径按实际数据存储和 VM 目录调整 cd /vmfs/volumes/datastore1/VM01 # 先列清楚有哪些 vmdk,确认哪个是基础盘,哪些是快照盘 ls -lh *.vmdk # 只对基础盘执行收缩;-K 用于收缩 Thin 虚拟磁盘 vmkfstools -K "VM01.vmdk"

vmkfstools -K的参数含义是收缩 Thin 虚拟磁盘,执行时会扫描 VMDK 里的零块并释放对应 VMFS 块。它要求虚拟机关机,执行时间跟磁盘大小和零块比例有关,进度到 100% 才算完成。原料里用*.vmdk通配符,现场最好别这么干:快照盘、裸设备映射盘、独立盘混在一起时,通配符会把不该动的文件带进去。血泪经验是,先在ls -lh输出里认准基础盘文件名,再单独执行。执行过程中不要开 vSphere Client 对这台 VM 做迁移或改配置,等命令返回后再动。

3.4 回收后的三个验证动作

回收完成后别只看一眼 VMDK 数字就收工。先看 VMDK 实际占用有没有下降,再看数据存储余量有没有回来,最后进 Guest 确认文件系统正常。下面三条命令分别对应这三个动作。

# 看 VMDK 实际占用是否下降 ls -lsh /vmfs/volumes/datastore1/VM01/VM01.vmdk # 看数据存储余量是否回来 df -h /vmfs/volumes/datastore1 # 看虚拟机是否还在关机状态,确认后再开机 vim-cmd vmsvc/power.getstate <vmid>

ls -lsh的第一列是实际占用,和回收前对比才有意义;df -h看数据存储余量,注意 VMFS 的余量刷新可能有延迟,等几秒再看;power.getstate确认 VM 状态,确认无误再开机。开机后进 Guest 看磁盘管理,确认卷没有异常,再跑一遍业务检查。方法一的边界很清楚:必须停机,零填充会扫全盘,大磁盘要留足窗口;但它的好处是不依赖第二块数据存储,回收链路短,适合余量紧张的环境。

4. 方法二落地:Storage vMotion 换格式的两跳回收

4.1 第一跳:把 Thin 迁到厚置备延迟归零

方法二的核心不是“迁移”两个字,而是借迁移换磁盘格式。第一跳把 Thin 磁盘迁到厚置备延迟归零,迁移过程中虚拟磁盘会被重新写一遍,原来 Thin 里的空洞在目标端不再以精简块的形式保留,旧数据存储上的 VMDK 在迁移完成后释放。原料里强调目标存储要有足够空间,这一点必须放在第一位:厚置备延迟归零会按磁盘最大容量分配目标空间,不是按当前实际使用量分配。也就是说,源端 VMDK 虽然只占 36.7G,目标端可能要按磁盘最大容量准备空间,容量不够时迁移会直接失败。迁移可以在线做,VM 不需要停机,但迁移期间对源端和目标端的 IO 都有压力,业务高峰期别硬上。

4.2 在线迁移的操作路径与参数

在 vSphere Client 里选中虚拟机,右键迁移,选择“更改数据存储”,目标存储选第二块数据存储,虚拟磁盘格式选“厚置备延迟归零”。这一步的关键参数只有两个:目标数据存储和磁盘格式。目标存储要确认余量大于磁盘最大容量,不要只看当前 VMDK 占用;磁盘格式要选厚置备延迟归零,不要选 Thin,否则第一跳没有意义。迁移任务开始在任务栏里能看到进度,迁移完成后原数据存储上的 VMDK 会释放,但目标端变成厚置备延迟归零,占用会按最大容量算。下面这张表是我现场用来做格式选择的,不是理论分类,而是回收场景下的取舍。

磁盘格式空间分配方式回收场景下的作用主要代价
Thin按需分配日常省空间,但空洞不会自动还需要手动回收,VMDK 可能虚胖
厚置备延迟归零创建时分配全部块,零化延迟第一跳把空洞挤掉,迁移完成释放旧存储目标端按最大容量占空间,容量要求高
厚置备立即归零创建时分配并立即零化性能稳定,适合对 IO 敏感的盘占用最大,迁移时间更长

选厚置备延迟归零而不是立即归零,是因为第一跳的目标只是把旧存储的空洞释放掉,延迟归零在迁移场景下够用,目标端零化压力比立即归零小。迁移完成后先别急着做第二跳,确认虚拟机运行正常、目标存储余量还在安全线以上,再做迁回。

4.3 第二跳:迁回 Thin 并把容量账算清

如果还想继续用 Thin,需要再做一次 Storage vMotion,把虚拟机从厚置备延迟归零迁回原来的数据存储,磁盘格式选 Thin。第二跳完成后,新 Thin 磁盘只分配实际有效块,空洞不再被分配,空间才算真正回收。这里有一个容量账要算清楚:第一跳目标端按最大容量占空间,第二跳源端是厚置备延迟归零,目标端是原数据存储的 Thin。两跳之间目标存储的余量要分别满足,不能拿第一跳的余量去套第二跳。原料里写“完成后磁盘格式转换为厚置备延迟归零,如果还想用 Thin,再迁回来”,这个顺序不能反:先厚后 Thin,才能把空洞留在旧存储上释放掉。第二跳完成后,原数据存储的 Thin 占用会明显下降,但迁移过程仍然需要目标存储有足够空间承接厚置备磁盘的复制流量。

4.4 目标容量和迁移窗口怎么估

迁移前我一般按三个数估容量:源 VMDK 当前实际占用、磁盘最大容量、目标存储现有余量。第一跳目标端按最大容量分配,所以目标余量必须大于磁盘最大容量,再加一成安全余量;第二跳目标端是 Thin,按实际有效块分配,余量要求低一些,但迁移过程中仍然要有临时 IO 空间。迁移窗口按数据量和存储带宽估,在线迁移虽然不停机,但迁移期间业务 IO 会变慢,数据库类虚拟机最好放在低峰期。原料里那台机器盘不大,两跳都能在较短时间内完成;如果是几 TB 的盘,第一跳的厚置备分配和第二跳的 Thin 复制都要留足时间,别把两跳塞进同一个十分钟窗口。方法二的优点是 VM 不停机,缺点是目标存储容量要求高、两跳操作多,适合有第二块数据存储且能接受迁移期间性能波动的场景。

5. 避坑与排查:五个现场翻车点

5.1 现象:SDelete 跑完,VMDK 一点没瘦

现象很常见:Guest 里进度条走完了,回到数据存储一看,VMDK 还是 36.7G,甚至因为新写入还涨了一点。原因通常不是 SDelete 没跑,而是第二段没做:虚拟机关机后没有执行vmkfstools -K,或者执行时虚拟机还在运行,命令直接失败但被忽略。还有一种情况是快照没合并,基础盘被快照链挡住,收缩命令作用不到真正的数据块。解决顺序是:先查快照,有快照先合并;再关机;再进目录确认基础盘文件名;最后单独执行vmkfstools -K。执行完用ls -lsh对比实际占用,不要只看 vSphere Client 的摘要数字。

5.2 现象:vmkfstools -K 报找不到文件或无法打开

这个报错多半是路径和文件名的问题。ESXi 的目录名、数据存储名、VMDK 文件名里可能有空格或特殊字符,通配符展开后顺序不对也会导致命令作用到错误文件。原因还包括:虚拟机没有真正关机、SSH 会话没有权限、当前目录不是虚拟机目录。解决时先pwd确认目录,再ls -lh看清文件名,带空格就用引号包住完整路径。不要直接复制原料里的*.vmdk一把梭,先把列表打出来,只对基础盘执行。如果报“Failed to open”,先看虚拟机电源状态,再看快照,再看文件权限,三件事排完再重试。

5.3 现象:Storage vMotion 迁到一半失败,目标存储满了

第一跳选厚置备延迟归零时,目标端按磁盘最大容量分配,不是按当前 VMDK 占用分配。很多人看源端只占 36.7G,就以为目标留 40G 够用,结果磁盘最大容量是 60G,迁移到一半目标存储满,任务失败。原因就是容量估算口径错了。解决时先看虚拟机磁盘的最大容量,不是看 VMDK 当前实际占用;目标存储余量要大于最大容量再加安全余量。已经失败的迁移先清理目标端的残留文件,再重新评估目标存储。如果目标存储实在不够,别硬做第一跳,回到方法一停机回收,或者先扩数据存储。

5.4 现象:迁回 Thin 后空间没回来,反而更紧张

第二跳迁回 Thin 后,原数据存储的空间应该释放,但有时看起来更紧张。原因可能是迁移任务还没完全结束,VMFS 的块回收有延迟;也可能是迁移过程中产生了新的快照或临时文件,把释放出来的空间又占回去了。解决时先等任务完全结束,再刷新数据存储容量;然后查快照和虚拟机目录下的临时文件,确认没有残留的-000001.vmdk或迁移临时盘。还有一点容易被忽略:第二跳的目标端如果选错数据存储,Thin 磁盘会落到另一块存储上,原存储当然不会释放。迁移前把源和目标在任务摘要里核对一遍,别只看虚拟机名字。

5.5 现象:SDelete 执行很慢,窗口快结束了还没跑完

SDelete 零化空闲块会扫全盘,磁盘越大、空闲块越多,时间越长。原因还包括 Guest 内杀毒软件实时扫描、磁盘碎片多、存储 IO 本身吃紧。解决时把 SDelete 放在维护窗口前半段,提前估算时间;执行前停掉不必要的扫描任务;大磁盘可以按卷分批处理,不要一个窗口里把所有卷都跑完。如果窗口实在不够,先处理系统盘和增长最快的业务盘,剩下的卷排到下一个窗口。零填充不是玄学,它就是 IO 换空间,窗口估算要把 IO 压力算进去,不能只看进度条。

6. 回收后的验收:一张检查表和一条硬习惯

回收做完,验收别只看 VMDK 数字。下面这张表是我现在每次回收后必走的检查项,五项都过再算收工。

检查项看什么通过标准
VMDK 实际占用ls -lsh第一列比回收前明显下降,且不是只降一点
数据存储余量df -h余量回到安全线以上,刷新后稳定
Guest 磁盘状态磁盘管理或df -h卷正常,业务读写无异常
快照与临时文件快照列表、VM 目录没有残留快照和迁移临时盘
磁盘格式vSphere Client 磁盘属性符合预期,Thin 就是 Thin,厚置备就是厚置备

我一般会把ls -lsh和df -h的输出顺手记在维护记录里,下次再遇到同一台机器空间异常,能直接对比是 Guest 增长还是空洞没回收。从那以后我每次做 Thin 卷回收,都强制走一遍“快照确认、停机确认、目标容量确认、回收后验收”这四步,哪怕盘再小也不省。希望帮到你。

本文还有配套的精品资源,点击获取