
简介面向 VMware 虚拟化运维人员与存储管理初学者这份 408KB 的 docx 文档聚焦 Thin 精简磁盘空间回收难题围绕 VMFS5 不支持自动回收空间的现实限制梳理 SDelete 清理与 Storage VMotion 迁移两条解决路径并补充适用条件、停机要求与格式转换等注意事项。包内共 1 个 docx 文件内容以问题现象、环境说明、处理思路和结果验证为主线便于读者理解精简卷空间占用与回收逻辑。该资料已有 2022 人学习适合需要处理 VMDK 空间未释放、Thin 磁盘回收及 ESXi 存储维护任务的读者参考可作为日常运维中的排查思路与方案对照材料。1. 从一块 36.7G 的 VMDK 说起Thin 磁盘删了文件为什么不瘦一台跑着 Server 2012 R2 的虚拟机系统里翻来覆去只放了 27.8G 的东西数据存储上那个 VMDK 却稳稳占着 36.7G。清过临时目录、删过旧日志、回收站也倒了这个差值一点没动——这就是 VMware 精简磁盘空间回收最典型的现场也是 Thin 磁盘最容易被误解的地方删文件在 guest 里只是把簇标记成空闲VMFS5 根本不认这件事块该占还占着。盘越用越虚备份越来越慢克隆越来越久等到数据存储亮红灯才想起来处理往往已经挤不出停机窗口。这套流程适合手上有 Thin 虚拟机、跑在 VMFS5 上、并且能安排出一次关机或一次在线迁移窗口的人。两种回收路子各有代价下面按「先盘环境、再动手、最后验证」的顺序拆开记。2. 回收前的环境盘点磁盘格式、VMFS5 和停机窗口三件事这套操作最怕上来就敲命令。同一条vmkfstools -K我在不同环境里见过两种完全相反的结果差别不在命令本身而在盘是什么格式、数据存储是什么文件系统、虚拟机上还挂着什么东西。动手前把这三件事确认掉比事后找后悔药便宜得多。2.1 三种磁盘格式Thin、厚置备延迟归零、厚置备置零vSphere 里虚拟磁盘的置备方式就三种回收这件事只对第一种有意义但另外两种在迁移方案里要当跳板用所以必须分得清。磁盘格式空间怎么分配删文件后能否回收转换时的空间占用精简置备Thin按实际写入量分配不能自动需手动回收等于已用数据量厚置备延迟归零Lazy Zeroed创建时按配置容量全量分配不适用等于配置容量厚置备置零Eager Zeroed创建时按配置容量分配并写零不适用等于配置容量在 vSphere Client 里看最直接选中虚拟机 → 编辑设置 → 展开硬盘看「磁盘置备」那一栏写的是哪个。命令行也能查前提是虚拟机关机否则部分字段读不全。# 登录 ESXi 主机后查看某个 vmdk 的详细信息 # 输出里重点看 type 字段和 RW 那一行的容量 vmkfstools -D /vmfs/volumes/datastore1/VMName/VMName.vmdk-D是 dump 的意思把描述符里的元数据打出来。输出比较长别被吓到只盯两处type是thick还是thin以及 RW 后面的扇区数——乘 512 就是这块盘的实际大小。如果虚拟机还开着这个命令读到的部分信息可能滞后所以盘点阶段我一般挑业务低峰、虚拟机相对安静的时候做。顺带说一个容易混淆的点目录里同一个磁盘会有两个文件VMName.vmdk只有几百字节到几 KB是描述符VMName-flat.vmdk才是真正装数据的那个通常几个 G 到几十 G。回收命令要作用在描述符上但判断空间有没有降下来看的是-flat.vmdk的大小。这两个搞反了后面的排查会一路跑偏。2.2 VMFS5 为什么不自动回收VMFS6 又差在哪VMFS5 不支持自动回收空间这不是配置没开是文件系统这一层就没这个机制。guest 操作系统里删掉的文件到 VMFS5 这里只表现为「这些块的内容不再被引用」但块本身仍然挂在虚拟磁盘上。Thin 的精简发生在写入那一刻第一次写到某个块VMFS 才真正分配。分配出去之后除非有人主动把这些块「打洞」还回来否则它们永远算在 VMDK 头上。后来的 VMFS6 把自动 UNMAP 做成了常规能力配合支持 UNMAP 的 guest 系统删除动作能一层层传到存储。这也是为什么同一套操作在不同环境里效果差很多——有人已经跑在 VMFS6 上删完文件过一阵空间自己就回来了有人还在 VMFS5等一年也不会动。Windows Server 2012 R2 这个代际在 VMFS5 上基本指望不上自动回收老老实实手工做反而更快。提示不确定数据存储是哪个版本在 vSphere Client 的存储视图里看「VMFS」标签页会写明 5.x 还是 6.x。这一步别猜。所以后面两套方法本质上都是在补 VMFS5 缺的那一环方法一从 guest 内部把空闲块写成零再由 ESXi 侧把这些零块识别出来释放方法二干脆整盘搬迁一次让复制过程只带走有内容的块。2.3 停机窗口、工具和一张准备清单方法一必须关机这是硬约束vmkfstools -K在虚拟机运行状态下执行会失败或者干脆没效果。方法二是在线迁移虚拟机不停但要求目标存储有足够空间而且迁移期间 IO 会受影响。两种方法对资源的要求不一样动手前把清单过一遍。准备项方法一要求方法二要求虚拟机状态必须关机可在线工具sdelete64.exe无vSphere Client 即可ESXi SSH需要临时开启不需要数据存储余量能容纳 VMDK 膨胀后的峰值目标存储能放下整块配置容量快照必须先删除必须先删除耗时量级与空闲空间大小正相关与磁盘配置容量和存储性能相关清单里我特意把快照单列一行因为它是这套流程里最常见的隐形拦路虎虚拟机挂着快照时写入会落到快照增量盘上回收命令作用不到原始数据跑完一看空间没变白等几个小时。回收前先把快照删掉或者合并掉这一步没有捷径。工具这边SDelete 是微软 Sysinternals 套件里的一个命令行实用程序作用是清除逻辑磁盘上的空闲空间。从微软 Sysinternals 官方下载页拿到压缩包解压后 64 位系统用sdelete64.exe32 位系统用sdelete.exe。ESXi 侧的 SSH 默认是关的需要在主机 → 服务里临时启用用完记得关回去。3. 方法一实操sdelete64 清零加 vmkfstools -K 回收全流程这套方法分两段前半段在虚拟机内部做把空闲块写成零后半段在 ESXi 主机上做把这些零块还给数据存储。两段之间必须关机顺序不能颠倒。3.1 把 sdelete64.exe 放进虚拟机并确认盘符下载下来的 Sysinternals 包解压后文件不少只挑sdelete64.exe一个就够。我的习惯是直接拷到 C 盘根目录路径短CMD 里不用来回切目录也避免了路径里带空格导致的引号问题。拷贝完先裸跑一次确认文件本身没被拦下来:: 以管理员身份打开 CMD直接执行不带参数会打印用法说明 C:\ sdelete64.exe能打出参数列表就说明可执行。这一步看着多余实际上能挡掉两类问题一是杀毒软件把工具静默隔离了执行时提示找不到文件二是拿到的是 32 位版本在 64 位系统上虽然也能跑但处理大容量磁盘时效率差一截。确认盘符也很关键。原文的场景是一台单分区的虚拟机C:就是全部。多分区的机器要逐个分区处理数据盘上如果有大量删除过的文件同样会撑大 VMDK只清 C 盘等于只回收了一半。:: 看一眼当前机器有哪些分区确认要清理的盘符 C:\ wmic logicaldisk get caption,freespace,sizefreespace是空闲字节数size是总容量。两者一减就是已用空间和 vSphere 里看到的 VMDK 大小对一下差值有多大回收的收益就有多大。3.2 sdelete64.exe -z C: 清零空闲空间核心命令只有一条:: -z 表示清零空闲空间这是回收能生效的前提 C:\ sdelete64.exe -z C: :: 如果希望减少无谓的多轮写入可以显式指定覆盖次数为 1 C:\ sdelete64.exe -z -p 1 C:参数逐个说清楚。-z是 zero free space把 NTFS 认为空闲的簇全部写成 0这是这条命令存在的唯一理由不加-z就变成清理文件了跟回收没关系。-p是覆盖次数passes默认就是 1写不写差别不大只有在有安全擦除要求的场景才需要往上调调到 3 以上会让整个流程慢好几倍。-s是递归子目录清理文件时用-z场景下不需要。-q是安静模式去掉进度输出批处理里用得上手工操作反而希望看到进度。-nobanner去掉启动横幅纯粹是让日志干净一点。执行之后会看到一条进度条在走速度取决于空闲空间大小和存储性能。几十 G 的空闲空间跑一两个小时不稀奇机械盘上更久。这时候别急着开第二个窗口去 vSphere 里看容量看了会心慌。注意清零过程中 VMDK 会明显膨胀极端情况下会涨到接近虚拟磁盘的配置容量。这是预期内的中间状态——那些原本「空闲」的块现在被写进了零VMFS 认为它们有内容自然就分配出去了。等下一步vmkfstools -K跑完这些块才会被真正释放。中途看见数据存储快满了先别停先确认剩余空间能不能撑到回收结束。跑完之后虚拟机关机。关机前顺手确认一下没有挂载的 ISO、没有正在写的日志避免关机卡在某个进程上。3.3 SSH 登录 ESXi定位到具体的 -flat.vmdk关机之后换到 ESXi 侧。用 SSH 登录到虚拟机所在的那台主机# 地址换成你自己的 ESXi 管理地址这里只是示例 ssh root192.0.2.10登录后先看数据存储挂在哪儿。ESXi 的/vmfs/volumes/下面每个数据存储会出现两条记录一条是 UUID 命名的真实目录一条是好记的名字做的软链接指向同一个地方。进哪个都行用友好名更省事。# 列出所有数据存储确认目标存储的挂载名 ls -l /vmfs/volumes/ # 进入虚拟机目录路径按实际情况替换 cd /vmfs/volumes/datastore1/VMName/ # 看清楚目录里有哪些 vmdk别急着执行通配符 ls -lh *.vmdkls -lh的输出会同时列出描述符和-flat.vmdk。真正占空间的是后者回收前后对比的就是它的大小。目录里如果有多块磁盘比如系统盘加数据盘*.vmdk会把它们全部匹配上。原文给的命令是vmkfstools -K *.vmdk通配符的好处是一条命令处理全部磁盘省事。但我一般会先ls看清楚再逐个指名道姓地执行原因是如果目录里混着一块厚置备的磁盘-K对它无效可能报错中断前面的活就白干了另外多块盘逐个跑进度和耗时都更好估算出问题也容易定位是哪一块。3.4 vmkfstools -K 执行回收盯住进度和剩余空间# -K 的作用是对 thin 磁盘打洞把内容全零的块还给数据存储 # 参数是 vmdk 的描述符文件不是 -flat.vmdk vmkfstools -K /vmfs/volumes/datastore1/VMName/VMName.vmdk-K这个参数从 ESXi 5.x 之后就有专门用于 thin 磁盘的空间回收。它做的事情可以理解为扫描整块虚拟磁盘把内容全是零的块标记为「未分配」从 VMDK 的占用里扣掉。所以前一步 SDelete 不是可有可无的准备工作它是让「空闲块」变成「全零块」的唯一手段没有这一步-K扫完会发现所有块都非零什么都回收不了。命令回车后不会有花哨的进度条屏幕上可能长时间没动静这是正常的。想确认它真的在干活另开一个 SSH 窗口盯两个数字# 每 10 秒刷新一次看 flat 文件在缩、数据存储剩余在涨 watch -n 10 ls -lh /vmfs/volumes/datastore1/VMName/VMName-flat.vmdk; df -h /vmfs/volumes/datastore1ls -lh看的是单个文件大小变化df -h看的是整个数据存储的剩余空间。两个数字应该同步往好的方向走flat 文件变小剩余空间变大。如果盯了十几分钟两个数字纹丝不动那基本可以判定这次回收没生效别再等了跳到第 5 章对照排查。耗时没有固定值。同样 30G 的回收量全闪存储上十几分钟老机械盘阵列上跑三四个小时也遇到过。中断了也不要紧-K不是原子操作已经打洞的部分不会回滚重新执行会从剩下的部分继续不会把前面的成果抹掉。4. 方法二实操Storage vMotion 转厚置备再回迁 Thin方法一要求停机碰上不能停的业务就得换路子。Storage vMotion 的思路不一样整盘搬到另一个数据存储迁移过程中重新组织数据落在目标端的文件自然就是紧凑的。这套操作全程在线虚拟机不用关机。4.1 迁移前的容量预算与目标存储检查这一步最容易翻车的地方是容量算法。很多人拿 guest 里的已用空间去估目标存储需要多少结果迁移跑到一半报空间不足。原因很简单中间那一跳选的是厚置备厚置备按虚拟磁盘的配置容量分配不是按已用数据量分配。虚拟磁盘配置容量guest 内实际已用转厚置备后目标存储占用回迁 Thin 后占用100G30G约 100G约 30G 上下一百 G 的盘只用了三十 G中间那一跳照样要占掉一百 G。预算按配置容量算别按已用算这是血泪经验。动手前先确认目标存储的剩余空间# 在 ESXi 主机上查看各数据存储的容量和剩余 df -h | grep vmfs # 单独看某一个数据存储的细节 vmkfstools -Ph /vmfs/volumes/datastore2df -h的输出里重点看 Use% 那一列剩余空间要大于虚拟磁盘的配置容量再留出百分之十左右的余量给迁移过程中的临时开销。vmkfstools -Ph会额外打出块大小、支持的文件类型这些信息目标存储如果是不同版本的 VMFS这一步能提前发现不兼容。还有一点常被忽略虚拟机如果有快照迁移时快照文件也会一起搬实际占用会比预算多。所以跟前一套方法一样先把快照清干净再动手。4.2 右键迁移更改数据存储与厚置备延迟归零操作路径在 vSphere Client 里步骤不多但每一步的选择都会影响最后能不能瘦下来。在清单里选中目标虚拟机右键 → 迁移。迁移类型选「仅更改存储」不要选「更改计算资源」后者会连带触发一次计算资源的重新放置没必要。选择目标数据存储注意看容量条别选到快满的那个。关键一步虚拟磁盘格式选「厚置备延迟归零」。确认摘要页的信息点完成然后等。为什么中间这一跳不直接选 Thin因为源盘已经是 Thin 了直接从 Thin 迁到 Thin复制过程能带走的只有已分配的块那些「已分配但内容全零」的块还是会被当成有效数据搬过去瘦身效果打折。先落成厚置备延迟归零等于强制把整块盘按配置容量铺开再回迁 Thin 的时候全零的块会被识别出来跳过落回目标存储的就只剩真正有内容的部分。迁移开始后任务栏里能看到进度百分比。这个百分比不是线性的前期在传数据后期在收尾卡在 90% 很久是常态。耗时取决于配置容量和存储带宽一百 G 的盘在两台性能正常的存储之间挪动半小时到两小时都算正常范围。期间虚拟机一直在线但磁盘 IO 会有可感知的抖动跑数据库的机器建议避开业务高峰。迁移完成后虚拟机会落在新存储上磁盘格式变成厚置备延迟归零此时 vSphere 里看到的占用就是配置容量。4.3 想回 Thin 就再来一次 vMotion以及它的代价如果目标就是彻底摆脱 Thin 的空间虚高问题可以让虚拟机以厚置备的形式留在新存储上简单直接。但如果存储容量紧张还是得回到 Thin那就再做一次 Storage vMotion把虚拟机迁回原来的数据存储磁盘格式这次选「Thin」。第一次迁移源存储Thin → 目标存储厚置备延迟归零 作用把整盘铺开让零块显形 第二次迁移目标存储厚置备延迟归零 → 源存储Thin 作用复制时跳过全零块落回 Thin 时只占实际数据量两次迁移加起来是两次全量拷贝IO 压力和耗时都是单次的两倍。这是这套方法的主要代价换来的是全程不停机。第一次迁移把数据摊平第二次迁移在复制时把全零块筛掉最终落在源存储上的 VMDK 就是压缩过的。有个细节要提醒第二次迁移前确认源存储的剩余空间够放回迁后的精简磁盘。虽然理论上回迁后占用会大幅下降但迁移过程中目标端是边写边算的瞬时占用可能比预期高一点留出余量更稳妥。还有一种更省事的做法有同行试过直接从 Thin 迁到另一存储的 Thin一次搞定。这条路在数据分布比较规整的情况下也能瘦下来因为复制过程同样会跳过未被引用的块。区别在于厚置备那一跳会把「已分配但内容全零」的块也识别出来瘦得更彻底。两种做法都能跑通看你对回收效果的预期。5. 避坑与排查五条回收翻车记录按现象原因解决拆开这套流程看起来命令不多但每一步都有能让人卡住半天的地方。下面五条是我在实际环境里反复遇到的按「现象 → 原因 → 解决」记照着对号入座基本能定位。5.1 清零阶段的两个坑现象一SDelete 跑完之后VMDK 不降反涨从 36G 涨到接近 100G数据存储直接报警。原因sdelete64.exe -z做的是把空闲簇写成零这些块在 guest 里是空闲的但写零这个动作让 VMFS 认为它们有内容于是实打实地分配了出去。磁盘越空涨得越狠一块一百 G 的盘如果只用了三十 G清零后 VMDK 会逼近一百 G。这是必经的中间态不是命令用错了。解决先确认数据存储剩余空间能不能撑到vmkfstools -K跑完。撑得住就继续往下走跑完自然回落撑不住就换方法二或者临时扩一下数据存储再回来做。以后再做同类操作我一般会提前看一眼剩余空间宁可先扩再清也不在中途卡住。现象二SDelete 跑了几分钟就退出提示「Access is denied」或者进度条压根没出现。原因CMD 不是以管理员权限打开的。清零空闲空间需要直接操作磁盘扇区普通权限拿不到这个句柄。另一个可能是杀毒软件实时防护把这个行为判定成可疑写入直接掐掉了进程。解决开始菜单里搜 CMD右键选「以管理员身份运行」标题栏上会带「管理员」字样再执行。杀毒软件这边临时把这台机器的实时防护关掉或者把sdelete64.exe加进白名单跑完再恢复。企业环境里如果装了统一的安全策略提前跟管策略的人打个招呼别等跑到一半被拦。5.2 回收与迁移阶段的三个坑现象三vmkfstools -K回车后立刻返回什么输出都没有空间一点没变。原因大概率踩了三个雷之一。虚拟机没关机-K对运行中的虚拟机无效虚拟机挂着快照写入落在增量盘上原始 VMDK 的块没变化磁盘格式根本不是 Thin厚置备的块本来就是全量分配没有洞可打。解决按顺序排除。先vim-cmd vmsvc/power.getstate vmid确认虚拟机确实是关机状态注意「已挂起」不算关机再在快照管理器里看有没有快照有就删掉或合并最后用vmkfstools -D确认这块盘是 thin。三个条件缺一不可。还有一种情况是命令里写成了-flat.vmdk-K要的是描述符那个文件写错了同样静默失败。现象四Storage vMotion 跑到一半失败任务里提示存储空间不足虚拟机留在原处。原因容量按 guest 已用空间算的没按虚拟磁盘配置容量算。中间那一跳选的是厚置备延迟归零目标端要按配置容量全量分配一百 G 的盘哪怕只用了三十 G也要一百 G 的空间才放得下。解决先算清楚vmkfstools -D里读到的配置容量再去目标存储里对剩余空间不够就先清理或换一个存储。失败的任务不会破坏虚拟机删掉重来即可但要注意重试前确认目标存储上有没有留下半截文件有的话手动清掉再开始。现象五两次 vMotion 都跑完了虚拟机回到 Thin可空间只降了一点点远没到预期。原因guest 里从来没有做过清零那些删掉的文件对应的块内容还是旧的随机数据不是零。迁移过程只跳过「内容全零」的块非零的块照样搬过去自然瘦不下来。另一个可能是第二次迁移时格式选项没选对落回了厚置备。解决回 guest 里补做一次sdelete64.exe -z C:再走一遍迁移。如果确认清零做过就去检查第二次迁移的格式选项vSphere Client 在迁移向导的最后一步会列出每块盘的格式这一页别一路回车过去。还有一种情况是虚拟机里存在定期任务回收完马上又写满了这种得从业务侧解决回收本身治不了。提示每次做完回收顺手把df -h的输出和ls -lh *.vmdk的结果各存一份。过一周再对比如果空间又掉回去了说明有持续写入的源头没找到早发现比晚了再排查省事。6. 装完怎么验证四个检查点确认空间真的回来了回收跑完不等于结束这套操作最后一定要落到验证上否则过几天发现空间没变前面几个小时的等待就成了玄学。我一般按四个检查点过一遍从内到外对数字。检查点在哪看命令或位置期望结果一、guest 内使用量虚拟机内部wmic logicaldisk get caption,freespace,size与回收前一致说明数据没丢二、VMDK 实际大小ESXi 主机ls -lh VMName-flat.vmdk明显小于回收前三、数据存储剩余ESXi 主机df -h /vmfs/volumes/datastore1剩余空间增加增加量接近差值四、vSphere 视图vSphere Client存储 → 文件 → 虚拟机目录与命令行数字对得上检查点一放在最前面是有原因的回收前后 guest 里的已用空间应该完全一致如果这个数字变了说明中间出了别的问题后面的容量对比就失去了参照。这一条能挡掉「清理脚本顺手删了东西」这类意外。检查点二和三是核心。两个数字要能对上flat 文件缩小了多少数据存储剩余就增加多少误差在几百兆以内属于正常元数据、日志、描述符都会有波动。如果 flat 文件小了但剩余空间没涨多半是还有别的虚拟机在同期写入挑个安静时段再看一次。检查点四用来交叉验证命令行看到的和图形界面看到的必须一致。不一致的时候以命令行为准vSphere Client 的缓存有时候会滞后几分钟刷新一下就好。最后还有一个容易被跳过的动作把虚拟机关机状态解除开机进去随便点几个业务功能确认数据完整。空间回收只动空闲块理论上不会碰到有效数据但「理论上」这三个字在运维现场不值钱。我见过一次因为快照合并失败导致引导异常的虽然跟回收本身没关系但发生在同一个窗口里排查起来就是一团乱麻。从那以后我每次做完回收都会在数据存储上留一份前后对比的记录隔一天再对一次数字。空间会不会「反弹」一次验证看不出来隔天再看才踏实。希望帮到你。本文还有配套的精品资源点击获取