仮想ディスクの未使用領域が解放される仕組み
仮想環境のストレージ空き容量を管理する上で、未使用領域の解放に関する各レイヤの仕様を理解しておくことは重要です。
本記事は、ゲストOS上で削除したファイルの容量分、ストレージの空き容量が確保されるまでの仕組みをとめたものです。対象は主にシンプロビジョニング(スパース)が有効なストレージ環境を使用するVMware vSphere 6系や7系以降ですが、仕組みは他の仮想環境でも同様です。
なお本記事では、圧縮機能や重複排除機能等、またストレージ自体やバックアップの設計については触れていませんが、それらを考慮する上でも本記事の内容は基礎的な要素の一つです。
注記
本記事では、ゲストOSが未使用領域をゼロクリアする方式について言及していますが、近年の環境は基本的にUNMAPやTRIMがサポートされているので、未使用領域を解放するという目的においてはOS側でゼロクリアを実行する必要性はありません。
本記事の内容は、ゼロクリアに言及しているため、少し古い実装についての説明ということになります。ただし、仮想環境におけるストレージレイヤというものの基本的な概念自体は変わっておらず、また古い実装についての記事があること自体は問題ではないので、改変せずそのままにしておきます。
よって、本記事のゼロクリア部分は、環境に応じ適宜UNMAPやTRIMに読み替えていただけたらと思います。
機会があればUNMAPやTRIMについては別記事にまとめます。
本記事の目的
- ゲストOS側でディスク使用量を削減した際に、ストレージの空き容量が確保されるまでの仕組みを把握する。
基本
おおまかな理解
仮想環境において、特に高集約化を図る場合、ストレージ利用効率を高めるためシンプロビジョニング機能が使用されることが多いです。
ただし、仮想マシンに割り当てたディスク容量の合計が、ストレージの物理容量を超える設計(オーバーコミット)になることもあるため、ストレージ空き容量を適切に管理することは重要です。
仮想環境では、主に以下の2か所でシンプロビジョニング機能が使用されます。
- シンプロビジョニング(スパースファイル)が有効な仮想ディスク(仮想基盤のレイヤ)
- シンプロビジョニングが有効なストレージボリューム(仮想基盤が使用するストレージのレイヤ)
本記事では、上記環境における下記動作の仕組みについて記載します。
- ゲストOS上で不要ファイルを削除し、(ゲストOSから見て)ディスク空き容量を十分に確保したのに、仮想基盤上で仮想ディスクのサイズが小さくならない。
- ゲストOS上で不要ファイルの削除後、仮想ディスクのサイズを小さくしたい場合には、ゲストOS上で未使用領域のゼロクリアを行ってから、仮想基盤上で未使用領域の解放(vSphereの場合はpunchzero)を行う必要性がある。
- 最近のVMFS(6以降)では、未使用になった領域に対するストレージボリューム上の割り当てを自動的に解放(マッピング解除)し、ストレージボリューム上の空き領域を確保してくれる。
これらの仕組みは、長期間に渡ってディスクの書き込みと削除が繰り返し行われるシンプロビジョニング環境では把握しておいた方が良いものです。
ゲストOS上で不要ファイルを削除したのに、仮想ディスクのサイズが小さくならない
まず、なぜゲストOS上で不要ファイルを削除しただけでは仮想ディスクのサイズが小さくならず、ストレージの空き容量を確保できないのかについて記載します。
- (図中の左) ゲストOS上でファイルを削除した場合、そのインデックス情報が削除されるだけで、ファイルのデータは通常残ります。別の言い方では、ゲストOSが使用するファイルシステム(WindowsであればNTFS等)のメタデータにおいて、そのファイルが存在しないものとして扱われるようになるだけで、ディスクに書き込まれたデータ自体は削除されません。
- (図中の中央) このままでは、VMFS(仮想基盤のファイルシステム)上は、そのゲストOSの仮想ディスクサイズが小さくなることはありません。仮想基盤としては、ファイルを削除したことも、それによって空き領域を増やせることも検知できないためです。
- (図中の右) ストレージ側のボリュームがシンプロビジョニング対応であったとしても、VMFS上で仮想ディスクのサイズが小さくならないのであれば、その使用量が削減されることはありません。
ゲストOS上でのゼロクリアと、仮想基盤上での未使用領域の解放により空き容量を確保可能
- ゲストOS上で削除されてもディスクに残ったままになっているファイルのデータを削除する方法は、ゼロクリア(0埋め)です。Windowsの
SDelete
コマンド、Linux/Unixではdd
コマンドによりゼロクリアが可能です(後述)。
ゼロクリアにより、対象ファイルシステムの未使用領域全てに0が書き込まれます。0を書き込んでも、あくまで未使用領域は未使用のままなので、ゼロクリアの前後で基本的にファイルシステムの使用量は変化しません(ゼロクリア処理中は一時的に使用量が増える場合があります(細かい話なのでこれも後述))。 - ゼロクリアが実行された仮想ディスクに対し、仮想基盤上でpunchzero (
vmkfstools -K
コマンド)を実行することにより、その仮想ディスクの容量を小さくすることができます。仮想ディスク容量のうち、ゼロクリアされた領域(未使用領域)分の容量は削減され、それ以外の使用済み領域分の容量のみが残ります。仮想ディスクの容量が小さくなった分、VMFS上の空き領域が増えます。
このような仮想ディスクのゼロクリア領域を解放する方法は、仮想環境ごとに異なります。vSphereの場合はvmkfstools -K
コマンドですが、Hyper-Vの場合はOptimize-VHD
コマンドレット、VirtualBoxの場合はvboxmanage modifyhd [UUID] --compact
コマンドがあります。
この他に、Storage vMotionにより同様にゼロクリア領域を解放できる場合がありますが、条件等の詳細はVMware社のdocsに記載があります。
ゼロクリア以外に、TRIMやUNMAPといった処理もありますが、本記事では記載していません。 - VMFSの空き領域が増えると、(VMFS6以降の場合は)自動的にストレージ側でもその分の容量が解放されるよう処理され、ストレージ上のボリュームの空き領域が増えます。
この処理はストレージに対するSCSI UNMAP(マッピング解除)やReclaim(再クレーム、レクラメーション)と呼ばれ、VMFS6未満の場合はesxcli storage vmfs unmap
コマンドにより手動実行する必要性がありましたが、VMFS6から自動的に実行されるようになりました。詳細はVMware社のdocsに説明があります。この処理は、ストレージ側のボリュームにおいてシンプロビジョニングが有効であり、マッピング解除操作をサポートしている場合に実行可能です。
上記のように、未使用領域の解放に関する各レイヤの仕様を理解することで、VMのディスク使用量を削減した際にストレージの空き容量が確保されるまでの仕組みを把握できます。
詳細
SDelete、ddによるゼロクリア
ゲストOS上で以下のコマンドを実行することで、未使用領域のゼロクリアが可能です。
これらのコマンドの実行時には、一時的にファイルシステムの空き容量が枯渇するため、重要なデータの書き込みエラーによるデータロス等が発生しないよう、必要に応じサービス停止して実行することをお勧めします。
WindowsでCドライブの未使用領域をゼロクリアする場合、以下のコマンドを実行します。
> SDelete -z C:
SDeleteコマンドは以下ページから入手できます。
– MicrosoftのSDelete配布ページ
仕組みは、上記URLの解説を理解しきれてはいないので一部推測になりますが、指定したドライブの空き領域と同じだけのサイズのファイルを作成(おそらくゼロ書き込み)し、その後それを削除するものと思われます。未使用領域を直接操作することは難しいので、そのような仕組みになると考えられます。
Linuxで/(ルート)パーティションの未使用領域をゼロクリアする場合、以下のコマンドを実行します。
# dd if=/dev/zero of=/zerofile; rm -f /zerofile
/dev/zeroの内容(0)を任意のファイル(/zefofile)に書き出した後、空き容量が無くなり次第dd
コマンドがエラーで終了します。その後すぐにrm
コマンドで作成したファイルを削除するというものです。
まとめ
仮想環境におけるレイヤごとの容量の消費と解放に関する基本的な仕組みについてまとめてみました。
ゼロクリア以外に、TRIM(fstrim等)やUNMAPといった処理もあるので、機会があれば別記事にまとめたいと思います。