VMware精简置备虚拟磁盘越删越大?空间回收与VMDK瘦身实战

📅 发布时间:2026/9/23 21:31:05
VMware精简置备虚拟磁盘越删越大?空间回收与VMDK瘦身实战
简介一份面向VMware虚拟化运维与存储管理人员的实用技术文档围绕精简置备Thin磁盘在vmfs5文件系统下无法自动回收空间的问题展开系统梳理了两种成熟的回收方案。该文档为可编辑的docx格式共1个文件压缩包仅408KB下载后方便按需批注留存。已有1984人学习下载。方案一基于微软SDelete工具先在Windows虚机内用sdelete64.exe清理空闲空间再停机并通过SSH登录ESXi主机执行vmkfstools命令完成回收方案二借助Storage VMotion在线迁移将虚拟磁盘先转为厚置备延迟归零再迁回时改回Thin格式从而释放空间无需停机。两种方法均配有操作前提、具体命令与注意事项可帮助读者根据停机窗口灵活选择文档还给出实际使用空间27.8G但VMDK占用36.7G的典型示例便于直观理解空间浪费成因有效消除精简磁盘体积膨胀带来的存储浪费。1. 为什么VMware精简置备的虚拟磁盘越删越大物理存储只剩几个 GB进虚拟机删掉上百 GB 的测试数据回到宿主机一看vmdk 文件依旧占着原来的体积。这是精简置备虚拟机的经典误判客户机里删除文件只改了文件系统索引数据块还留在 vmdk 里Hypervisor 认为这些块仍然被占用自然不会把空间还给你。精简磁盘空间回收要解决的就是这一层错位先让客户机把空闲区域变成全零再让宿主机识别全零块并裁剪底层稀疏文件。以下内容面向用 VMware Workstation 跑测试机、维护 vSphere 精简存储池的工程师按“原理 → 客户机清理 → 宿主机回收 → 自动化维护”的顺序展开。2. VMware精简置备的膨胀原理与磁盘空间回收机制2.1 精简置备与厚置备vmdk 文件大小规划之前的两个选择创建虚拟机时选择精简置备vmdk 的逻辑容量仍按配置值显示例如你给 C 盘分配了 100 GB但初始 vmdk 可能只有几 MB 到几十 MB只有真正写入数据时存储层才按 1 MB 或 8 MB 的粒度分配新块。厚置备则相反创建瞬间就占满配置大小而“厚置备延迟置零”比“厚置备快速置零”的创建速度快但首次写入时有清零开销。这个差异也决定了回收方式完全不同。厚置备磁盘的空间固定无论客户机怎么删文件宿主机都没法从 vmdk 回收固定块精简置备磁盘是稀疏文件只要宿主机认定某些块不再被映射就能把文件尾部或中部打洞。理解这个区别才能解释为什么同样的回收操作在精简磁盘上有效、在厚磁盘上无效。对比项精简置备Thin厚置备延迟置零Thick Lazy厚置备快速置零Thick Eager创建时空间占用按需分配立即分配立即分配并清零回收可行性高可打孔/UNMAP低需迁移重写低需迁移重写性能稳定性存在写放大首次写入慢无首写惩罚适用场景测试机、共享存储池常规生产集群/FT/关键生产表格说明日常维护中见到的空间“越用越大”多数集中在精简置备磁盘。厚置备遇到磁盘满只能通过 Storage vMotion 迁移到更大的数据存储不存在“瘦身”一说。2.2 客户机“删除文件”与主机的“块释放”之间差了什么客户机操作系统的文件系统在删除文件时只做了两件事把 inode 或 FAT 表项标记为“可覆盖”把对应逻辑块号加入空闲链表。它不会通知虚拟 SCSI 控制器哪些扇区已经失效更不会主动把扇区内容清零。于是vmdk 底层稀疏文件仍然维护着这些块的映射宿主机看到的仍然是“已分配且非零”的数据。要让宿主机承认这些块可用需要两条路径一是客户机主动把空闲空间“写零”让 vmdk 里对应区域变成连续全零二是客户机发出 SCSI UNMAP/DISCARD 命令让虚拟磁盘控制器把块映射标记为薄。大多数客户机操作系统不会自动做这两件事精简磁盘回收的第一步永远是客户机内的清理动作。我常用的检查命令是vmware-vdiskmanager它能在关机状态下查看 vmdk 的实际占用和内部布局# 查看虚拟磁盘信息-d 是答辩describe模式不会修改磁盘内容 vmware-vdiskmanager -d /vmware/Win11/Win11.vmdk执行后输出里会包含VMFS、Capacity、Used等字段重点看实际占用是否远小于配置容量。这里逻辑是Capacity是 vmdk 标称大小Used是当前已有数据占用的块数。如果两者差距不大说明内部数据依然密布回收前必须先清理客户机。2.3 Workstation 与 ESXi 的回收路径不同别用错命令精简磁盘回收在不同产品线上有不同操作入口混用命令是运维事故的重灾区。在 VMware Workstation/Workstation Pro 里只有虚拟机关机后才能用vmware-vdiskmanager -k或-r做压缩在 vSphere/ESXi 里对 VMFS 数据存储可以执行esxcli storage vmfs unmap对虚拟机磁盘本身则常用 Storage vMotion 重写副本的方式回收。环境常用回收操作前提条件是否支持在线Workstation / Fusionvdiskmanager -k / -r关闭虚拟机否vSphere VMFSesxcli storage vmfs unmapESXi 主机可访问该存储是vSphere NFSStorage vMotion 到新存储依赖 NFS 服务器是否支持 UNMAP否迁移中可继续vSphere vSANvSAN 自动空间再平衡无需手动是注意esxcli命令只作用于 VMFS 文件系统层不能直接在 Workstation 上执行而vmware-vdiskmanager也不认识 vSphere 的远程 VMFS 数据存储。拿错命令的典型报错是“参数无效”或“无法识别文件类型”。先确认磁盘所在环境和文件系统类型再决策用哪条路径。3. Windows与Linux客户机的精简空间回收实操3.1 先在客户机把空闲块“归零”Windows 的 sdelete -z为了让宿主机识别全零块回收前必须在客户机内部把未使用区域清零。Windows 最常用的工具是 Sysinternals 的sdelete-z参数专门用于把卷的空闲空间写零。如果漏掉这一步后续 Workstation 里执行 shrink 也不会有效果因为 vmdk 中删掉的数据仍是随机数据宿主机无法区分“有用”和“已删除”。# 管理员身份运行-z 表示把空闲空间清零 sdelete -z C:建议按需调整参数-c是清理空闲空间默认行为-z是清理并清零两者对后续 shrink 的影响不同。一般回收场景用-z如果开启系统还原或卷影副本先关闭它们因为sdelete -z不会处理受保护的还原点真正能降下来的空间有限。执行时间取决于磁盘大小和写入速度100 GB 的卷可能要跑 10~20 分钟不要中途强制关机。提示Windows 的页面文件和休眠文件会锁定部分区域清零后这些文件占用的空间依然存在。回收前临时关闭休眠powercfg /h off、把页面文件设为固定大小能多回收几个 GB。3.2 Linux 客户机fstrim 和 zerofree 的使用前提Linux 下有两个方向支持 DISCARD 的块设备可以执行fstrim通知底层存储批量释放块对 VMware 虚拟磁盘这种模拟 SCSI 设备fstrim是否有效取决于驱动和虚拟控制器的支持程度。较新的 Ubuntu/RHEL 默认采用discardasync挂载选项但 Workstation 默认的 LSI Logic SAS 控制器并不总是转发 UNMAP因此最稳妥的办法是用zerofree把未分配块写零。zerofree要求分区处于只读挂载状态所以操作顺序是卸载或只读挂载数据目录然后执行清零最后重新挂载回读写模式。# 先卸载数据盘假设 /dev/sdb1 是需要清理的分区 umount /data # 以只读方式挂载避免写入产生新的脏块 mount -o ro /dev/sdb1 /data # 清零空闲块-v 显示进度 zerofree -v /dev/sdb1 # 清理完成后重新挂载 mount -o remount,rw /data参数上-n可以做试运行只输出哪些块会被清零-f用于强制跳过某些文件系统标记。需要说明的是zerofree只针对 ext2/ext3/ext4XFS 或 btrfs 请使用fstrim -v /data再看虚拟控制器是否真正转发。验证方法是在宿主机查看 vmdk 的Used是否下降。3.3 VMware Workstation 里的 Shrink 最小命令Shrink 本质是重建一个不含全零块的 vmdk 文件过程需要额外临时空间最好保证宿主机磁盘可用容量大于当前 vmdk 实际占用的 1.2 倍。先关闭虚拟机再用vmware-vdiskmanager的-k参数压缩磁盘。# 关闭虚拟机后执行-k 表示 shrink 磁盘文件 vmware-vdiskmanager -k /vmware/Win11/Win11.vmdk执行结果会显示压缩前后的空间变化。如果你的客户机里没有先执行 3.1 或 3.2 的清零这里压缩完也不会有明显收益。-r参数可以重新配置磁盘类型例如把 thick 转 thin但需要额外指定目标文件-k只做空间回收不改变磁盘类型。如果虚拟机有多个 vmdk 分卷必须逐个执行不要只压一个主磁盘。注意Workstation 的 Shrink 不是在线操作运行中虚拟机执行会报“磁盘已被锁定”。SSD 上压缩耗时较短机械盘则建议预留半小时以上的维护窗口。3.4 回收前后如何验证 vmdk 是否瘦下来验证是回收操作中容易被忽略的一环。vmdk 是稀疏文件ls -lh显示的是逻辑大小ls -ls显示的是实际占用的扇区数。压完后看实际块数是否明显下降这才是有效回收的指标。# 对比压缩前后的实际磁盘块占用 ls -lh /vmware/Win11/Win11.vmdk ls -ls /vmware/Win11/Win11.vmdk如果ls -ls输出的块数没有变化回到客户机检查是否完成清零Windows 用fsutil volume diskfree C:看可用空间Linux 用df /data看已用空间。有一点容易被误解-lh显示的逻辑大小通常不会变因为它代表虚拟磁盘容量只有某些第三方工具的“压缩”显示才会把逻辑大小改小。所以判断标准看物理块数而不是看文件大小的第二个字段。4. vSphere/ESXi环境下的VMDK精简与UNMAP回收4.1 Storage vMotion 重写最直接也最通用的回收方案在 vSphere 环境中最稳妥的回收方式是 Storage vMotion把虚拟机从一个数据存储迁移到另一个数据存储也可以是同一数据存储内的不同位置迁移过程会按源盘实际写入的块生成新 vmdk自动丢弃全零块和无效映射。这个操作对 VMFS、NFS、vSAN 均有效是跨存储协议时最省心的方案。PowerCLI 最小命令如下# 把虚拟机 MyVM 迁移到 datastore2-DiskStorageFormat 可选 Thin Get-VM -Name MyVM | Move-VM -Datastore (Get-Datastore -Name datastore2) -DiskStorageFormat Thin参数含义-DiskStorageFormat Thin控制迁移后的磁盘格式如果原来是 Thick可以顺道转成 Thin-RemoveSource控制迁移完成后是否删除源文件。执行前要确认目标数据存储有足够空间迁移过程会产生一份完整的临时副本空间不够会直接失败。注意同一数据存储内迁移也会触发 vmdk 重建但 vCenter 默认会对源副本做校验耗时更长。4.2 VMFS 上的 UNMAPesxcli 命令与参数表VMFS 数据存储在创建虚拟机时也会维护一层块分配映射删除虚拟机、删除厚置备磁盘中的某些块后VMFS 本身并不立刻把这些块返回给文件系统。从 ESXi 6.5 开始支持自动 UNMAP但很多运维团队关闭了自动回收所以手动执行esxcli storage vmfs unmap仍是常规操作。# 查看数据存储的回收参数确认是否开启自动回收 esxcli storage vmfs unmap -l # 手动对 datastore1 执行 UNMAP优先回收连续映射 esxcli storage vmfs unmap -l datastore1 -n 2000-l后面跟数据存储名称-n 2000表示执行 2000 次迭代单次迭代处理一段映射区间。执行时机建议放在业务低峰UNMAP 发出的块释放指令会对存储控制器产生压力全闪存阵列影响较小机械盘会出现秒级 IO 延迟波动。如果数据存储中还有快照先删除无用快照再执行 UNMAP否则快照引用的块不会被归还。参数作用建议值-l指定数据存储名称必须-n迭代次数视数据量100~5000-u每次迭代最多处理块数默认 0 不限可调小减缓冲击-a自动模式开关不用于手动执行注意区分esxcli storage vmfs unmap释放的是 VMFS 文件系统层的空间虚拟磁盘内部已删除文件占用的块需要先由客户机丢出 UNMAP 或清零主机层才能感知。所以 vSphere 环境下客户机里执行fstrim仍值得做它能把 vmdk 内部的空闲块转成底层全零区域随后 VMFS UNMAP 才能从文件系统层收回实际物理空间。4.3 NFS 和 vVOL 环境写零不再有意义的边界情况NFS 数据存储上的 vmdk 存在于远端文件系统VMFS UNMAP 命令无法使用。能不能回收取决于 NFS 服务器是否实现 UNMAP 或 SCSI 映射删除协议例如 NetApp 的 NFSv4.1 支持相关操作基础 Linux NFS 服务则往往不支持。对这类环境Storage vMotion 重写仍然有效但迁移到同一 NFS 导出路径时部分阵列不会打孔最好迁移到另一台存储再迁回。vVOLVirtual Volumes环境由存储阵列管理虚拟磁盘回收逻辑和 VMFS 不同阵列知道每个 vVOL 的设备映射客户机发出的 UNMAP 会直接传到阵列由阵列回收容量。这意味着不需要在 ESXi 层执行 esxcli只需确认虚拟机磁盘控制器启用“标记为 SSD”或已启用丢弃支持。边界情况在于如果存储阵列的产品文档没说明支持 vVOL 自动回收手动迁移仍是唯一可靠手段。所以遇到“回收后空间没变化”时不要只盯着 ESXi 侧命令要结合存储类型判断哪一层该做动作。5. 维持精简状态定期回收与自动化脚本5.1 客户机内部的定时清理与回收脚本空间回收不应该等磁盘告警才想起。更常见的做法是在客户机内设置每周自动清空回收站并执行写零然后在宿主机侧每月做一次压缩或 UNMAP。下面是 Linux 客户机里一个可放入 crontab 的脚本它对所有存在的 ext4 分区执行zerofree并对支持丢弃的挂载点执行fstrim#!/bin/bash # 每周日凌晨 3 点执行清理空闲空间并触发虚拟磁盘打孔 for part in $(lsblk -o NAME,TYPE -n | awk $2part {print /dev/$1}); do if findmnt $part /dev/null 21; then fstrim $(findmnt -n -o TARGET $part) || true else zerofree -v $part 2/dev/null || true fi done脚本逻辑是已挂载分区优先用fstrim在线清理未挂载分区用zerofree写零。|| true的作用是跳过不支持的分区类型避免脚本中途退出。配合 cron 执行时建议重定向输出到日志文件便于排查哪些分区没有成功回收。Windows 客户机可以用任务计划程序运行sdelete -z C:但注意避开业务高峰清零过程会产生较大的存储写流量。5.2 宿主机侧的一次性回收检查vSphere 管理员可以用 Agentless 方式直接统计数据存储上各 vmdk 的“实际占用率”把消耗最大的磁盘找出来再决定是否迁移或 UNMAPGet-Datastore -Name datastore1 | Get-VM | ForEach-Object { $disk Get-HardDisk -VM $_ $used $disk.CapacityGB $provision ($disk | Measure-Object -Property CapacityGB -Sum).Sum [PSCustomObject]{ VM $_.Name; CapacityGB $provision; AllocatedGB $used } } | Sort-Object CapacityGB -Descending | Select-Object -First 20这条命令统计的是逻辑容量不是物理占用实际查看物理占用需要到 ESXi 命令行用du -h /vmfs/volumes/datastore1/虚拟机目录。把逻辑容量与实际du结果放在一起对比能直观看出哪些虚拟机膨胀最多。定期执行这类检查后再配合 4.1 的 Storage vMotion 或 5.1 的客户机脚本就能把空间回收做成常态维护。如果某台虚拟机回收后空间又迅速涨回来优先检查客户机日志、临时目录和交换文件是否常驻写入把这些写放大源掐掉比频繁压缩磁盘更省事。本文还有配套的精品资源点击获取