p2v 物理サーバのHDDイメージを仮想マシンのイメージに変換

最近もっぱら奴隷のように仮想化を調べていて、物理サーバの引越しがお題目。仮想化!仮想化ァ!

virt-p2v を使う方法

以前は↑のvirt-v2vのURLからvirt-p2vのisoイメージが直接downloadできたらしい?けど、今はなくなっているので、自力で作らないといけない。

そのうちRHEL 6.X あたりで取り込まれそうだけど、現時点でさっくり作りたければ、fedora 16を使えば良い。

virt-p2v.iso の作成
# yum install virt-p2v-image-builder rubygem-virt-p2v virt-v2v
# virt-p2v-image-builder

ただ、このvirt-p2v-image-builder なんでか知らないけど64bitOSで実行すると失敗するらしいので、
fedora 16 の32bitで実行する。あとは出来上がったvirt-p2v.iso を焼いて、サーバに突っ込んで起動する。

virt-p2v はディスクイメージを吸いだして、ssh経由で、他のサーバにアップロードする仕組みになっているので、その受け皿となるサーバの準備も必要

サーバの設定

virt-p2vで起動したOSはrootでsshログインしようとしてくるので、(userが固定で変えられなかった)のでsshd_config、hosts.allow等を適当に設定。

# yum install virt-v2v

/etc/virt-v2v.conf を設定して、virt-p2v-serverを起動。libvirtのstrageの名前(virsh pool-list に表示されるもの)や、formatでqcow2、raw などを設定。

virt-p2v-serverが起動していなかったり、設定がおかしいとエラーメッセージが出る。
virt-p2v-serverはクライアントがsshログイン時に自動で実行するものなので、サーバ側で手動で実行はしなくてよい。

virt-p2vエラーになる

さっそく動作試験をしようと、仮想マシンで2GBぐらいのイメージをqcow2で作って、virt-p2vでブートさせてイメージをコピーしていると、、、、"Error reading data in send_data: Input/output error" などと言って途中で失敗しよる。virt-v2vを起動しているサーバのmessagesには

Feb  4 18:34:21 hoge virt-v2v[2457]: FATAL: Error receiving data:
Feb  4 18:34:21 hoge virt-v2v[2457]: p2v-server exited.

と出る。うーん。virt-p2v-serverがperlだったのでソースを見ると

469     while($total < $length) {
470         my $in = read(STDIN, $buf, $length, $total)
471             or err_and_die(__x('Error receiving data: {error}', error => $@));
472         logmsg DEBUG, "Read $in bytes";
473         $total += $in;
474     }

となってるけど、なんでreadで失敗するんだろ。イメージをsparseファイルで作ってるから?関係ないよなー。

実機のサーバでやってみたけど、同じように途中で失敗するので一旦諦めた。

ddを使う

結局のところp2vはHDDのイメージをごっそり持っていって、あとごにょごにょしてるだけなので、virt-p2vなんか使わなくてもddと万能のnc様で解決すんじゃね?と思ってやってみる。

サーバ側

適当なportでlisten

# nc -l 10000 > disk.img
クライアント側

適当なlinuxのlivecdを使ってcdブートする。ddのbsはdefaultの512 byteは小さすぎるので、適当に大きい値を指定。1M, 10M, 64M, 128M でやってみたけど、どの値も転送速度は100Mbyte/sec程度で代わりがなかった。(NICの速度と、サーバのdisk i/oで頭打ち?)

# dd if=/dev/sda bs=1M | nc server.ip.address 10000
kvmで起動させる

仮想マシンのHDDイメージをさっきncで受信したdisk.img に指定して起動。。。

イメージファイルの編集

の前に、元のdiskのfstab(/dev/sda1) がkvm上の認識(/dev/vda1) と異っていたのでgrubの起動で失敗した。libguestfsを使って、イメージファイル内のfstabを直接編集したら無事起動できた。

おまけ: イメージの変換

ddで吸いだしているので、virt-p2vのrawモードと同様に使用しているデータ量に関係なく、元のHDDと同じサイズのイメージが出来上がってしまう。そこでqemu-img convert でqcow2にしたら、わずかだけどイメージのサイズが減った。

# ls -lhs disk.img 
150G -rw-r--r-- 1 root root 150G  2月  4 13:16 2012 disk.img
# qemu-img info disk.img
image: disk.img
file format: raw
virtual size: 149G (160041885696 bytes)
disk size: 149G
# qemu-img convert -f raw disk.img -O qcow2 disk_qcow2.img
#### => 2時間かかった^^;;;;
# ls -lh disk_qcow2.img 
-rw-r--r-- 1 qemu qemu 121G  2月  4 16:30 2012 disk_qcow2.img
# qemu-img info disk_qcow2.img
image: disk_qcow2.img
file format: qcow2
virtual size: 149G (160041885696 bytes)
disk size: 121G
cluster_size: 65536
変換にかかる時間

virt-p2vのほうは成功してないので不明。(dd&ncとあんま変わらんと思うけど)
ddで吸いだして、ncで転送をしているだけなので、おおきくはHDDの容量、NICの速度、Disk I/Oで決まるのかな。

シーケンシャルなwriteなので、ざっくり50MByte/secだとすると、
160GBのHDDの場合は160GB / (50Mbyte/sec) = 3200sec (約60分)
250GBのHDDの場合は250GB / (50Mbyte/sec) = 5000sec (約80分)
ってところ?適当。

追記

コメントいただいている通り、ssh+tarだと実質つかっているファイルだけの転送なので早くいけますね。
(ddと違ってイメージごと持っていかないので、移行先でパーティション作成などはあらかじめやっておく必要あり)