技術

XenServer 物理マシン1台で仮想マシンを無停止でコピーする方法

追記
XenServerのバージョンが5.5に上がり、XenCenterに稼働中の仮想マシンのスナップショットをとる機能と、さらにそのスナップショットから新たな仮想マシンを立ち上げたりテンプレートとして外部にバックアップする機能が追加されたため、GUIですべての操作が完結するようになりました。特殊な事情がない限り下記のような作業は必要ないと思われます。

XenServerライフ、エンジョイしていますか?

うちのXenServer、無償化の公式発表前に入れたので旧Enterprise Editionの試用版として動作してる状態でライセンスの残り期限が十数日という状態になってました。
昨日、Hotfix3と新しいライセンスファイルをインストールしまして、無事Enterprise Editionの表記が消え、ライセンスも約1年延長されました。
(1年経ったらどうなるんでしょうか?Citrixのアンケートに答えて再度ライセンスファイルをダウンロードする形になるんでしょうか?)

XenServerの良いところは、XenServer自体よりもXenCenterというWindows上で動く管理ソフトの出来の良さだと思っておりますが、問題点も少々あります。
LinuxやMacOSXで動かないところとか言ったら元も子もないのでそこはグッとこらえるとして、やっぱり個人的に一番キツイ問題点は、稼働中の仮想マシンのコピーが出来ないところです。

そのコピーも一瞬で終わるのなら、一度仮想マシンを落としても良いかなと思うのですが、コピーはコピーなので仮想HDDのサイズが数十ギガとかになると結構時間が掛かってしまいます。

まぁ、計画的な皆さんは仮想マシンを本番に投入する前にコピーを取ったり、同じサーバー環境を手軽に再現できる別の仕組みなんかを持ってらっしゃると思いますが、私はどうも行き当たりばったりなタチでございまして、コピーを取りたいと思った仮想マシンが絶賛本番稼働中ということも少なくありません。

そこで、物理マシン1台のみで稼働してるXenServerの仮想マシンを無停止でコピーする方法を考案しました。
まぁ、XenやXenServerがどういう仕組みで動いてるか知ってる方はすぐ思いつく方法だと思いますが、私自身が忘れっぽいのでここに書いておきます。

XenServerのローカルのHDDに保存される仮想マシンの仮想HDDは、LVMで管理されているLVとして存在しています。
ちなみに、NFS上に保存する場合は、VHD形式(MSのVPCで使われてるアレです)のファイルとして保存されます。

でまぁ無停止で仮想HDDのコピーをするために、簡単に言うとLVのスナップショット機能を使います。
あと、LVからLVへ直接コピーをする方法が分からなかったため、一時的な作業用の領域を使います。
つまり、今から書く方法では例えば80GBの仮想HDDをコピーするために物理HDDに160GB以上の空き領域が必要になります。
(外付けUSBHDDやNFSを利用する場合はこの限りではありません。物理マシン1台という範疇からは外れてしまいますが。)

手順1:まず、コピー先となる仮想マシンを作成します。
コピー元の仮想マシンと同じ設定で作成してください。XenCenter上で作成してOKです。
(XenCenterの制限からか、一度通常のインストールプロセスを開始する必要があります。じゃないと仮想マシンが起動しないので。仮想マシンが起動したらすぐに停止してかまいません。)

手順2:コピー元とコピー先の仮想マシンの仮想HDDに分かりやすい名前を付けます。
XenCenterからやっちゃってください。仮想マシン名と全く同じ名前は逆に分かりづらくなるのでおすすめ出来ません。

手順3:コピー元とコピー先の仮想HDDのLVM的なuuidを調査する。
XenServer自体にsshでログインするか、XenCenterのコンソールを使うかして、以下のコマンドを実行。

[root@xs ~]# xe vm-disk-list –multiple
Disk 0 VBD:
uuid ( RO) : 0d70a367-6d3d-138d-1f69-db82c1xxxxxx
vm-name-label ( RO): MyWebServerCopy
userdevice ( RW): 0

Disk 0 VDI:
uuid ( RO) : 197bae16-d1f3-4a64-ba8f-41d2cdxxxxxx
name-label ( RW): MyWebServerCopy HDD
sr-name-label ( RO): Local storage
virtual-size ( RO): 8589934592

Disk 0 VBD:
uuid ( RO) : 9d947eab-57a8-82b4-e900-194cf2xxxxxx
vm-name-label ( RO): MyWebServer
userdevice ( RW): 0

Disk 0 VDI:
uuid ( RO) : e60e9a37-d52a-40a1-83d4-cfa26dxxxxxx
name-label ( RW): MyWebServer HDD
sr-name-label ( RO): Local storage
virtual-size ( RO): 8589934592

name-labelを参考にコピー元とコピー先のLVのuuidを控えておく。
間違えて逆で控えないよう注意!

