ubuntu-vm-builder で仮想マシンを作る

うぶまがのロードテストにも書きましたが、普段の仮想マシン管理には virt-manager を使っていたりします。ですが GUI アプリですので、あまりスマートではありません。VM のホストに ssh して、そこからコマンドで制御できればそれで十分なわけです。というわけで ubuntu-vm-builder を使って見ました。当然仮想化には KVM を使いますので、KVM が使えるマシンである必要があります。デスクトップのサンドボックスを作るわけではなく*1、複数の仮想サーバを一台のマシンでまかなうのが目的ですので、やりたいことは以下のようになります。

  • KVM を使って仮想マシンを動作させる
  • CLI から制御する
  • ネットワークにブリッジ接続する
  • ホストの起動時にゲストを自動起動させられればベター

KVM のインストール

10.04 以降なら、以下のようにインストールします。

$ sudo aptitude install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils

あるいは tasksel で virtual machine host をインストールしてしまってもいいです。netboot でのインストールなら、インストールの最終段階で tasksel が起動するので、そこで済ませてしまうといいかもです。コマンドからやるならこんな感じ。

$ sudo tasksel install virt-host

KVM が使えるかの確認には、kvm-ok コマンドがあります。以下のような感じになれば OK。

$ kvm-ok
INFO: Your CPU supports KVM extensions
INFO: /dev/kvm exists
KVM acceleration can be used

ブリッジを作成する

/etc/network/interfaces を編集して、ホストにブリッジ br0 を作成しておきます。br0 にも IP アドレスを振らないと、ホスト自身がネットワークに接続できなくなってしまうので、ここでは IP アドレスを指定しています。

$ sudo vi /etc/network/interfaces
auto eth0
iface eth0 inet manual

auto br0
iface br0 inet static
	address 192.168.1.8
	network 192.168.1.0
	netmask 255.255.255.0
	broadcast 192.168.1.255
	gateway 192.168.1.1
	bridge_ports eth0
	bridge_fd 9
	bridge_hello 2
	bridge_maxage 12
	bridge_stp off
$ sudo /etc/init.d/networking restart

仮想マシンを作る

ubuntu-vm-builder は vmbuilder を Ubuntu 向けに使いやすくするラッパースクリプトです。コマンドを叩くとカレントディレクトリにサブディレクトリを掘り、そこに仮想マシンのイメージファイルと起動用のスクリプトを作成します。たとえばこんな感じで使います。

$ sudo ubuntu-vm-builder kvm lucid --mirror=http://jp.archive.ubuntu.com/ubuntu --destdir=lucid
2010-11-18 14:02:13,481 INFO    : Calling hook: preflight_check
2010-11-18 14:02:13,511 INFO    : Calling hook: set_defaults
2010-11-18 14:02:13,512 INFO    : Calling hook: bootstrap
2010-11-18 14:11:19,677 INFO    : Calling hook: configure_os
(...snip...)
2010-11-18 14:17:47,475 INFO    : Calling hook: deploy
2010-11-18 14:17:48,439 INFO    : Calling hook: fix_ownership
$ cd lucid
$ ./run.sh

run.sh コマンドは kvm コマンドのラッパーなので、kvm コマンドのオプションを追加することもできます。

vmbuilder のオプション

vmbuilder で仮想マシンを構築する際に、様々な設定をオプションで渡すことが可能です。よく使うのはこのへん。

