サーバーの仮想化をしたい。サーバー上で動かしたい Windows のアプリがある。専用に一台準備するほどのものでもないので仮想化したい。サーバーには Ubuntu 11.10 “Oneiric Ocelot” が入ってる。

普段はオーバーヘッドの少ない LXC を使って仮想化してる。でも LXC じゃホストと同じカーネルで動く仮想マシンというか分離環境しか作れない。もちろん Linux 上で Windows を動かすとか無理。

というのも、OS 内のプロセスとリソースを分離してくれるのが LXC なので、LXC で作った仮想マシン内で走ってる各プロセスは、結局ホスト OS の中で走っているプロセスでしかない。

LXC は完全な仮想システムを実装するために、Linux の既存のプロセス管理基盤にリソース管理と分離のメカニズムを追加し、chroot から構築されている。

LXC builds up from chroot to implement complete virtual systems, adding resource management and isolation mechanisms to Linux’s existing process management infrastructure.)

lxc Linux Container より

どう考えても Windows は動かない。 動かしたいアプリは Wine じゃ動かない。 Mono でも動かない。やっぱり完全な仮想マシンを作るしかない。

Ubuntu の Virtual Machine host オプション

Ubuntu サーバー版のインストーラーでは、最後の方でインストールするソフトウェア (パッケージ群) を選択できるんだけど、いつからかそこに Virtual Machine host って選択肢ができてた。このサーバーに入れた時 “標準で仮想化が付いてくるなんて便利だねー” なんて思いながらとりあえずチェックを入れてた様な気がした。

これを選択すると ubuntu-virt-server っていうパッケージがインストールされるらしい。具体的には何が入っているのかというと

Package: ubuntu-virt-server (1.3) より

Qemu が入っているらしい。じゃあせっかくだしそれを使って仮想化しよう。

ちなみに libvirt はいろいろな仮想化ツールを抽象化して、仮想マシン管理を一元化してくれるライブラリらしい。サポートする仮想化ツールの幅も広いみたいで、聞いたことのある仮想化技術の名前がほとんど並んでた。便利ねー。

けど使わない。レイヤー増やしたくない。とりあえず今は覚えること増やしたくない。

とりあえず ubuntu-virt-server が入ってること確認、というか入ってなかったらインストール。

$ sudo apt-get install ubuntu-virt-server
[sudo] password for hama:
Reading package lists... Done
Building dependency tree
Reading state information... Done
ubuntu-virt-server is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.

入ってた。よしよし。

仮想マシンの準備

ディスクイメージ作成

ゲスト OS を Windows XP にする。とりあえずインストール CD とライセンスが必要。探してきた。YMMV。30分はかかった。吸い出して ISO イメージにして適当なところにアップロードしておいた。ファイル名はとりあえず xp_installer.iso としておいた。これで CD イメージはできた。

次に、ゲスト OS の HDD。物理 HDD やネットワークストレージを直接使ってみたいなー、速そうだなーと思いながらも使わない。とりあえず一番手軽な仮想 HDD ファイルを使う。

HDD イメージは qemu-img というプログラムを使って作るらしい。オプションなしで実行するとヘルプが表示されるみたい。

$ qemu-img
...
Supported formats: vvfat vpc vmdk vdi sheepdog raw host_cdrom host_floppy host_device file qed qcow2 qcow parallels nbd dmg tftp ftps ftp https http cow cloop bochs blkverify blkdebug

なんかいろいろサポートされてすごい。とりあえず標準的なものを使う。で、それが qcow2 らしい。モーモー。

QEMU はいくつかのイメージタイプをサポートします。ネイティブとされ、もっとも柔軟なフォーマットは qcow2 で、コピーオンライト、暗号化、圧縮、スナップショットなどに対応します。

“QEMU supports several image types. The “native” and most flexible type is qcow2, which supports copy on write, encryption, compression, and VM snapshots.”

QEMU/Images - Wikibooks より

完全に牛を思い浮かべながら、イメージを作る。フォーマットは qcow2 で、出力ファイル名は xp.qcow2、容量は10ギガバイト。モー。

$ qemu-img create -f qcow2 xp.qcow2 10G
Formatting 'xp.qcow2', fmt=qcow2 size=10737418240 encryption=off cluster_size=65536

一瞬でできた。ナイス。

ネットワーク設定

ゲストもネットワークに接続したい。Qemu は、ユーザモードネットワークっていう便利なネットワークを標準で提供してくれる。これは VMware や VirtualBox で言うところの NAT 型に相当。これを使うと、Qemu がゲストのルーター、DHCP、DNS になってくれて簡単に外界に出られるらしい。ただ、外界から仮想マシンにアクセスするにはいろいろ設定が必要みたい。

今回はできればホストと同じように接続したい。同じセグメントにある物理マシンと同じ扱いをしたい。なので、ユーザーモードネットワークではなさそう。

VMware ではゲストを物理ネットワークに直接接続することをブリッジと呼んでたけど、Qemu とだいたい同じっぽい。仮想マシンに tap インターフェースを使わせて、それと eth0 をブリッジすれば良さそう。

QEMU は TAP インターフェースを利用できます。ゲスト OS を普通のポートに接続しなければならない際に便利です。

“QEMU can use TAP interfaces … can be useful when the guest OS … must be connected to via standard ports”

QEMU/Networking - Wikibooks より

じゃあそれで。ブリッジ作成前の環境はこんな感じと仮定。ありがちなやつ。

ネットワーク192.168.0.0/24
インターネットへのルーター192.168.0.1
ホストの eth0192.168.0.50
DHCP 自動割当範囲192.168.0.101 から .254 まで

eth0 → br0 にする感じ。インターフェース設定を変更。

$ sudo nano /etc/network/interfaces

/etc/network/interfaces 変更前:

auto  lo
iface lo inet loopback
auto  eth0
iface eth0 static
  address 192.168.0.50
  netmask 255.255.255.0
  gateway 192.168.0.1

/etc/network/interfaces 変更後:

auto  lo
iface lo inet loopback
auto  eth0
iface eth0 inet manual
auto  br0
iface br0 inet static
  bridge_ports eth0
  bridge_stp off
  bridge_maxwait 0
  address 192.168.0.50
  netmask 255.255.255.0
  gateway 192.168.0.1

保存したらネットワークを再起動。リモートで作業している時は特に設定を間違えないように注意する。再起動後接続できなくなる。ネットワーク経由でシリアルポートに接続できるならまあいいけど。

$ sudo service networking restart

ちなみに、設定内の bridge_stpスパニングツリープロトコルを有効にするかどうか。”ループ構成を回避するための通信プロトコル” らしい。細かいことは libvirt: Wiki: Networking が参考になりそう。

VNC クライアント

仮想マシンの画面には VNC 経由で接続するので、適当なクライアントをインストールしとく。

Windows:

Mac:

最近 Mac はあまり使ってないのでよくわからない。前は Chicken of the VNC とか使ってたけど。Apple 謹製のリモートデスクトップクライアントは確か VNC に対応してたような気がする。

仮想マシンを起動 → VNC 接続

ディスクイメージ、ネットワークブリッジ、VNC とそろったところで、実際に仮想マシンを起動する。わくわく。

KVM を使うので、たぶん root 権限が必要。ないと /dev/kvm にアクセスできないって言われる。あとブリッジというかタップインターフェースを作るのにも必要かもしれない。

$ sudo qemu -cpu core2duo -smp 1 -hda xp.qcow2 -m 512M -k ja -name "Windows XP" -nographic -vga cirrus -vnc :0,passw0rd -net nic,model=rtl8139 -net tap -enable-kvm -daemonize -runas hama -cdrom xp_installer.iso
qemu: pci_add_option_rom: failed to find romfile "pxe-rtl8139.bin"

ROM ファイル pxe-rtl8139.bin が見つかりませんよーと言われた。起動してるんだろうか。っていうかターミナルの改行がおかしくなったので直す。

$ reset

次にプロセスリストを見て起動しているか確認する。

$ ps ax | grep qemu
22445 ?        Sl     0:13 qemu -cpu core2duo -smp 1 -hda xp.qcow2 -m 512M -k ja -name Windows XP -nographic -vga cirrus -vnc :0,passw0rd -net nic,model=rtl8139 -net tap -enable-kvm -daemonize -runas hama -cdrom xp_installer.iso
25082 pts/0    S+     0:00 grep --color=auto qemu

起動してるっぽい。ってか VNC のパスワードが ps で漏れてる。これはよくない。けどまあとりあえず。

VNC で接続する。Qemu のオプション -vnc :0 で指定した通り VNC #0 (= #5900 ポート) に接続する。 ホストのそこに接続する。パスワードは ps で漏れてる passw0rd。Windows XP のインストーラーが立ち上がってるハズ。

(一部の色が変だけど勝手に直るので心配なし。)

懐かしい Windows XP をインストールする。しかし Windows XP で懐かしいとか言ってたら怒られそうだな、とか思いながらウィザードを進める。ファイルのコピーには割と時間がかかるが気にしない。

ゆっくり待つ。

Qemu がメモリーリークする

インストール中に目を離していたら、ホスト OS に入ってるシステム監視ツールが、”メモリーが少なくなってきたけど” と言ってきた。仮想マシンのメモリは -m 512M で指定したとおり 512 メガバイト。サーバー全体の物理メモリーは 8 ギガバイト。これだけで使い切るはずがない。ちょっと確認する。

$ free

監視ツールが嘘付くわけないよねーと思いながら、何がメモリをそんなに使ってるのか確認する。

$ top

Qemu のプロセスに割り当てられてるメモリは 512 メガバイト前後なのが確認できた。でも何かがおかしい。空きメモリが勢いよく減ってく。たぶん何かがメモリーリークしてる。Qemu を起動するまでは起きなかったので、たぶん Qemu の何かがメモリーリークしてる。あるよねー。

とりあえず Qemu のバージョンを確認して、情報を探しに行く。

$ qemu --version
QEMU emulator version 0.14.1 (qemu-kvm-0.14.1), Copyright (c) 2003-2008 Fabrice Bellard

