KVMを使う(LiveMigration編)
仮想サーバの醍醐味(?)のひとつに、Migration(マイグレーション)機能があります。KVMは仮想サーバのセーブとロード、offlineおよびlive migrationのそれぞれに対応している、と主張しています。今回はこれを確かめてみることにしましょう。
Migration機能とは
Migrationとは、仮想サーバをあるホストサーバから別のサーバへ移動させる機能のことです。たとえば「ホストサーバの負荷が高まったので、複数のゲストサーバのうちいくつかを他へ移動して、負荷を分散させたい」としましょう。通常であればいったんゲストサーバをシャットダウンし、新しいホスト上で再起動する手順を踏む必要があります。Migration機能はゲストサーバをシャットダウンすることなく、サーバの状態(プロセス、メモリ、ディスクなど)を一時的に停止してコピーし、新しいホスト上で再開させることができます。これによりサーバの移動が非常にスムーズになるというわけです。

特にLiveMigrationと呼ばれる機能は、可能な限りゲストサーバを落とすことなく移動させる技術です。その行程はおおよそ以下の通りです。
- あらかじめ転送先のゲストサーバを設定し起動する。このときpauseオプションを付けて停止状態にしておく
- 転送元ゲストサーバに、転送先を指定してMigrationコマンドを送る
- 転送元ゲストは自らの状態を転送先にコピーする
- ディスクは共有されていることを前提としてコピーしない
- メモリをコピーし、転送先に送りこむ
- プロセス状態のスナップショットを保存し、これも転送先に送る
- すべてが終わったら自らをpauseする
- 転送先ゲストはコピー完了と同時に起動する
- ディスクは共有状態なのですぐに使えるようになる
- メモリを受け取り展開する
- プロセス状態も同様に展開し、レジスタ等をセットする
- 準備ができたら自らのpauseを解除する
肝心なのは、3から4までの間をいかにスムーズに行うかということです。特に動作中のプロセスをコピーする瞬間は、どうしても処理を停止せざるを得ません。この停止時間をなるべく短くするために、メモリのコピーはダイナミックに行われます。
- プロセスを動かしたままメモリのコピーを行う
- ある程度の分量が移動したらプロセスを停止させ、最後までコピーを行う
- プロセスが動いている間に書き換えられたメモリを再度転送する

このような工夫により、プロセスの停止時間を数秒単位に縮めることができます。実際に試してみましょう。
KVM(qemu)のLiveMigration
2台のホストサーバ(転送元と転送先)と共有ファイルシステムとしてNFSサーバを1台用意します。NFSサーバはなんでもOKですが、ホストサーバは同一スペックでなければいけません。転送元のホストを192.168.12.45、転送先ホストを192.168.12.46とします。なお、2台のホストから見たNFSサーバのマウントポイントは、同じpathになっていることが望ましいようです。
まず192.168.12.45上で、VMをひとつ起動します。ネットワーク設定も含め、お好きなスペックのゲストを起動しましょう。ネットワークも設定できます。ここでは192.168.12.100とします。ネットワーク設定編で紹介した通り、ブリッジ経由でアクセス可能なようにしておけば、LiveMigration時にIPアドレスごと移動できます。
つづいて転送先ホスト192.168.12.46で、待機状態のVMをひとつ作成します。LiveMigrate用の待機ホストを作成するには、-incomingオプションを付与します。
host2# qemu-system-x86_64 -hda /nfs/kvm/vm01.img -m 512 ... -incoming tcp:0:4449
- incomingオプションの3つ目のパラメータはポート番号で、LiveMigrateをするときに指定することになるのでメモしておきます。
それではいよいよ移動開始です。転送元ゲストの、qemuモニタに接続します。
host1# telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'
QEMU 0.12.4 monitor - type 'help' for more information
(qemu) info status
VM status: running
info statusをチェックすると動作中であると分ります。
migrate_set_speedコマンドを使って、データ転送帯域を指定します。ここでは1Gbpsにしてみます。
(qemu) migrate_set_speed 1g
migrateコマンドを使って、転送先ホストのIPアドレスとポート番号を指定し、LiveMigrateを開始します。migrateコマンドには-dオプションを付けておきましょう。
(qemu) migrate -d tcp:192.168.12.46:4449
コマンドを実行すると、すぐにLiveMigrateが始まります。しかしプログレスメータ等は表示されないので、info migrateコマンドを使って手動でチェックしなければいけません。
(qemu) info migrate
Migration status: active
transferred ram: 9656 kbytes
remaining ram: 531272 kbytes
total ram 540928 kbytes
info migrateを何度か実行していると、少しずつtransferredが増え、remainingが減っていきます。そしてある時点で転送元VMがpauseされ、残りが一気に転送されて移動が完了します。
(qemu) info migrate
Migration status: active
transferred ram: 283164 kbytes
remaining ram: 261924 kbyes
total ram: 540928 kbytes
(qemu) info migrate
Migration status: completed
migrateコマンド投入からcompleteまで約12秒、最終コピー時のpauseは一瞬で、1秒間隔で打ったpingや、VMにtelnetで接続したコンソール画面には何の異常も発生しませんでした。この実験では単にVMの移動をやっただけなので負荷がかかっていません。メモリ量が増えたり、プロセスやトラフィックなどの負荷がかかった場合は、開始から完了までに長時間かかったり、Migrateが失敗(キャンセルして元のVMの動作が続行されます)することもあり得ます。いろいろ負荷をかけてテストしてみると面白いでしょう。
参考文献
11月16日、LPI-Japan主催のセミナーでKVMに関する講演をさせていただきました。当研究所ではこれまでにqemu-kvmをソースからコンパイルして使うことを前提に色々な紹介をしてきましたが、講演では広く気軽に試していただくよう、Ubuntu Desktop Editionを例にパッケージでインストールする方法を取り上げました。講演ではスライドでお見せした部分を、当ブログではじっくりコンソールでご覧にいれたいと思います。

サーバの準備
「Desktop環境で気軽に試していただく」ということで、サーバ(PC)についてうるさい条件はつけていません。強いて言うなら
- VT対応のCPUがよいが、なくても試せます
- メモリは1GB以上。試すだけなら半分ぐらいでも大丈夫です
- ディスクは空き容量20GBほど。5GB以下だと仮想マシンが入りません
ぐらいでしょうか。これにUbuntu Desktop Editionをインストールします。バージョンは10.04でも大丈夫ですが、10.10が最新版です。Ubuntuのインストールにあたって特別な設定やオプションは必要ありません。
KVMパッケージのインストール
Applications → Accessories → Terminal を実行し、コマンドラインから次のように入力します。
$ sudo apt-get install qemu-kvm kvm-pxe
次にKVMモジュールを有効化します。
$ sudo modprobe kvm
以上で完了です。ちなみにUbuntu 10.10の場合、インストールされるqemuのバージョンは7月27日にリリースされた0.12.5になります。
br0の設定
当ブログのネットワーク設定編をご覧いただいた方でしたらお分かりと思いますが、VMに外部ネットワークを接続するためにはブリッジ・インターフェースを用意する必要があります。そのために /etc/network/interfaces を書き換えます。以下にDHCPでアドレスを貰う場合の設定をご紹介します。
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet manual
auto br0
iface br0 inet dhcp
bridge_ports eth0
ファイルを書き換えたらインターフェースをリスタートします。
$ sudo /etc/init.d/networking restart
これでホスト・サーバのインターフェースはbr0となり、ブリッジが利用できるようになります。
VMインストールのための準備
次にVMのHDDに当たるイメージファイルを作成します。ディスク性能編でご紹介しましたが、ごく簡単に試すならqcow2フォーマットで作成しましょう。
$ qemu-img create -f vm.img 10G
やっぱりパフォーマンスが気になるということでしたら、スパースファイルにならないようddを使って作ります。
$ dd if=/dev/zero of=vm.img bs=1M count=10240
ディスクの空き容量を超えないよう注意しましょう。
最後にインストールしたいOSのisoイメージファイルを用意しておきます。以上で準備完了です。
VMを起動する
それではいよいよVMを起動してみましょう。カレントディレクトリにvm.imgとxxxx.isoファイルがあると仮定します。
$ sudo kvm vm.img -m 256 -net nic,model=e1000,macaddress=xx:xx:xx:xx:xx:xx
-net tap,ifname=tap0 -cdrom xxxx.iso -boot d
これでCD-ROMからブートして、HDDに見立てたファイルvm.imgにインストールできるようになります。

スクリーンショットを撮るために用意したPCがしょぼくて、VTが付いていません。そのためにKVMサポートが動いていません。
このようにGUI環境下ではウィンドウがそのままVMとなり、フォーカスがある限りVMに対する操作がキーボードやマウスを使って行えます。マウスカーソルはVMのウィンドウに固定されますが、タイトル部分に出ているようにCTL+ALTを押すとリリースできます。
qemuモニタ呼び出し
qemuモニタを利用するには、VMのウィンドウでCTL+ALT+2を押下します。すると画面がqemuモニタに切り替わります。元のVMのスクリーンにはCTL+ALT+1で戻せます。ちなみにCTL+ALT+3ではシリアルポートに繋ぐことができます。
VMの終了
VMを終了するには、行儀よくVM内でシャットダウンすることをお勧めしますが、インストールが終了したときなど、リブートがうまくいかず固まってしまうこともあります。そんなときはqemuモニタからquitすれば、VMはあっさり終了します。
インストール完了後の起動
インストールが完了したら、CD-ROMを外して再起動します。qemuモニタからejectしてもいいのですが、qemuを終了して再起動するのが楽です。そのときコマンドラインから -cdrom オプションと -boot オプションを外します。
$ sudo kvm vm.img -m 256 -net nic,model=e1000,macaddress=xx:xx:xx:xx:xx:xx
-net tap,ifname=tap0
このコマンドはVMの起動ごとに実行することになるので、スクリプトにしておくと楽です。
おわりに
いかがでしょうか、SDLを使うととても簡単にKVMが試していただけると思います。本格的に使う場合はVMのウィンドウがいちいち邪魔だったり、VMプロセスがTerminalをロックしてしまったりするので、-nographicオプションや-vnc、-monitor、-daemonizeといったオプションを駆使していけばよいと思います。そのような使い方については、当ブログの過去の記事をご参照いただければと思います。
著者

1998年、エス・アール・エス有限会社入社の後、合併を経てさくらインターネット株式会社へ。技術部部長、取締役を経て、2009年7月に研究所所長就任。
会社設立時より技術担当。レンタルサーバ組み立てから始め、データセンタ構築、バックボーン構築、オンラインゲームプロジェクトの技術運用などを歴任。2018年まで、クラウドサービスのマネージャを担当。
初代所長に任命された割に研究者としての実績はなく、論文は学生時代に書いたきり。他、数冊の書籍の執筆経験がある。
最近の興味の中心は、サーバの仮想化、クラスタリングなど。