Xenを使って Ubuntu 11.10 (oneiric) の上で Debian 6.0 (squeeze) を動かす

(ホスト側) 必要なパッケージ

  • lvm2 2.02.66-4ubuntu3
  • libc6-xen 2.13-20ubuntu5
  • libxenstore3.0 4.1.1-2ubuntu4.1
  • xen-docs-4.1 4.1.1-2ubuntu4.1
  • xen-hypervisor-4.1-i386 4.1.1-2ubuntu4.1
  • xen-tools 4.2.1-1
  • xen-utils-4.1 4.1.1-2ubuntu4.1
  • xen-utils-common 4.1.0~rc6-1ubuntu1
  • xenstore-utils 4.1.1-2ubuntu4.1
  • ほか、その依存関係

ubuntuのカーネルイメージはデフォルトでxenのdom0に使えるので、カーネルそのものは特に追加する必要はない。
今回はホスト側のカーネルは linux-image-3.0.0-16-generic-pae をそのまま使っている。

(ホスト側) LVMのボリュームグループを作成しておく

最初はループバックで動かして後からLVMのブロックデバイスを追加しよう…としたら、domUinitrdにブロックデバイス用のモジュールがうまく入らなかった。最初からLVMを前提にしてxen-create-imageを行う方が確実なようだ。

  • partedかfdiskで適当にパーティションを確保して
  • 再起動はしたくないので partprobe でパーティション情報を再ロードして
  • 「pvcreate パーティションのデバイス名」でLVMの物理ボリュームに仕立てて
  • 「vgcreate -s 128m vg1 パーティションのデバイス名」でLVMのボリュームグループを作成する。

ここで作ったボリュームグループに対して、後からxen-create-imageが自動的に論理ボリュームの切り出しを行うことになる。

(ホスト側) grubの設定

  • パッケージを入れた後に update-grub する
  • その後に grep menuentry /boot/grub/grub.cfg すると 「~ and XEN」のついた起動選択肢があるのを確認できる
  • その選択肢が自動的に選ばれるように、mv /etc/grub.d/ にある 10_linux か 20_linux_xen のどちらかをリネームして順序を入れ替える
  • 再度 update-grub してからリブート
  • xm list でdom0が表示されていればOK

dom0の最低メモリ量を調整するために、何回かここで再起動するかもしれない。
また、OSのループバックデバイスの数を変更するのに /etc/modprobe.d/loopback.conf を作って options loop max_loop=16 …等と書く必要があるかもしれない。

(ホスト側) xen-create-image

domU用の、OS入りのディスクイメージを生成する。
今回は --mirror=http://ftp.jp.debian.org/debian --dist=squeeze を指定することで、debianを入れたディスクイメージを作成する。
なんでoneiric じゃないのかと言われそうだが、その理由は /usr/share/debootstrap/scripts/ の下に oneiric が存在していなかったからだ。debianのsqueeze は提供されているので、ちゃんとdebian用のディスクイメージを作れる。おそらくOSのリリース時期と、それを利用したdebootstrap設定の提供時期が原因だと思われる。
…というのはどうでもよくて、本当は単にdebianの方が好みだからだ。選択できるのであればホストOSにもdebianを選んでいただろう。

/etc/xen-tools/xen-tools.conf に書くか、もしくはxen-create-imageのコマンドラインオプションにこんな感じで指定する。どの項目をどちらに書くかはお好みで。

# /etc/xen-tools/xen-tools.conf
arch = i386   # i386 or amd64
lvm = vg1     # イメージが出力されるLVMボリュームグループ
install-method = debootstrap
gateway    = 192.168.2.21
netmask    = 255.255.255.0
broadcast  = 192.168.2.255
nameserver = 210.224.163.4
mirror = http://ftp.us.debian.org/debian # パッケージを取ってくるリポジトリ
ext3_options     = noatime,nodiratime,errors=remount-ro
ext2_options     = noatime,nodiratime,errors=remount-ro
xfs_options      = defaults
reiserfs_options = defaults
btrfs_options    = defaults

# command to create image
xen-create-image --force --hostname=guest1 --ip=192.168.2.2 --pygrub --dist=squeeze --mirror=http://ftp.jp.debian.org/debian 

うまくいけばrootのパスワードが出力されて作成が完了する。

(ホスト側) ネットワークの設定

今回の環境ではホストOSにはプライベートIPアドレスが全く割り当てられていないので、ブリッジモードを使うわけにはいかない。NATも後で外す予定なので、ルータモードでネットワークを設定してみた。

ルータもードを選択する場合、/etc/xen/xend-config.sxp で

(network-script network-route)
(vif-script     vif-route)

が呼ばれるようにするだけではなく、/etc/xen/scripts/vif-route にも手を入れた方が便利だ。vif-routeスクリプトは仮想NICのホストPC側のアドレスに、ホストPCのeth0と同じアドレスを設定してしまうのだが、そうするよりは、仮想NICのゲストOS側のアドレスと同じネットワーク内のアドレスを割り当てた方が色々と捗る。

私が取った方法は、ゲストOS側のアドレスの末尾に文字列の1を連結するというものだった。

# main_ip=$(dom0_ip) 
main_ip="${ip}1"

この変更によって、もしゲストOSに設定したIPアドレスが192.168.2.2なら、その仮想NICのホストPC側の端点は 192.168.2.21で初期化されることになる。なんとも原始的だが、今回はここを洗練させる必要は特にない。

(ホスト側) マスカレードの設定

ゲストOSから外向きの通信が行えるようにするには、ホストOSに次のような設定を行う。

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

送信先をフィルタするためにNATではなくプロクシを使うケースもあるが、ここでは説明しない。

マスカレードの設定(B)

今回はjailの代わりに仮想PCを使うのが目的なので、ゲストから外向きの通信を制限したい。
ホスト側に適当なプロクシを入れて、送信先をフィルタすることで賄う。
ただしDNSに限っては引けるようにする。

iptables -t nat -A POSTROUTING -p tcp --dport 53 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -p udp --dport 53 -o eth0 -j MASQUERADE

ゲストPCを起動

先ほど作成したディスクイメージにつけたhostname がguest1だったので、/etc/xen/guest1.cfgが作成されているはずだ。
xm create guest1.cfg -c でゲストPCを起動して、そのコンソールを表示する。
なお、ゲストPCを起動したままコンソールをデタッチするにはCTRL+]を押す。

(ゲスト側) ネットワーク設定

ゲストOSの/etc/network/interfaceを編集する。この時点ではエディタはnanoかviの二択だ。

auto eth0
iface eth0 inet static
 address 192.168.2.2
 gateway 192.168.2.21
 netmask 255.255.255.0
 broadcast 192.168.2.255
 dns-nameservers 192.168.2.21

編集が終わったらゲストOS側で /etc/init.d/networking restart を実行してネットワーク設定を更新する。
仮想NICのゲストOS側のアドレスと同じネットワーク内のアドレスが仮想NICのホストOS側に割り当てていた場合は、これでゲートウェイが自動的にルーティングに設定されるはずだ。
適当な外部のサーバにpingを打ってみて、もしネームサーバが正しく設定されていない場合は手動で/etc/resolv.conf を編集する。
pingと名前解決さえできれば後は全く普通のdebianだ。