手順4:一時的なコピー先の領域を確保する。
ローカルのHDDで領域が確保できない場合は外付けのUSBやNFSをマウントしても良いと思う。
XenServerは基本CentOSっぽいので何でも出来る。
が、ここではタイトルの「1台」にこだわってローカルのHDDに新たにLVを作成することにする。

まず、LVを作成するためのVG名を調べる。

[root@xs ~]# ls /dev | grep VG
VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx

コレがVG名。
このVGに一時コピー先の領域を確保する(LVを作成するとも言う)。もちろんコピー元仮想HDDより大きいサイズを確保する。

[root@xs ~]# lvcreate -L 10G -n temp VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx
Logical volume “temp” created

確保したLVの中にパーティションを切ったりした方が良いのかも知れないけど、面倒なのでパーティションは切らず直接フォーマットする。

[root@xs ~]# mkfs -t ext3 /dev/VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx/temp
mke2fs 1.39 (29-May-2006)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
1310720 inodes, 2621440 blocks
131072 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=2684354560
80 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 25 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.

で、マウント。

[root@xs ~]# mount /dev/VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx/temp /mnt

手順5:コピー元仮想HDDのスナップショットを作成する。
コピー元仮想HDDに変更があるとその分スナップショットの領域に書き込みが発生する(スナップショットに書き込まれるのは古いデータ)のですが、スナップショットの領域以上に変更があるとスナップショットが壊れるらしいので、作業に掛かりそうな時間とコピー元仮想マシンの稼働具合からスナップショットの領域のサイズを決定する。大きめにとれるなら大きめにとっておいた方が安全。
ちなみに、スナップショット名に「snapshot」は利用できないので注意。
例では、コピー元8GBに対して1GB分のスナップショット領域を作成。

[root@xs ~]# lvcreate –snapshot –size=1G –name=source_snapshot /dev/VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx/LV-e60e9a37-d52a-40a1-83d4-cfa26dxxxxxx
Logical volume “source_snapshot” created

手順6:確保した一時コピー先にコピー元仮想HDDのスナップショットから内容をddでファイルとして書き出す。
例では、面倒なのでbs=32Mとか書いてますが一般的にもっともっと小さい値を指定した方が早いはずです。

[root@xs ~]# dd if=/dev/VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx/source_snapshot of=/mnt/source_image bs=32M

ddの進捗が見たいときは、ddのプロセス番号を調べてその番号に対してUSR1シグナルを送って下さい。
(進捗はddのプロセスで表示されます)

[root@xs ~]# kill -USR1 12345

手順7:一時コピー先からコピー先仮想HDDへコピー。
コピー先仮想マシンが起動してる場合は停止して下さい。
で、仮想マシンが停止してる状態だとその仮想マシンの仮想HDDつまりLVがinactive状態になり/dev配下では見えなくなってしまうので、一度activeにします。

[root@xs ~]# lvchange -a y /dev/VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx/LV-197bae16-d1f3-4a64-ba8f-41d2cdxxxxxx

activeにしたら、一時コピー先からコピー先仮想HDD(LV)へddでコピーします。

[root@xs ~]# dd if=/mnt/source_image of=/dev/VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx/LV-197bae16-d1f3-4a64-ba8f-41d2cdxxxxxx bs=32M

本当は一時コピー領域など使わずにコピー元からコピー先へ直接コピーできれば良いんですが、直接ddをやっても正常に動作しないのでこんなまどろっこしい方法になってます。なんか良い方法ないですかね?

コピーが終わったらコピー先LVを一応非アクティブに戻しておきます。

[root@xs ~]# lvchange -a n /dev/VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx/LV-197bae16-d1f3-4a64-ba8f-41d2cdxxxxxx

手順8:コピー先のネットワークの設定をする。
手順7まででコピー先の仮想マシンがコピー元と全く同じ状態で起動するようにはなっていますが、ネットワークの設定(ホスト名やIPアドレス設定)も同じになってるのでそのまま起動すると危険です。
せっかくコピー元は無停止なのにIPがコンフリクトしてコピー元に接続できなくなるかもしれません。
なので、XenCenterからコピー先の仮想ネットワークアダプタを削除してから起動し、XenCenterのコンソールからネットワークの設定を他と被らないようにして、停止し、仮想ネットワークアダプタを元に戻し、再度起動します。

もしくは、ここ(lvmのディスクイメージをmount – 間違いだらけの備忘録)を参考にして、直接コピー先のLVをマウントしてネットワーク関連の設定ファイルを書き換えるのも良いと思います。

これで、仮想マシンのコピーができました。
最後に作業で使ったスナップショットを削除します。(スナップショットが残っててそれが溢れると何が起きるか分かりません。)

[root@xs ~]# lvremove /dev/VG_XenStorage-1683d355-0e2e-8b50-19d1-79934exxxxxx/source_snapshot

あと、一時コピー先もアンマウントしてLVを削除しておいた方がいいでしょう。

コメントを残す

メールアドレスが公開されることはありません。



※画像をクリックして別の画像を表示

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください