KVM/ProxmoxでTRIM/UNMAPを設定する:「占有」されたディスク容量を取り戻す方法

Virtualization tutorial - IT technology blog
Virtualization tutorial - IT technology blog

なぜ仮想マシンのディスク容量は使えば使うほど膨らむのか?

KVMやProxmoxで(.qcow2やLVM-thinなどの)Thin Provisioningディスクを使用している場合、次のような状況に心当たりがあるはずです。仮想マシン内で20GBのファイルを削除すると、仮想マシン内の空き容量はすぐに増えます。しかし、物理ホスト側で確認すると、仮想ディスクファイルは以前と同じ容量を占有したままで、1バイトも小さくなりません。

原因は単純です。ファイルを削除した際、ゲストOSはそのブロックを自身のインデックス上で「空き」としてマークするだけです。下層の仮想化レイヤー(KVM/QEMU)はこの変更を関知しません。ホスト側は依然としてそのブロックに重要なデータが入っていると思い込み、物理ディスク上のスペースを保持し続けます。

私は以前、500GBのNVMeドライブを搭載したIntel NUCで12台のVMを動かすホームラボを運用していました。Dockerのテストで重いイメージを頻繁にプルしては削除していた時期、VM内では150GBの空きがあると表示されているのに、NVMeドライブは容量不足で真っ赤になっていました。その時、TRIM/UNMAPを有効にするのを忘れていたことに気づきました。

TRIM(SSD用)またはUNMAP(SCSI用)は、仮想マシンと物理マシンの間の「共通言語」です。ゲストOSがホストに対して「ねえ、このブロックはもう不要だから回収して!」と伝える役割を果たします。その結果、物理ディスクの容量が自動的に縮小されます。

ステップ1:仮想ハードウェアの設定

TRIMコマンドは古いコントローラー経由では転送できません。このプロトコルをサポートする適切なドライバーを選択する必要があります。

Proxmox VEでの設定

ProxmoxのWebインターフェースで、VMのHardwareセクションに移動し、次の2点を確認します:

  • SCSI Controller: VirtIO SCSI または VirtIO SCSI single に変更します。これが現在の最適解です。
  • Hard Disk: Bus/Deviceが SCSI になっていることを確認します。

最重要ポイント:ディスクを編集する際、Discardのチェックボックスをオンにする必要があります。これがUNMAPコマンドを仮想化レイヤーに通過させるためのスイッチとなります。

ProxmoxでDiscardを有効化

純粋なKVM/QEMU構成(virshを使用)

コマンドライン派の方は、virsh edit <vm_name> コマンドで仮想マシンのXMLファイルを編集します。<disk> セクション内の <driver> タグを探し、discard='unmap' 属性を追加してください。

<disk type='file' device='disk'>
  <driver name='qemu' type='qcow2' discard='unmap'/>
  <source file='/var/lib/libvirt/images/ubuntu-server.qcow2'/>
  <target dev='sda' bus='scsi'/>
</disk>

注意:これらのハードウェア変更を反映させるには、仮想マシンを完全にシャットダウン(Shutdown)してから再起動する必要があります。

ステップ2:ゲストOS内での有効化

ホスト側の準備ができたら、次は仮想マシン内のOSに「掃除」の仕方を教える番です。

Linuxゲストの場合

連続TRIM(削除するたびに即座にクリーンアップ)と定期TRIMの2つの選択肢がありますが、大きなファイルを削除した際のI/Oパフォーマンスの急激な低下を避けるため、定期TRIMをお勧めします。

UbuntuやDebianなどの最近のディストリビューションの多くは、fstrim.timer を使用しています。次のコマンドで確認してください:

# タイマーが動作しているか確認
systemctl status fstrim.timer

# 動作していない場合は有効化
sudo systemctl enable --now fstrim.timer

すぐに効果を確認したい場合は、sudo fstrim -av コマンドを実行してシステムに強制的にクリーンアップを行わせることができます。画面に /: 15 GiB... trimmed と表示されれば、ホスト側の実際の空き容量が15GB増えたことになります。成功です!

Windowsゲストの場合

Windowsは通常、VirtIO SCSI drivesをSSDとして自動的に認識します。管理者権限のコマンドプロンプトでTRIMの状態を確認してください:

fsutil behavior query DisableDeleteNotify

結果が 0 であれば、準備完了です。もし 1 であれば、fsutil behavior set DisableDeleteNotify 0 コマンドを実行して有効化します。

ステップ3:結果の検証

仮想マシンの表示を信じるだけでなく、ホスト側の実際の数値を確認しましょう。物理サーバー上で du コマンドを使用して、.qcow2ファイルの実際の占有容量を確認します:

# ディスク上の実際の占有容量
du -sh /var/lib/libvirt/images/my-vm.qcow2

# 最初に定義された仮想容量
ls -lh /var/lib/libvirt/images/my-vm.qcow2
</pre>

正しく設定されていれば、du コマンドの結果は元の仮想容量よりも大幅に小さくなっているはずです。また、Linuxゲスト内で lsblk -D を実行し、DISC-MAX 列に値が表示されていれば(0以外)、インフラがTRIMを正しくサポートしていることを意味します。

現場からの実戦経験

  • SSD Emulation: Proxmoxでは、Windows VMに対してこのオプションを有効にしてください。これにより、Windowsはドライブを低速なHDDではなくSSDとして認識し、デフラグなどの動作を自動的に最適化します。
  • ZFS Storage: ZFSを使用している場合、容量の解放に数秒から数分の遅延が生じることがあります。これはCopy-on-Writeメカニズムの特性であり、心配する必要はありません。
  • バックアップ時のメリット: これは非常に大きな利点です。不要なデータブロックを処理しなくて済むため、バックアップファイルが軽量になり、圧縮プロセスも高速化されます。

わずか数ステップの設定で、高価なSSDの容量を1GBたりとも無駄にすることなく最大限に活用できるようになります。システムの最適化が成功することを願っています!

Share: