KVM ゲストOSの肥大化したイメージスパースファイルを縮小・圧縮して元のサイズに戻す方法

スパースファイルの概要・特徴

スパースファイルとは、ファイルサイズをi-node内で大きめに宣言しつつ、HDDへのブロック割り当てをその宣言よりも少なく割り当てるディスクスペース節約術を使ったファイルのことです。

具体的な節約方法は、ファイル内で 0 が連続する箇所についてはブロック割り当てをしないことにより割り当てを減らすのです。これはファイルシステムの機能に依るもので、XFS以外にも NTFS や VMFS 等のファイルシステムでも対応していますが、互換性はありません。

KVM のゲストOSイメージとして使われるファイルはこのスパースファイルの恩恵を受けやすいため、よく使われる方法です。これはシンプロビジョニングというソリューション名で知られています。

この技術により、保険のためにゲストOSのHDDサイズを多めに設定しても、実際に使われない領域についてはディスク消費をしなくて済みます

スパースファイルの肥大化の原因

ですが、よくある誤解でもあるのですが『ゲストOSでファイルを削除すればKVMホスト上のイメージファイルのディスク割り当て量も減る』という解釈は間違っています

『知らぬ間に "OSから見たディスク利用量" よりも "イメージファイル自体のディスク利用量" が格段に大きくなる』といった事態に遭遇したならば、きっと『スパースファイルが肥大化した』ためでしょう。これには2つの原因があります。

原因①:削除されたファイルの割り当てブロックは 0 に書き換えられるわけではならない

例えばゲストOS内で "ファイルA" を新規作成し"test"という文字列を書き込み、このデータが"ブロックA" に割り当てられたとします。このとき、"ファイルA"を削除しても "ブロックA" は 0 に書き換えられるわけではありません。"ブロックA" が解放される(他のファイルが"ブロックA"を利用できるようになる)だけで、ブロックには "test" という文字列データは残ります

デジタルフォレンジック等のデータ復元で使われるのはこの特性だったりするのですが、まずこれが1つ目の原因です。

原因②:自動開放機能が無い

例えゲストOS内で削除したファイルのブロック領域の全てのbitを 0 に塗り替えたとしても、それが自動でスパースとして開放されることはありません。この領域をスパースにするには相応の手順が必要です。

なので肥大化したスパースファイルを元のサイズに戻すには次のステップが必要です。

  1. ゲストOSイメージファイル内の未利用領域を 0 で塗りつぶし
  2. 0 連続領域のブロック開放

リサイズ(縮小・圧縮)方法

方法を2つ紹介します。どちらも本質的には同じことをやっているので、2つやる必要は無いです。もし片方の方法で縮小できないのであれば別の原因があるはずです。

方法① virt-sparsify コマンドの利用

KVMホスト上で libguestfs-tools-c をインストールし、 virt-sparsify というコマンドを使うだけです。なお、ゲストOSは事前にシャットダウンしてから実行しましょう。

# yum install libguestfs-tools-c
# virt-sparsify before-guest.img after-guest.img

方法② dd コマンド + cp コマンド

まず、KVMホスト上で dd コマンドにより空き領域を 0 で塗りつぶします。具体的には 0 が連続したファイルを限界まで書き込み、その後に削除します。なお、このタイミングでイメージファイルのディスク利用量はi-node内で宣言したファイルサイズまで膨れ上がります。

[root@guest ~]# dd if=/dev/zero of=/tmp.dat
[root@guest ~]# sync
[root@guest ~]# rm /mnt/test/tmp.dat

tmp.dat はスパースにしたいディスクのマウント先に作成します。例えば /var がマウントされたディスクをスパースにしたいのであれば"of=/var/tmp.dat" とします。

次に、ゲストOSをシャットダウンし、cp --sparse=always でコピーすると、スパースファイルが出来上がります。

[root@kvmhost ~]# cp --sparse=always before-guest.img after-guest.img

シェアする

  • このエントリーをはてなブックマークに追加

フォローする