--mirror
使用するミラーサーバを指定します。
--destdir
仮想マシンを作成するディレクトリを指定します。
--arch
ゲストのアーキテクチャを指定します。指定できるのは i386/amd64/lpia。(デフォルトではホストと同一)
--mem
ゲストに割り当てるメモリ量をMBで指定します。(デフォルトでは 128)
--hostname
ゲストのホスト名を指定します。libvirt に追加する場合はラベル名にもなります。
--timezone
ゲストのタイムゾーンを指定します。(デフォルトでは UTC)
--user
初期ユーザのログインネームを指定します。(デフォルトでは ubuntu)
--name
初期ユーザのフルネームを指定します。(デフォルトでは ubuntu)
--password
初期ユーザのパスワードを指定します。(デフォルトでは ubuntu)
--libvirt
指定した URI仮想マシンを追加します。(例:qemu:///system)
--addpkg
任意のパッケージを自動的に導入します。
--bridge
ネットワークにブリッジ接続する場合のインターフェイスを指定します。
--ip
ゲストの IP アドレスを指定します。(デフォルトでは DHCP)
--mask
ゲストのサブネットマスクを指定します。(デフォルトでは 255.255.255.0)
--dns
ゲストが使用するネームサーバを指定します。(デフォルトでは xxx.xxx.xxx.1)
--gw
ゲストのゲートウェイを指定します。(デフォルトでは xxx.xxx.xxx.1)
一般ユーザでの kvm の使用

run.sh をキックした際に、/dev/kvmパーミッションエラーが出ました。/dev/kvm を利用するには kvm グループに所属する必要があるようです。

$ ./run.sh
open /dev/kvm: Permission denied
Could not initialize KVM, will disable KVM support
$ ls -l /dev/kvm
crw-rw---- 1 root kvm 10, 232 Nov 18 13:26 /dev/kvm

KVM Installation のページには次のような記述がありますが、これは libvirt を経由して KVM を使用する際の話のようですね。

Karmic (9.10) and later The libvirtd-bin package will automatically add your username to the libvirtd group. There is no need to be part of the kvm group. After the installation, you need to relogin so that your user becomes an effective member of the libvirtd group. The members of this group can run virtual machines.

ここでいくつか疑問が。なんでデフォルトでカレントユーザが kvm グループに所属していないのでしょう? ubuntu-vm-builder パッケージあたりがやってくれてもよさそうなのに(libvirtd-bin はやってるわけだし)。ひょっとして run.sh を叩く方法は Ubuntu 的には推奨されていなくて、libvirt を経由すること前提だったりするんでしょうか。あるいは手動で kvm グループに所属させるのが正しい?
と、このあたりまで調べて某しばたさんに聞いてみたところ「うちだと kvm グループに所属してないけどパーミッションエラー出ないよ?」とか言われました。ぇぇー orz
なんかやり方間違ってるのかなあ。

libvirt を使う

ubuntu-vm-builder に --libvirt オプションをつけておけば、/etc/libvirt/qemu/hostname.xml が作成され、virsh や virt-manager から仮想マシンを操作することが可能になります。virsh を使えば run.sh を直接叩かなくてもよくなります。

$ virsh
# list --all
 Id Name                 State
----------------------------------
  - lucid32              shut off
# start lucid32
Domain lucid32 started
virsh からコンソールを取る

起動した仮想マシンを操作するため、virsh からコンソールを取ります。

# console lucid32
No console available for domain

ubuntu-vm-builder で作成、登録した仮想マシンにはコンソールが用意されていません。そこで仮想マシンの設定を編集して、pty の設定を追加します。

# edit lucid32
(...snip...)
   </interface>

+   <console type='pty'>
+     <target port='0'/>
+   </console>
+   <console type='pty'>
+     <target port='0'/>
+   </console>

    <input type='mouse' bus='ps2'/>
(...snip...)

Domain lucid32 XML configuration edited.
# start lucid32
Domain lucid32 started

virsh # console lucid32
Connected to domain lucid32
Escape character is ^]
23:31:23.482: error : vshRunConsole:77 : unable to open tty /dev/pts/1: Permission denied

な、なんだってーーーー(AA 略
どうやらこれを踏んだようです。

As this is a feature that needs to be added to Libvirt, this won't be fixed for Lucid. Marking wont-fix in Lucid, but leaving the bug open for tracking beyond Lucid. Unassigning myself for now.

Dustin…… orz
あ、VNC でしたら普通に使えるので、virsh ではなく virt-manager とか使う人は問題ないと思います。

よろしい、ならば ssh

コンソールがとれないなら ssh を使えばいいじゃない。というわけで ssh 経由でゲストを操作することにします。Ubuntu にはデフォルトで ssh サーバがインストールされないので、vmbuilder の --addpkg オプションを使用します。合わせて別マシンから操作できるよう、ブリッジインターフェイスと IP アドレスも設定します。
最終的な仮想マシン作成コマンドはこんな感じ。我が家では DNS サーバを独立して立てているので、--dns オプションも指定しました。一般的なブロードバンドルータの類にお任せしている環境では、デフォルトでいいでしょう。

$ sudo ubuntu-vm-builder kvm lucid --mirror=http://jp.archive.ubuntu.com/ubuntu --arch=i386 --mem=512 --destdir=lucid32 --hostname=lucid32 --timezone=Asia/Tokyo --user=mizuno --name=mizuno --pass=hogehoge --bridge=br0 --ip=192.168.1.60 --dns=192.168.1.4 --libvirt=qemu:///system --addpkg=openssh-server --addpkg=acpid
$ ssh 192.168.1.60
mizuno@192.168.1.60's password: 
Linux lucid32 2.6.32-25-generic-pae #45-Ubuntu SMP Sat Oct 16 21:01:33 UTC 2010 i686 GNU/Linux
Ubuntu 10.04.1 LTS

Welcome to Ubuntu!
(...snip...)
$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 52:54:00:xx:yy:zz
          inet addr:192.168.1.60  Bcast:192.168.1.255  Mask:255.255.255.0
(...snip...)

ゲストの自動起動

あとは virsh でゲストを libvirtd の起動と同時に開始させる設定を行えば終了です。

$ virsh
# autostart lucid32
Domain lucid32 marked as autostarted

いちおー当初の目的は達せられたような気がします。

*1:それなら素直に Vitualbox 使うし