ESXi から Proxmox VE (以下 PVE)に移行しようとして、検証を遅々として進めています。PVE は(というか Linux は)VMFS6 上の vmdk を直接扱うことはできないようなので、一旦何かしらの変換をして扱う必要があります。
ESXi の VM をエクスポートして OVF 形式に変換し、それを PVE でインポートするのがサポートされた方法のようですが、そうすると元の vmdk と同じサイズの一時ディスクが必要になってしまうので嬉しくありません(最近 HDD 高いし)。というわけでディスクイメージを直接変換し、VM そのものの設定は面倒ですが手作業で行うことを考えます。VM の数が少ないならこれでもいいでしょう。
ディスクイメージを直接変換するには、ESXi の VMFS6 を PVE 上で vmfs6-tools で読み込み専用マウントし、vmdk ファイルを qemu-img コマンドで qcow2 形式なり raw 形式に変換します。vmfs6-tools は Debian のパッケージリポジトリから取ってくる形になります。
root@pve:~# apt install vmfs6-tools (中略) root@pve:~# vmfs6-fuse /dev/sdb8 /mnt/vmfs VMFS version: 6 root@pve:~# qemu-img convert -f vmdk -O qcow2 /mnt/vmfs/somevm/somevm.vmdk ~/somevm.qcow2
…というのが通り一遍な話なんですが、検証していて気づいたことがあります。
まず、thin provisioning、lazy zeroed thick provisioning、eager zeroed thick provisioning の vmdk について、それぞれにほぼ同じデータを書いて(具体的には Ubuntu をインストールした)、その後 qcow2 形式に変換しました。すると以下のようになります。
root@pve:~# time qemu-img convert -f vmdk -O qcow2 /mnt/tmp/ubuntu-eager/ubuntu-eager.vmdk /mnt/pve/testdir/images/ubuntu-eager.qcow2 real 20m43.444s user 0m15.347s sys 1m3.470s root@pve:~# time qemu-img convert -f vmdk -O qcow2 /mnt/tmp/ubuntu-lazy/ubuntu-lazy.vmdk /mnt/pve/testdir/images/ubuntu-lazy.qcow2 real 20m7.457s user 0m15.473s sys 1m3.892s root@pve:~# time qemu-img convert -f vmdk -O qcow2 /mnt/tmp/ubuntu-thin/ubuntu-thin.vmdk /mnt/pve/testdir/images/ubuntu-thin.qcow2 real 6m0.489s user 0m11.766s sys 1m0.454s root@pve:~# ls -lh /mnt/pve/testdir/images/ total 15G -rw-r--r-- 1 root root 4.9G Oct 10 20:58 ubuntu-eager.qcow2 -rw-r--r-- 1 root root 4.9G Oct 10 21:20 ubuntu-lazy.qcow2 -rw-r--r-- 1 root root 4.9G Oct 10 21:27 ubuntu-thin.qcow2
できる qcow2 ファイルのサイズが同じなのは当然予想できたことですが、thin だけが処理が早く、lazy と eager は時間がかかっています。lazy なのに時間がかかるのはおかしいな?と思って vmdk の backing file (実際のディスクのデータが入っているファイル。xxx-flat.vmdk という名前)を dd で読んでみても、やっぱり同じ傾向になります。
root@pve:~# time dd if=/mnt/tmp/ubuntu-eager/ubuntu-eager-flat.vmdk of=/dev/null bs=1M 65536+0 records in 65536+0 records out 68719476736 bytes (69 GB, 64 GiB) copied, 1244.46 s, 55.2 MB/s real 20m44.479s user 0m0.331s sys 0m59.913s root@pve:~# time dd if=/mnt/tmp/ubuntu-lazy/ubuntu-lazy-flat.vmdk of=/dev/null bs=1M 65536+0 records in 65536+0 records out 68719476736 bytes (69 GB, 64 GiB) copied, 1208.32 s, 56.9 MB/s real 20m8.364s user 0m0.322s sys 1m0.591s root@pve:~# time dd if=/mnt/tmp/ubuntu-thin/ubuntu-thin-flat.vmdk of=/dev/null bs=1M 65536+0 records in 65536+0 records out 68719476736 bytes (69 GB, 64 GiB) copied, 353.017 s, 195 MB/s real 5m53.066s user 0m0.215s sys 0m51.034s
lazy なら vmdk の大半を占める、まだ書き込みがされていない(つまりゼロのままであるはずの)領域は、実際には読み込みをしない挙動になることが期待されます。しかし、この遅さは明らかに何かしら読み込みを行っていますし、実際 iostat で見ると読み込みを行っているのが分かります。
上の例では ESXi をインストールした HDD はゼロを書いて消去したものを使っていました。ではランダムデータを書いて消去したものを使ったらどうなるでしょうか。なお、今度は Ubuntu はインストールせず、vmkfstools で作成した直後の vmdk を対象としています。
root@pve:~# time qemu-img convert -f vmdk -O qcow2 /mnt/vmfs/dirty-lazy.vmdk ~/dirty-lazy.qcow2 real 20m13.763s user 0m10.469s sys 1m35.590s root@pve:~# time qemu-img convert -f vmdk -O qcow2 /mnt/vmfs/dirty-eager.vmdk ~/dirty-eager.qcow2 real 20m41.797s user 0m15.293s sys 1m0.150s root@pve:~# time qemu-img convert -f vmdk -O qcow2 /mnt/vmfs/dirty-thin.vmdk ~/dirty-thin.qcow2 real 0m51.079s user 0m11.715s sys 0m39.344s root@pve:~# ls -lh total 65G -rw-r--r-- 1 root root 193K Dec 14 19:24 dirty-eager.qcow2 -rw-r--r-- 1 root root 65G Dec 14 18:44 dirty-lazy.qcow2 -rw-r--r-- 1 root root 193K Dec 14 19:44 dirty-thin.qcow2
lazy だけデカいです。これは qcow2 イメージにはゼロでない値が保存されている、つまり lazy な vmdk を読んだときにゼロでない値を読んだということです。
lazy な vmdk は、ディスクの領域は予約するが、その領域にゼロを書き込む代わりに、その領域はまだ書き込みが行われていないので読み込んだらゼロを返せとフラグを立てることで lazy なゼロ化を実現しています(予約したうえで実際にゼロを書き込むのが eager zeroed、予約自体をしないのが thin)。今回ゼロでない値を読んでいるということは、上記のフラグを認識せず、予約した領域のデータをそのまま読んでしまっていると見られます。この状態で変換をかけると、ファイルシステムレベルで見せてはいけないVMホストの生ディスクの様子がゲストから見えてしまうことになり、セキュリティ上の問題をはらんでいます。もしこれを気にするのであれば、ESXi 上で eager zeroed に変換する (vmkfstools -k) か thin に変換する (vmkfstools -K) といった処置をしておく必要があります。
no comment untill now