Google で検索してみた。正確にどのバージョンかはわからないけれど、メモリーリークがあって、修正されたことは間違いなさそう。ふーん。

とりあえず、最新の安定版を使ってみよう。ということで、Qemu の公式サイトを見てみた。

Feb 17, 2012

QEMU version 1.0.1 is out. See the Download page for more information.

May 7, 2011

QEMU version 0.14.1 is out. See the Download page for more information.

1.0 まわってた。0.14.1 古っ、と思ったけどどうも 0.15.0-rc2 → 1.0-rc1 にバージョンが飛んでるので超古いわけでもなさそう。とはいえ 0.14.1 がリリースされたのは2011年の5月。Oneiric は同10月。Qemu のリリースログを見ると10月の段階では 1.0 はまだリリース候補版だったみたい。ふーん。

今2012年の3月だし。アップデートから入ってくるのが 0.14.1 って。

まあ自前でコンパイルするからいいけど。

とりえあず、Qemu は落とす。さっき ps で見た時、プロセス番号が 22445 だったのでそれを落とす。

$ kill 22445

Windows XP のインストールは後でやり直す。あんまりメモリーが残ってなかったらシステムを再起動した方がいいかもしれない。

Oneiric で Qemu をコンパイル

とりあえず、ビルドするのに必要なパッケージをまとめてインストールする。面倒なので qemu-kvm パッケージをコンパイルするのに必要なパッケージをまとめてインストールする。

$ sudo apt-get -V build-dep qemu-kvm

環境によって違うとは思うけれど、結構たくさんインストールされた。

準備が整ったところで、Qemu のソースを拾って展開。

$ curl http://wiki.qemu.org/download/qemu-1.0.1.tar.gz | tar zxv --

configure して make して sudo make install。ありがち。インストール先は /usr/local/qemu-1.0.1 としておいた。

$ cd qemu-1.0.1
$ ./configure --prefix=/usr/local/qemu-1.0.1 --enable-vnc --enable-system --enable-kvm
$ make

結構長い。しばらく待つ。

$ sudo make install

入ったら一応確認する。

$ ls /usr/local/qemu-1.0.1/bin

どうも qemu-system-* がそれらしい。CPU アーキテクチャ毎のバイナリがある。

コンパイルしたバイナリで Windows XP をインストール

さっき作った HDD イメージには途中までインストールされた Windows XP があって微妙なので、いったんイメージを作り直す。

$ rm xp.qcow2
$ /usr/local/qemu-1.0.1/bin/qemu-img create -f qcow2 xp.qcow2 10G
Formatting 'xp.qcow2', fmt=qcow2 size=10737418240 encryption=off cluster_size=65536

モーモー。

今度はコンパイルされた Qemu のバイナリを使って仮想マシンを起動する。オプションは前回と同じ。

$ sudo /usr/local/qemu-1.0.1/bin/qemu-system-i386 -cpu core2duo -smp 1 -hda xp.qcow2 -m 512M -k ja -name "Windows XP" -nographic -vga cirrus -vnc :0,passw0rd -net nic,model=rtl8139 -net tap -enable-kvm -daemonize -runas hama -cdrom xp_installer.iso
qemu: pci_add_option_rom: failed to find romfile "pxe-rtl8139.bin"

実行すると、やっぱり改行がおかしくなるので:

$ reset

次に VNC で接続。インストーラーが立ち上がっているはず。懐かしいインストーラーを進める。インストールが終われば晴れて Windows XP が立ち上がる。

Internet Explorer 6 が入っててちょっと怖い。アップデートは忘れずに。 ネットワーク周りの確認もしておく。ゲストが期待通りの IP を DHCP から取得しているか。ゲストから外界に接続できるか。外界からゲストに接続できるか、とか。

あと、タップインターフェースのブリッジ接続はどうなったかというと、Qemu が勝手にタップインターフェースを作って、一つだけあったブリッジインターフェースを選んで接続してくれたっぽい。ブリッジインターフェースが複数ある場合はたぶん br0 とか br1 とかちゃんと指定するんだと思う。

それと、Qemu 起動時のコマンドラインオプションに VNC のパスワードが入ってるので何か対策が必要。まあ普段は使わないので VNC なしで Qemu を起動するのが妥当かも。Linux なら SSH、Windows なら RDP とかで繋がるし。これは今度調べる。

メモリーリークは解決した

結局、自前で Qemu 1.0.1 をコンパイルして使ってみたら、Oneiric 付属の Qemu 0.14.1 を使った時のようなメモリーリークは確認できなかった。ということで、たぶん Oneiric のパッケージに入ってるバージョンがメモリーリークの原因だったっぽい。このパッケージ 2012年3月20日現在も oneiric-updates に入ってる。

結論: Qemu は便利。でも Ubuntu には気をつける。

Qemu のおかげで割と簡単に Windows XP のゲストが作れた。ベンチマークは取ってないけど、結構サクサク動いている印象。これで無料なんだから素晴らしい。活用したい。一方 Ubuntu から提供される Qemu のパッケージは欠陥品の可能性が高いので気をつける。自分で最新の安定版をコンパイルしたものを使った方がよさそう。