Windows仮想マシン内の不要になった300 GBの古いデータベースを削除したにもかかわらず、vSphere Clientを確認するとDatastoreの使用率が92%で警告(赤色)のままだったという経験はありませんか?空き容量は1メガバイトたりとも戻ってきません。これは、シンプロビジョニング(Thin Provisioning)ディスクを扱う仮想化インフラの管理者であれば誰もが一度は直面する典型的なトラブルです。
この原因は、ゲストOS(Guest OS)のファイル削除メカニズムにあります。ファイルを削除しても、ゲストOSはインデックス管理テーブル(NTFSのMFTやext4/xfsのInodeなど)を更新するだけで、対象ブロックを「上書き可能」としてマークするに過ぎず、データをゼロクリア(完全消去)するわけではありません。下位層のハイパーバイザーであるESXiには領域が解放された通知が届かないため、ESXiはVMDKファイルの割り当てサイズを維持し続けます。その結果、時間の経過とともに仮想ディスクは肥大化し続け、ストレージ(SAN/NAS)の実容量を圧迫してしまうのです。
私の運用環境では、8ノードのESXiクラスタ上で140台以上の仮想マシンが稼働し、16GbpsのファイバーチャネルSAN経由でDell Unityストレージに接続されています。大規模なデータクリーンアップを行うメンテナンス時には、この手順を実施して数テラバイト規模の無駄な領域を回収しています。
代表的な3つの容量回収・解放アプローチ
仮想マシンの稼働状態(起動中または停止中)やDatastoreの構成に応じて、主に以下の3つのアプローチがあります:
- 方法1:ディスク形式の変換を伴うStorage vMotion — 仮想マシンを別のDatastoreへ移行する際、一時的にThick Eager Zeroedに変換したのち、再度Thinに戻す。
- 方法2:OS内でのゼロ埋め(Zeroing)+vmkfstoolsによるディスク縮小 — 仮想マシンの空き領域にゼロを書き込んだ後、ESXi Shell上でpunch zeroコマンドを実行する。
- 方法3:SCSI UNMAP(esxcli)の手動実行またはVMFS-6の自動回収 — SCSI UNMAPコマンドを発行してDatastoreの未使用ブロックをSAN/NASストレージアレイへ返却する。
各アプローチのメリット・デメリット詳細比較
1. Storage vMotion
- メリット:すべての操作をvCenterのGUI上で完結可能。仮想マシンを稼働させたまま無停止(Zero Downtime)で実施できる。
- デメリット:仮想マシンのプロビジョニングサイズ以上の空き容量を持つ別のDatastoreが必要。移行プロセスでストレージネットワークの帯域を大量に消費する(スループットが300〜500 MB/sに達することもある)。
2. ゲストOSでのゼロ埋めとvmkfstools punch zeroの組み合わせ
- メリット:
-flat.vmdkファイルのサイズを実際の使用容量まで確実に縮小できる。大量のデータを削除した単一の仮想マシンに対して極めて効果的。 - デメリット:仮想マシンの停止(ダウンタイム)が必要。事前のゼロ埋めフェーズでストレージのIOPS負荷が高まり、一時的にVMDKファイルがプロビジョニング最大サイズまで膨張する。
3. SCSI UNMAPコマンド(esxcli)およびVMFS-6の自動UNMAP機能
- メリット:仮想マシンの停止が不要。VMFS-6では非同期領域解放(Asynchronous Space Reclamation)としてバックグラウンドで自動実行され、帯域も25 MB/s〜100 MB/sに適切に制御される。
- デメリット:Datastoreレベルの領域回収に限定される(仮想マシン自体の完全削除やスナップショット削除時など)。仮想マシン内部で領域のゼロ化やトリムが行われていない場合、VMDKファイル自体は縮小されない。
実務における使い分けのベストプラクティス
- メンテナンスウィンドウ(ダウンタイム)を確保できる場合:方法2を採用します。特定の仮想マシンのVMDKファイルを極限まで縮小する最も確実な手法です。
- 停止が許されない24時間365日の本番環境:一時バッファ用のDatastoreに十分な空きがある場合は、Storage vMotionを活用します。
- 検証環境などで数百GB規模の仮想マシンを5〜10台まとめて削除した場合:
esxcli storage vmfs unmapコマンドを実行し、SAN/NASストレージ側へ即座に利用可能容量を反映させます。
ステップバイステップの実施手順
ステップ1:仮想マシン内部の未使用ブロックをクリーンアップ
まず、ESXiがどのブロックが空き領域であるかを認識できるように、未使用領域をゼロで埋める必要があります。
Windows Serverの場合:Microsoft Sysinternalsの公式ツール「SDelete」をダウンロードします。PowerShellを管理者権限で実行します:
# -zオプションでCドライブの全空き領域にゼロを書き込む
sdelete64.exe -z C:
注意:SDeleteの実行中、VMDKファイルはプロビジョニングサイズ(Provisioned Size)の上限まで一時的に肥大化します。実行前にDatastoreの空き容量が十分にあることを必ず確認してください。
Linux(RHEL、Ubuntu、Rocky Linuxなど)の場合:
# fstrimコマンドを実行して未使用ブロックを破棄(仮想マシンがSCSIコントローラに対応している必要があります)
sudo fstrim -av
ストレージまたは構成がTRIMに直接対応していない場合は、ゼロ埋めの一時ファイルを作成した後に削除します:
# ディスクが満杯になるまでゼロを書き込み、完了後にファイルを削除
dd if=/dev/zero of=/var/tmp/zero.fill bs=1M status=progress; rm -f /var/tmp/zero.fill
ステップ2:vmkfstoolsによるVMDKファイルの縮小(オフライン作業)
対象の仮想マシンをシャットダウンします。仮想マシンが配置されているESXiホストにSSH接続し、該当ディレクトリへ移動します:
# 1. 仮想マシンのディレクトリへ移動
cd /vmfs/volumes/Datastore_SSD/AppServer01/
# 2. スナップショットの確認(スナップショットが存在しないことが必須条件)
ls -l *delta* *sesparse*
# 3. ディスク縮小コマンドの実行(punch zero)
vmkfstools -K AppServer01.vmdk
vmkfstools -Kコマンドは仮想ディスクファイル全体をスキャンします。ゼロの連続する領域を検出すると、ESXiはメタデータポインタを削除して物理ブロックを解放します。これにより、実データが120 GBしか入っていない500 GBの仮想ディスクは、Datastore上で正確に120 GBまで縮小されます。
ステップ3:Datastoreの解放領域をSANストレージへ返却(UNMAP)
VMDKファイルを縮小した後や、大容量の仮想マシンを完全に削除した後は、物理ストレージアレイ(SAN)に対してブロックの解放を通知します:
# Datastore一覧を表示してVolume UUIDを取得
esxcli storage filesystem list
# ストレージアレイのI/O負荷を抑えるためブロックカウント200でUNMAPを実行
esxcli storage vmfs unmap -u 652a9f14-38b81234-5678-001b21xxxxxx -b 200
1ブロックは1 MBに相当します。-b 200オプションを指定することで200 MB単位に分割して処理され、同時に稼働しているSANシステムのI/Oキューの枯渇を防ぎ、安全に実行できます。
トラブルを防ぐための3つの重要原則
- vmkfstools実行前に必ずスナップショットを完全削除する:デルタスナップショットが存在する状態でベースディスクに対して
vmkfstools -Kを実行すると、スナップショットチェーン全体が破損する重大なリスクがあります。 - ブロックカウント(-b)を過大に設定しない:500を超える値を指定すると、SANのキュー深度(Queue Depth)が逼迫し、同一LUN上にある他の仮想マシンのレイテンシが大幅に悪化する恐れがあります。
- VMFS-6を標準として採用する:新規に作成するDatastoreは原則VMFS-6でフォーマットしてください。自動UNMAPがバックグラウンドで動作するため、夜間の手動コマンド実行作業を削減できます。

