Ubuntu 9.10(Karmic Koala) で KVM
新しい記事があります。Ubuntu 16.04 LTS の KVM で仮想サーバ (2016/05/06, 2017/08/10 リンク先修正)
Ubuntu 9.10(Karmic Koala) のサーバ版 ( ubuntu-9.10-server-amd64 ) をホストとゲストともに使って、KVMによる仮想マシン環境を構築してみます。Linuxをインストールしたマシン(ホスト)上にソフトウェアで複数の仮想マシン(ゲスト)を作成し、それら仮想マシンにもLinuxをインストールすることで、一台のマシンを複数のマシンに見せかけます。一台のコンピュータのハードウェア全体をソフトウェアで実現(完全仮想化)します。
Ubuntuでは仮想マシン環境を制御するために Virtual Machine Manager(GUI) と virsh (CLI) が用意されていて、それらがlibvirtを使うことで各種の仮想マシン環境(Xen、KVM、OpenVZ、User Mode Linuxなど)の制御を抽象化しています。このページでは KVM の使い方を理解するため、 libvirt を使わずコマンドラインから直接 kvmコマンドを使って仮想マシンをコントロールすることにします。
Ubuntuはインストールにグラフィック画面を使います。Ubuntuのサーバ版はXがインストールされないため、ホスト上でUbuntuをインストールできません。Xをインストールすることは可能ですが、サーバとして運用するにはリソースの無駄になります。そこでqemu-kvmをvncサーバとして起動し、WindowsにUltraVNC(VNCビューアのみ)をインストールして、画面をWindowsに転送することで、Ubuntuをインストールしました。
KVM と QEMU
仮想化には比較的新しい KVM を使用しました。仮想環境としての Linux KVM (Kernel-based Virtual Machine) は QEMU という5年ほど前から利用されている比較的古い仮想マシンエミュレータが重要な部分を占めます。
QEMU 自身は色々なCPUを実行できるエミュレータで、CPU命令をソフトウェアでいちいち解釈実行する方法ではなく、動的にコンパイルするような方法を使ってかなり速いエミュレータとして有名でした。PCのハードウェア全体がソフトウェアで実現されていて、昔からOSの開発でも利用されていました。
Linuxカーネルのモジュールとしての KVM はintelVTやAMD-Dという機能を持つ最近のCPU(Core2Duo等)を使って、仮想環境のOSの特権命令まで直接実行する仕組みです。CPUの仮想化支援機能(intelVTまたはAMD-V)にアクセスするためのインタフェース(/dev/kvm)を提供しています。カーネルモード、ユーザモードに加えて、ゲストモードという新しい動作モードが追加されます。CPUで仮想環境の命令を直接実行してしまうので、仮想環境といえども速度の低下は全くありません。ただし、ハードディスクやネットワークカードなどの周辺機器(IO)へのアクセスはトラップされて物理的なデバイスとのインターフェイスがソフトウェアで行われるため、速度は多少遅くなります。
仮想環境としての Linux KVMはこのCPU以外の周辺機器の仮想化を、昔から使われていて安定なQEMUを使うことでPC全体を仮想化(完全仮想化)しています。したがってKVMは仮想環境として、非常に新しい部分(CPUの持つ仮想マシンモニター機能)をシンプルな仕組みでカーネル内に持ち、古い部分(QEMUによるハードウェアエミュレーション)をユーザプロセス側で受け持つ形式でうまく融合したものとなっています。KVM は2007年2月以降のLinuxのカーネル(2.6.20以降)のソースにモジュール(バイナリになると250KB程度とコンパクト)として取り込まれています。GUIが必須ではないのでホスト側のリソース(メモリ、CPU負荷)が無駄にならないため、サーバとして利用するにはよい環境ではないかと思います。
仮想環境の構成
外部のネットワークから見た場合、ホスト1台とゲスト2台の合計3台のサーバが独立して稼働しているような構成とします。 物理的にIPアドレスを別々に持つ3台のサーバがスイッチングハブで接続されているのと同じ状態になります。この例ではゲストOSが2つですが、必要ならばいくつでも増やすことができます。
外部からは以下のように見えることを目指します。ゲストは同様にいくつでも増やせます。
+------+ +-----------------------------------+ | GW +-----+ Switching HUB | +------+ +----+-------------+-------------+--+ 172.18.21.1 | | | +----+-----+ +---+-----+ +---+-----+ | HOST | | GUEST | | GUEST | +----------+ +---------+ +---------+ 172.18.21.80 172.18.21.90 172.18.21.91
ホストとしての64ビット Ubuntu 9.10 サーバ版のインストール
仮想環境の入れ物(ホストOS)として 64ビット Ubuntuサーバ版(ubuntu-9.10-desktop-amd64.iso) をインストールします。ゲストOSに64ビットを使う場合は64ビット版が必要です。仮想環境のホストとする場合はメモリを豊富に積んでおく必要があるので、あえて32ビット版のUbuntuをインストールする理由は思いつきません。KVMを使うため、BIOSの設定で intelVT または AMD-V を有効にしておきます。実際のインストールは下のゲストのインストールとほぼ同じです。ホストのディスクのパーティションの構成は環境によって異なり、「Manual」を使うことになると思いますから割愛します。
ゲストのインストール準備
Ubuntuはインストールにグラフィック画面が表示されますが、標準ではUbuntuのサーバ版はグラフィック画面を表示できません。仮想マシンのqemu-kvmをvncサーバとして起動し、Windows に UltraVNC ( https://www.uvnc.com/)からUltraVNC_1.0.8.2_Setup.exe [1825KB] をダウンロードしてVNCビューアをインストールすることで、グラフィック画面をWindowsで操作することが可能となります。ついでにLinuxをインストールするスクリーンショットも取得できます。
UltraVNCのインストール
ライセンス(GPL v2)の確認を求められます。Ubuntuと同じライセンス(Ubuntuのすべてが同じではないですが)なのでUltraVNCを使用するだけなら特に問題にならないと思います。建前としては「ちゃんと読んで同意できる場合だけ使ってください」ですが...
インストールするバージョンに関する情報が表示されます。
インストールするフォルダの確認です。変更する必要はないでしょう。
インストールするプログラムの選択です。今回はVNCのサーバは不要なので「Ultra VNC Viewer」を選択しました。
スタートメニューのフォルダ名を指定します。デフォルトのままで問題ありません。
デスクトップに起動用のアイコンを作成するように指定しました。
指定した内容の確認画面です。
ライセンスなどの再確認です。
インストールが終了すると表示されます。[Finish]で終了します。
UltraVNCの使い方
UltraVNC Viewerを起動して、VNCサーバにホストのIPアドレスとポート番号を指定します。ポート番号は kvm の起動時にVNCサーバとして指定したオプションの番号に5900を加えた値を指定します。「 -vnc :0」の場合は5900になります。[Connect]ボタンを押せば仮想マシンの画面が表示されます。
仮想ディスクイメージの作成
仮想マシンのハードディスクは仮想ディスクイメージというファイルとして準備する必要があります。仮想ディスクイメージは「qemu-img」コマンドを使って作成します。次の例は 4GB のディスクイメージを qcow2 フォーマットを使って、u91064s.qcow2 というファイル名で作成します。
jun@Host:~$ qemu-img create -f qcow2 u91064s.qcow2 4GB Formatting 'u91064s.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=0
qcow2 フォーマットは、使っている部分だけがファイルに記録されます。したがって実際に作成されるイメージは 4GB ではなく、次のように260KBのイメージとなります。仮想ディスクに書き込むと徐々に大きくなり、ディスクイメージの作成時に指定したサイズまで大きくなります。
jun@Host:~$ ls -l total 140 -rw-r--r-- 1 jun jun 262144 2009-12-27 23:21 u91064s.qcow2
ゲストOSとして64ビット Ubuntu 9.10 サーバ版のインストール
ホストのCD-ROMドライブに ubuntu910-server-amd64 の CD-ROM をセットして仮想マシンを起動してインストールを開始します。仮想ディスクイメージは上で作成したファイルを指定します。「-cdrom /dev/cdrom」は CD-ROM としてホストのドライブを使う指定です。「-boot d」は起動ドライブをCD-ROMとする指定です。
sudo kvm -hda u91064s.qcow2 -cdrom /dev/cdrom -boot d -m 512 -vnc :0
VNCビューアでIPアドレスをホストマシンのIPアドレス、ポートを5900として接続するとゲストマシンの起動画面が表示されます。最初にインストールに使用する言語の指定です。ここではデフォルトのEnglishのままでいきます。
Ubuntuを仮想ハードディスクにインストールするため、「Install Ubuntu Server」を選択します。
使う言語の指定です。サーバとして利用するのでコンソールが日本語を表示できない場合を考えてEnglishにしました。
国の指定です。日本を指定する場合は other / Asia / Japan とたどります。
キーボードのレイアウトの指定です。日本語のキーボードは検出されないので、ここでは <No> を選択します。
Japanを選択します。
普通は「Japan - OADG 109A」です。
ホストの名前を設定します。適当に名前を決めてください。/etc/hostname と /etc/hosts というテキストファイルの内容を書き換えれば後から変更できます。
Ubuntuをインストールするハードディスクの構成を選択します。仮想マシンの仮想ディスクイメージにインストールする場合は「use entire disk」としてディスク全体を使ってインストールしても問題ありません。
表示されたハードディスクが消去されるという警告です。間違いがなければエンターキーで次に進みます。
フォーマットされるパーティションの情報が表示されます。
ユーザの名前を入力します。
アカウントに使うユーザ名を入力します。
パスワードを入力します。
確認のため、もう一度パスワードを入力します。
ホームディレクトリを暗号化する場合は <Yes> を選択します。普通は <No> で問題ありません。
インターネットへの接続がプロキシサーバを経由する場合はここで設定します。認証が必要な場合もユーザ名、パスワードをここで設定します。自宅で使う場合は何も設定しなくても大丈夫です。ここで設定しない場合でも、あとから以下の内容のテキストファイルを /etc/apt/apt.conf として置けば同じです。
Acquire::https::Proxy "https://ユーザ名:パスワード@プロキシIPアドレス:ポート番号";
システムのアップデートを自動で行うかどうかを指定します。
サーバをどういった目的で使うかが決まっていれば、ここでインストールするソフトウェアを指定できます。下の例は「データベースとしてPostgreSQLを使って、PHPでプログラムを作成、ApacheでWebサーバを動作させる。SSHで接続する。Windows機とファイルのやり取りもしたい。」といった場合の選択です。「LAMP Server」を選択すると MySQL もインストールされますが、不要ならば後から「apt-get remove mysql-common」を実行します。
仮想環境を入れるためのホストの場合は、ほとんど何も設定しなくても大丈夫です。仮想環境用にKVMを入れる場合も「sudo apt-get install qemu-kvm」するだけなので、ここで「Virtual Machine Host」を選択することはないと思います。選択するとlibvirt-bin、libxen3 等もインストールされますが、Xenを使わないなら不要です。
LAMPサーバを選択した場合はMySQLの管理者用のパスワードが求められます。
MySQLの管理者用のパスワードの再確認です。
インストールの終了です。
ディスクイメージのサイズを確認します。
jun@Host:~$ ls -lt -rw-r--r-- 1 jun jun 1315045376 2009-12-28 00:22 u91064s.qcow2
仮想ハードディスクからゲストOSの起動
仮想環境の場合は自動的に再起動されないので、「kvm -hda ディスクイメージ -boot c」として仮想ディスクイメージから起動します。ゲスト用のメモリは512MB(-m 512)、ゲストの出力は vnc の場合のコマンドです。vncでなく起動したコンソール(-curses)にゲストの出力を表示することもできます。
sudo kvm -hda u91064s.qcow2 -boot c -m 512 -vnc :0
ネットワークカードの設定(-net)を省略するとホストがdhcpサーバ兼ルータとして働き、ゲストのIPアドレスは以下の例のように 10.0.2.15 といったIPアドレスが自動的に設定されます。
ここでは起動の確認だけにします。各種の設定は後述します。
ホスト側のネットワークの設定
物理的には1台のマシンをネットワーク的には独立した3台のサーバがスイッチングハブで接続されている状態に設定します。
+------+ +-----------------------------------+ | GW +-----+ Switching HUB | +------+ +----+-------------+-------------+--+ 172.18.21.1 | | | +----+-----+ +---+-----+ +---+-----+ | HOST | | GUEST0 | | GUEST1 | +----------+ +---------+ +---------+ 172.18.21.80 172.18.21.90 172.18.21.91
ホストとなるマシンのネットワークカード(eth0)の内側にブリッジ(br0)があり、仮想マシンはtap デバイスを介してブリッジに接続します。
+-----------------------------------------+ | Host : Ubuntu 9.10 amd64 sever | | | +---+----+ +---------------+ | | eth0 +---------+ Switching HUB | | +---+----+ | br0 | | | +-+----------+--+ | | | | | | +------+-+ +-+------+ | | | tap0 | | tap1 | | | +---+----+ +---+----+ | | | | | | +---+----+ +---+----+ | | | KVM | | KVM | | | | QEMU | | QEMU | | | +--------+ +--------+ | | | Guest0 | | Guest1 | | | | LINUX | | LINUX | | | +--------+ +--------+ | +-----------------------------------------+
ブリッジの生成
最初にホストのネットワークカード(NIC)を自分宛のEthernetフレーム以外も受け付けるプロミスキャスモード(promiscuous mode)に変更します。プロミスキャスモードにすることでEthernetフレームの宛先MACアドレスが自分と異なる場合でも読み込むことができるため、ブリッジとして動作できるようになります。
次にホスト内にブリッジを生成して、eth0をブリッジに繋ぎかえます。ブリッジとは Ethernet Bridge のことで、物理的には普通のスイッチングハブ(レイヤー2スイッチ)と考えることができます。 qemu-kvm をインストールすると自動的にインストールされる bridge-utils パッケージのコマンド 「brctl addbr ブリッジ名」で生成できます。
ブリッジを生成して、eth0を繋ぎかえる時にネットワークは一旦切断されるため、シェルスクリプトにしておけばリモートからでも連続してコマンドを実行できます。ブリッジにIPアドレスを設定するとホストも外部ネットワークに接続できます。ネットワークは一旦切断されるため、リモートからSSHで接続している場合は再接続する必要があります。
次に示す「bridge.sh」で上記の設定を一気に行います。最初にあるシェル変数のIPとGATEWAYの値は環境にあわせて変更してください。「sudo sh bridge.sh」で実行できます。 ホストの起動時に自動的にブリッジを生成する方法は後述します。
jun@Host:~$ cat bridge.sh #!/bin/sh IP=172.18.21.80 # ホストのIPアドレス GATEWAY=172.18.21.1 # ルータのLAN側IPアドレス echo "change IP address : $IP" ifconfig eth0 0.0.0.0 promisc up # プロミスキャスモードに設定 brctl addbr br0 # ブリッジの作成 brctl addif br0 eth0 # ブリッジにeth0を接続 ifconfig br0 up # ブリッジを起動 ifconfig br0 $IP netmask 255.255.255.0 # ブリッジにIP設定 route add default gw $GATEWAY # ゲートウェイ設定
実行すると ifconfig の出力は以下のようになります。ブリッジのbr0にIPアドレスが設定され、eth0 はプロミスキャスモード(PROMISC)になっていることが確認できます。
jun@Host:~$ ifconfig br0 Link encap:Ethernet HWaddr 00:1d:60:6d:ae:b4 inet addr:172.18.21.80 Bcast:172.18.21.255 Mask:255.255.255.0 inet6 addr: fe80::21d:60ff:fe6d:aeb4/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:85 errors:0 dropped:0 overruns:0 frame:0 TX packets:58 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:8515 (8.5 KB) TX bytes:6822 (6.8 KB) eth0 Link encap:Ethernet HWaddr 00:1d:60:6d:ae:b4 inet6 addr: fe80::21d:60ff:fe6d:aeb4/64 Scope:Link UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1 RX packets:1618 errors:0 dropped:0 overruns:0 frame:0 TX packets:1260 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:220688 (220.6 KB) TX bytes:340693 (340.6 KB) Interrupt:17 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:144 errors:0 dropped:0 overruns:0 frame:0 TX packets:144 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:23876 (23.8 KB) TX bytes:23876 (23.8 KB)
ホストの起動時に自動的にブリッジを生成するには /etc/network/interfaces を以下のように変更します。
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). # The loopback network interface auto lo iface lo inet loopback # The primary network interface #auto eth0 #iface eth0 inet dhcp auto br0 iface br0 inet static address 172.18.21.80 netmask 255.255.255.0 network 172.18.21.0 broadcast 172.18.21.255 gateway 172.18.21.1 pre-up ifconfig eth0 down pre-up ifconfig eth0 0.0.0.0 promisc up pre-up brctl addbr br0 pre-up brctl addif br0 eth0 pre-up ifconfig eth0 up post-down ifconfig eth0 down post-down brctl delif br0 eth0
ホストを起動するとブリッジが有効になっていることが「ifconfig」で確認できます。
ゲストOSの起動と設定
ゲストOSを起動して、ホスト内に作成したブリッジに接続する場合は、kvm コマンドにネットワークに関するオプション(-net)を2つ指定します。「-net nic」と「-net tap,ifname=tap0,script=/etc/qemu-ifup」です。
sudo kvm -m 512 -boot c -curses -hda u91064s.qcow2 \ -net tap,ifname=tap0,script=/etc/qemu-ifup
/etc/qemu-ifup は kvmのオプション(-net tap,ifname=)で指定した tap デバイスとブリッジを接続する以下のようなコマンドを実行します。
/sbin/ifconfig tap0 0.0.0.0 up /usr/sbin/brctl addif br0 tap0
qemu-ifupは引数からtapデバイス名を受け取り、ブリッジ名をip routeから取得するスクリプトになっているため、上記のコマンドが直接書いてあるわけではありません。
次のコマンドは、qcow2形式のディスクイメージ u91064s.qcow2 をhdaに接続、そのハードディスクから起動(-boot c)します。ゲスト用のメモリは 512Mバイト(-m 512)、ゲストの出力は起動したコンソール(-curses)、ネットワークカードのMACアドレスを指定(-net nic,macaddr=52:54:00:12:34:56)、TAPアダプタに接続(-net tap,ifname=tap0)します。TAPアダプタとはLinuxのプロセスからネットワークデバイスとして読み書きできる仮想デバイスです。
sudo kvm -m 512 -boot c -curses \ -drive file=u91064s.qcow2,if=virtio,boot=on \ -net nic,model=virtio -net tap,ifname=tap0,script=/etc/qemu-ifup
ゲスト側のIPアドレスはスクリプトで固定IPを設定しています。ネットワークカードのデバイス名がeth0とは限らないため、「ifconfig -a」から取得しています。
#!/bin/sh IP=172.18.21.90 NIC=`/sbin/ifconfig -a| awk '$1 ~ /^eth/ {print $1}'` echo $NIC echo $IP ifconfig $NIC $IP netmask 255.255.255.0 route add default gw 172.18.21.1
Virtio による準仮想化
ゲストOS上で動作する準仮想化ドライバ(Paravirtualized driver)を使ってネットワークとブロックデバイスのアクセスを高速化できます。virtioドライバはUbuntuのカーネルに用意されているため、特に何も用意する必要はありません。KVMの起動時に指定するだけです。ネットワークには「model=virtio」、ディスクには「if=virtio」を次のように追加します。ドライブの指定には「-hda」ではなく、「-drive」を使います。
kvm -m 512 -boot c -curses \ -drive file=u91064s.qcow2,if=virtio,boot=on \ -net nic,model=virtio -net tap,ifname=tap0,script=/etc/qemu-ifup
速度の比較
1000baseT(1Gbps)で接続されたLAN内の無印玄箱(100Mbps)のWebページから400MBのファイルをダウンロードしてホストとゲストの速度を比較します。
ホスト
2.66GHzのCore2Duo(E6750)、メモリ6GBでUbuntu9.10-server-amd64上で直接ダウンロードします。ダウンロードしたファイルを伸張する時間も測定しました。
jun@Host:~/tmp$ time wget https://172.18.21.69/u91064s.qcow2.tgz --2009-12-31 01:16:55-- https://172.18.21.69/u91064s.qcow2.tgz Connecting to 172.18.21.69:80... connected. HTTP request sent, awaiting response... 200 OK Length: 406601328 (388M) [application/x-gzip] Saving to: `u91064s.qcow2.tgz' 100%[======================================>] 406,601,328 9.39M/s in 41s 2009-12-31 01:17:37 (9.39 MB/s) - `u91064s.qcow2.tgz' saved [406601328/406601328] real 0m41.352s user 0m0.400s sys 0m3.240s jun@Host:~/tmp$ time tar zxf u91064s.qcow2.tgz real 0m23.582s user 0m9.890s sys 0m3.140s
ダウンロードしたファイルと伸張したファイルのサイズです。
jun@Guest0:~$ ls -l -rw-r--r-- 1 jun jun 1315045376 2009-12-28 00:22 u91064s.qcow2 -rw-r--r-- 1 jun jun 406601328 2009-12-28 00:37 u91064s.qcow2.tgz
玄箱HG(1Gbps)からもダウンロード
jun@Host:~/tmp$ time wget https://172.18.21.70/u91064s.qcow2.tgz --2009-12-31 02:16:11-- https://172.18.21.70/u91064s.qcow2.tgz Connecting to 172.18.21.70:80... connected. HTTP request sent, awaiting response... 200 OK Length: 406601328 (388M) [application/x-gzip] Saving to: `u91064s.qcow2.tgz.1' 100%[======================================>] 406,601,328 13.8M/s in 28s 2009-12-31 02:16:39 (13.9 MB/s) - `u91064s.qcow2.tgz.1' saved [406601328/406601328] real 0m27.982s user 0m0.310s sys 0m2.600s
ゲスト
ゲストOSでの評価は仮想ディスクイメージをコピーして、全く同じ状態で評価しています。コピーしているため、ホストのドライブ上のディスクイメージの状態は全く同じではありません。
sudo kvm -m 512 -boot c -curses -hda u91064s.qcow2 \ -net nic -net tap,ifname=tap0,script=/etc/qemu-ifup
カーネルモジュールを表示すると、QEMUが用意している Realtek RTL8139 というネットワークカードのエミュレーションを使っていることがわかります。
jun@Guest0:~$ lsmod Module Size Used by iptable_filter 3872 0 ip_tables 21168 1 iptable_filter x_tables 25768 1 ip_tables ppdev 8232 0 virtio_balloon 5412 0 parport_pc 37352 1 lp 11908 0 psmouse 57124 0 serio_raw 6596 0 parport 40528 3 ppdev,parport_pc,lp i2c_piix4 11728 0 floppy 65192 0 8139too 27360 0 virtio_pci 9160 0 virtio_ring 5344 1 virtio_pci virtio 5956 2 virtio_balloon,virtio_pci 8139cp 23200 0 mii 6368 2 8139too,8139cp
QEMUのモニターでも Realtek RTL8139 が使われていることが確認できます。
QEMU 0.11.0 monitor - type 'help' for more information (qemu) info network VLAN 0 devices: tap.0: ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown rtl8139.0: model=rtl8139,macaddr=52:54:00:12:34:56 (qemu) info block ide0-hd0: type=hd removable=0 file=u91064s.qcow2 ro=0 drv=qcow2 encrypted=0 ide1-cd0: type=cdrom removable=1 locked=0 [not inserted] floppy0: type=floppy removable=1 locked=0 [not inserted] sd0: type=floppy removable=1 locked=0 [not inserted] (qemu) c
400MBのファイルを玄箱においてHTTPでダウンロードしました。ダウンロードしたファイルを伸張する時間も測定しました。
jun@Guest0:~$ time wget https://172.18.21.69/u91064s.qcow2.tgz --2009-12-31 01:02:13-- https://172.18.21.69/u91064s.qcow2.tgz Connecting to 172.18.21.69:80... connected. HTTP request sent, awaiting response... 200 OK Length: 406601328 (388M) [application/x-gzip] Saving to: `u91064s.qcow2.tgz' 100%[======================================>] 406,601,328 9.17M/s in 42s 2009-12-31 01:02:55 (9.26 MB/s) - `u91064s.qcow2.tgz' saved [406601328/406601328] real 0m41.912s user 0m0.360s sys 0m17.500s jun@Guest0:~$ time tar zxf u91064s.qcow2.tgz real 0m38.769s user 0m10.830s sys 0m3.020s
玄箱HGでも測定
jun@Guest0:~$ time wget https://172.18.21.70/u91064s.qcow2.tgz --2009-12-31 02:13:54-- https://172.18.21.70/u91064s.qcow2.tgz Connecting to 172.18.21.70:80... connected. HTTP request sent, awaiting response... 200 OK Length: 406601328 (388M) [application/x-gzip] Saving to: `u91064s.qcow2.tgz' 100%[======================================>] 406,601,328 14.6M/s in 27s 2009-12-31 02:14:20 (14.6 MB/s) - `u91064s.qcow2.tgz' saved [406601328/406601328] real 0m26.623s user 0m0.220s sys 0m14.710s
ゲスト virtio
ネットワークとブロックデバイスにvirtioを使って準仮想化します。
sudo kvm -m 512 -boot c -curses \ -drive file=u91064s.qcow2,if=virtio,boot=on \ -net nic,model=virtio -net tap,ifname=tap0,script=/etc/qemu-ifup
カーネルモジュールを表示すると、Realtek RTL8139 用のモジュールがロードされていません。そのかわり virtio_net が使われています。
jun@Guest0:~$ lsmod Module Size Used by iptable_filter 3872 0 ip_tables 21168 1 iptable_filter x_tables 25768 1 ip_tables ppdev 8232 0 virtio_balloon 5412 0 parport_pc 37352 1 psmouse 57124 0 serio_raw 6596 0 lp 11908 0 i2c_piix4 11728 0 parport 40528 3 ppdev,parport_pc,lp virtio_blk 7816 3 virtio_net 16896 0 floppy 65192 0 virtio_pci 9160 0 virtio_ring 5344 1 virtio_pci virtio 5956 4 virtio_balloon,virtio_blk,virtio_net,virtio_pci
QEMUのモニターでも virtio が使われていることが確認できます。
QEMU 0.11.0 monitor - type 'help' for more information (qemu) info network VLAN 0 devices: tap.0: ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown virtio.0: model=virtio,macaddr=52:54:00:12:34:56 (qemu) info block virtio0: type=hd removable=0 file=u91064s.qcow2 ro=0 drv=qcow2 encrypted=0 ide1-cd0: type=cdrom removable=1 locked=0 [not inserted] floppy0: type=floppy removable=1 locked=0 [not inserted] sd0: type=floppy removable=1 locked=0 [not inserted]
400MBのファイルを玄箱においてHTTPでダウンロードしました。
jun@Guest0:~$ time wget https://172.18.21.69/u91064s.qcow2.tgz --2009-12-31 01:10:42-- https://172.18.21.69/u91064s.qcow2.tgz Connecting to 172.18.21.69:80... connected. HTTP request sent, awaiting response... 200 OK Length: 406601328 (388M) [application/x-gzip] Saving to: `u91064s.qcow2.tgz' 100%[======================================>] 406,601,328 9.53M/s in 47s 2009-12-31 01:11:29 (8.26 MB/s) - `u91064s.qcow2.tgz' saved [406601328/406601328] real 0m47.004s user 0m0.620s sys 0m5.080s jun@Guest0:~$ time tar zxf u91064s.qcow2.tgz real 0m48.037s user 0m12.110s sys 0m4.880s
玄箱HGでも測定
jun@Guest0:~$ time wget https://172.18.21.70/u91064s.qcow2.tgz --2009-12-31 02:19:39-- https://172.18.21.70/u91064s.qcow2.tgz Connecting to 172.18.21.70:80... connected. HTTP request sent, awaiting response... 200 OK Length: 406601328 (388M) [application/x-gzip] Saving to: `u91064s.qcow2.tgz' 100%[======================================>] 406,601,328 13.0M/s in 30s 2009-12-31 02:20:09 (13.0 MB/s) - `u91064s.qcow2.tgz' saved [406601328/406601328] real 0m29.820s user 0m0.360s sys 0m5.510s
結果
100Mbps程度の転送ではホストとゲストに大した差は出ません。virtioを使用するとゲストのシステムの負荷はかなり小さくなることが分かります。
複数のゲストOSを使う
ゲストOSを複数起動するためには、ゲストのディスクイメージを別々に用意して起動します。1つのディスクイメージを複数の仮想マシンで共有することはできません。同じ環境のゲストを使う場合でもイメージをコピーする必要があります。今回はサーバとして使用するのでゲストごとにホスト名、ネットワーク設定が必要となります。
1番目のゲストをゲスト0、2番目のゲストをゲスト1とします。/etc/hostname もそれぞれ Guest0、Guest1としました。ゲスト0の起動
ゲストを起動するためのKVMコマンドのオプションはMACアドレス(macaddr=52:54:00:12:34:00)とTAPデバイスの名称の指定(ifname=tap0)を行います。
sudo kvm -m 512 -boot c -curses \ -drive file=u91064s.qcow2,if=virtio,boot=on \ -net nic,macaddr=52:54:00:12:34:00,model=virtio \ -net tap,ifname=tap0,script=/etc/qemu-ifup
ネットワークの設定
ゲストのネットワークを設定するシェルスクリプトを用意しました。ここでは固定IPを起動後に設定します。ネットワークカードのデバイス名がeth0とは限らないため、「ifconfig -a」から取得しています。ゲストのIPアドレスとルータのIPアドレスの下位バイトを最初に書き込んでおくことにしています。
#!/bin/sh IP=172.18.21.90 GW=.1 #GW=.254 IP24=`expr $IP : "\(.*\)\.[0-9]"` NIC=`/sbin/ifconfig -a| awk '$1 ~ /^eth/ {print $1}'` echo $NIC echo "ip address :" $IP echo "broadcast :" $IP24.255 echo "gateway :" $IP24$GW ifconfig $NIC $IP netmask 255.255.255.0 broadcast $IP24.255 route add default gw $IP24$GW
root@Guest0~# ifconfig -a eth1 Link encap:Ethernet HWaddr 52:54:00:12:34:00 inet addr:172.18.21.90 Bcast:172.18.21.255 Mask:255.255.255.0 inet6 addr: fe80::5054:ff:fe12:3400/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:46 errors:0 dropped:0 overruns:0 frame:0 TX packets:28 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:13303 (13.3 KB) TX bytes:3005 (3.0 KB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:52 errors:0 dropped:0 overruns:0 frame:0 TX packets:52 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:17113 (17.1 KB) TX bytes:17113 (17.1 KB)
ゲスト1の起動
ゲスト1を起動するにはゲスト0と異なる仮想ディスクイメージファイル(file=u91064sB.qcow2)、MACアドレス(macaddr=52:54:00:12:34:01)とTAPデバイスの名称(ifname=tap1)の指定が必要です。
sudo kvm -m 512 -boot c -curses \ -drive file=u91064sB.qcow2,if=virtio,boot=on \ -net nic,macaddr=52:54:00:12:34:01,model=virtio \ -net tap,ifname=tap1,script=/etc/qemu-ifup
ネットワークの設定
ゲスト0と同様にネットワークを設定するシェルスクリプトを用意しました。ゲスト0と異なる固定IP(IP=172.18.21.91)を起動後に設定します。
#!/bin/sh IP=172.18.21.91 GW=.1 #GW=.254 IP24=`expr $IP : "\(.*\)\.[0-9]"` NIC=`/sbin/ifconfig -a| awk '$1 ~ /^eth/ {print $1}'` echo $NIC echo "ip address :" $IP echo "broadcast :" $IP24.255 echo "gateway :" $IP24$GW ifconfig $NIC $IP netmask 255.255.255.0 broadcast $IP24.255 route add default gw $IP24$GW
root@Guest0~# ifconfig eth1 Link encap:Ethernet HWaddr 52:54:00:12:34:01 inet addr:172.18.21.91 Bcast:172.18.21.255 Mask:255.255.255.0 inet6 addr: fe80::5054:ff:fe12:3401/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:199 errors:0 dropped:0 overruns:0 frame:0 TX packets:16 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:53407 (53.4 KB) TX bytes:1677 (1.6 KB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:109 errors:0 dropped:0 overruns:0 frame:0 TX packets:109 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:26401 (26.4 KB) TX bytes:26401 (26.4 KB)
ホスト
ホスト側のネットワークの状態です。eth0 以外にも br0、tap0、tap1 が動作していることがわかります。
jun@Host:~$ ifconfig -a br0 Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx inet addr:172.18.21.80 Bcast:172.18.21.255 Mask:255.255.255.0 inet6 addr: fe80::21d:60ff:fe6d:aeb4/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:4382 errors:0 dropped:0 overruns:0 frame:0 TX packets:3590 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:678128 (678.1 KB) TX bytes:1546751 (1.5 MB) eth0 Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx inet6 addr: fe80::21d:60ff:0e6d:aeb4/64 Scope:Link UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1 RX packets:4555 errors:0 dropped:0 overruns:0 frame:0 TX packets:3724 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:748183 (748.1 KB) TX bytes:1562023 (1.5 MB) Interrupt:17 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:11 errors:0 dropped:0 overruns:0 frame:0 TX packets:11 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:744 (744.0 B) TX bytes:744 (744.0 B) tap0 Link encap:Ethernet HWaddr da:5b:2f:45:26:e0 inet6 addr: fe80::d85b:2fff:fe45:26e0/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:58 errors:0 dropped:0 overruns:0 frame:0 TX packets:247 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:500 RX bytes:6378 (6.3 KB) TX bytes:67099 (67.0 KB) tap1 Link encap:Ethernet HWaddr ae:2c:bf:35:91:98 inet6 addr: fe80::ac2c:bfff:fe35:9198/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:22 errors:0 dropped:0 overruns:0 frame:0 TX packets:227 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:500 RX bytes:2400 (2.4 KB) TX bytes:62453 (62.4 KB)
ゲストOSをサーバとして使う
ここまでコンソールでkvmコマンドを実行することでゲストOSを起動し、ゲストOSのコンソール出力は vnc 経由(-vnc)、または起動コンソール(-curses)で表示していました。 vnc 経由では仮想マシンのグラフィック出力を転送する方法、cursesオプションはVGAへの文字出力を抽出してkvmを起動したコンソールに表示する方法となっています。どちらもPCのグラフィックカードへのコンソール出力を利用するものです。 ゲストで実行する Linux をサーバとして使用する場合は、常にコンソール出力を表示する必要はなく、ホストのバックグラウンドプロセス(デーモン)として動作すれば十分です。
ここでは仮想マシン上のゲストOSをホストと独立してサーバとして利用します。デスクトップでLinuxを使う場合と異なり、ネットワークさえつながっていればキーボードも画面もほとんど必要ありません。ホストの起動時に自動的にゲストもサーバとして起動し、メンテナンス等で必要なときだけコンソール経由でアクセスできれば理想的です。「ゲストOSはホストのバックグラウンドプロセスとして黙ってサーバとしての動作を続け、必要なときだけコンソールを表示する。」という動作をカーネルのコンソール出力をシリアル端末に切り替えて、コンソールの接続、切断を screen コマンドを利用して実現します。
- ゲストのLinuxのネットワークを設定、
- ゲストの Linux のコンソール出力をシリアル回線に出力、
- シリアルの出力を kvm を起動したホストのコンソールに表示、
- screen コマンドを利用してホストのコンソールを実端末(実画面)と分離、必要に応じてゲストのコンソールを表示。
以上の機能を実現する方法を試してみました。
ゲストのネットワーク設定
/etc/network/interfaces のeth0 に関する部分をコメントアウトしました。
jun@Guest0:~$ cat /etc/network/interfaces # This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). # The loopback network interface auto lo iface lo inet loopback # The primary network interface #auto eth0 #iface eth0 inet dhcp
今回は起動の最後に実行される(/etc/init.d/rc.localから呼ばれる) /etc/rc.local でネットワークを設定することにしました。exit 0 の前にネットワークの設定を追加します。
root@Guest0/etc# cat /etc/rc.local #!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. IP=172.18.21.90 GW=.1 #GW=.254 IP24=`expr $IP : "\(.*\)\.[0-9]"` NIC=`/sbin/ifconfig -a| awk '$1 ~ /^eth/ {print $1}'` ifconfig $NIC $IP netmask 255.255.255.0 broadcast $IP24.255 route add default gw $IP24$GW exit 0
/etc/rc.localが実行可能(x)になっていることを確認します。
jun@Guest0/etc$ ls -l rc.local -rwxr-xr-x 1 root root 517 2010-01-06 01:17 rc.local
ゲストを再起動すると /etc/rc.local で設定した固定IPで起動されます。
カーネルのシリアル出力設定
ゲスト側のカーネルのコンソール出力をシリアルに出力するように変更するため、ゲスト側の grub のカーネルのコマンドラインをシリアル用に設定します。Ubuntu 9.10 は GRUB2を使っているため、/boot/grub/menu.lst ではなく、/etc/default/grub を変更した後、「update-grub」を実行します。
jun@Guest0/etc/init$ cat /etc/default/grub # If you change this file, run 'update-grub' afterwards to update # /boot/grub/grub.cfg. GRUB_DEFAULT=0 GRUB_HIDDEN_TIMEOUT=0 GRUB_HIDDEN_TIMEOUT_QUIET=true GRUB_TIMEOUT="10" GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8" # Uncomment to disable graphical terminal (grub-pc only) #GRUB_TERMINAL=console # The resolution used on graphical terminal # note that you can use only modes which your graphic card supports via VBE # you can see them in real GRUB with the command `vbeinfo' #GRUB_GFXMODE=640x480 # Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux #GRUB_DISABLE_LINUX_UUID=true # Uncomment to disable generation of recovery mode menu entrys #GRUB_DISABLE_LINUX_RECOVERY="true"
Ubuntu 9.10 は Upstart を使っているため、inittab がありません。ゲスト側の /etc/init/tty1.conf を変更して、シリアル回線からログインできるようにします。
jun@Guest0/etc/init$ cat /etc/init/tty1.conf # tty1 - getty # # This service maintains a getty on tty1 from the point the system is # started until it is shut down again. start on stopped rc RUNLEVEL=[2345] stop on runlevel [!2345] respawn exec /sbin/getty -L ttyS0 115200 vt100 #exec /sbin/getty -8 38400 tty1
kvm の起動オプションに「-serial stdio」を指定することで、ゲストOSのシリアル出力を起動コンソールの標準入出力(stdio)に表示させます。
jun@Host:~$ sudo kvm -m 512 -boot c -nographic -serial stdio \ -drive file=u91064s.qcow2,if=virtio,boot=on \ -net nic,macaddr=52:54:00:12:34:00,model=virtio \ -net tap,ifname=tap0,script=/etc/qemu-ifup Ubuntu 9.10 u91064s ttyS0 u91064s login: jun Password: Last login: Wed Jan 6 23:10:05 JST 2010 on tty1 Linux u91064s 2.6.31-14-server #48-Ubuntu SMP Fri Oct 16 15:07:34 UTC 2009 x86_64 To access official Ubuntu documentation, please visit: https://help.ubuntu.com/ System information as of Wed Jan 6 23:12:43 JST 2010 System load: 0.0 Memory usage: 12% Processes: 78 Usage of /: 23.6% of 3.71GB Swap usage: 0% Users logged in: 0 Graph this data and manage this system at https://landscape.canonical.com/
コントロールと「a」を同時に押した後、「c」を押すことで QEMU(kvm)のモニター画面に切り替えられます。もう一度「C-a c」を押すとコンソール出力に切り替えることができます。
jun@Guest0:~$ C-a h print this help C-a x exit emulator C-a s save disk data back to file (if -snapshot) C-a t toggle console timestamps C-a b send break (magic sysrq) C-a c switch between console and monitor C-a C-a sends C-a QEMU 0.11.0 monitor - type 'help' for more information (qemu) jun@Guest0:~$
ゲストのコンソール出力
screen コマンドは端末の出力を物理的な端末と切り離したり、再接続したりすることができるコマンドです。screen からゲストを起動してゲストのコンソール出力を実端末(ターミナル画面)と切り離したり、再接続したりできると便利です。
以下のコマンドを入力して1番目のゲストを起動します。「screen -S Guest0」の行は、screen のセッション(ウィンドウの集合)にGuest0という名前を付けるオプションです。ゲストOSで動作させるサーバの名前などをセッション名として指定すると再接続する場合に識別しやすくなります。
screen -S Guest0 sudo kvm -m 512 -boot c -nographic -serial stdio \ -drive file=u91064s.qcow2,if=virtio,boot=on \ -net nic,macaddr=52:54:00:12:34:00,model=virtio \ -net tap,ifname=tap0,script=/etc/qemu-ifup
ゲストのLinuxが起動して、ログインプロンプトが表示されるまで私の環境で 5 秒程度の時間がかかります。kvmコマンドの応答と考えるとちょっと長く感じますが、サーバが5秒で起動すると考えると非常に速いです。
jun@Host:~$ sudo kvm -m 512 -boot c -nographic -serial stdio \ > -drive file=u91064s.qcow2,if=virtio,boot=on \ > -net nic,macaddr=52:54:00:12:34:00,model=virtio \ > -net tap,ifname=tap0,script=/etc/qemu-ifup [sudo] password for jun: Ubuntu 9.10 Guest0 ttyS0 Guest0 login: jun Password: Last login: Thu Jan 7 01:42:06 JST 2010 on ttyS0 Linux Guest0 2.6.31-14-server #48-Ubuntu SMP Fri Oct 16 15:07:34 UTC 2009 x86_64 To access official Ubuntu documentation, please visit: https://help.ubuntu.com/ System information as of Thu Jan 7 01:45:33 JST 2010 System load: 0.0 Memory usage: 9% Processes: 78 Usage of /: 23.6% of 3.71GB Swap usage: 0% Users logged in: 0 Graph this data and manage this system at https://landscape.canonical.com/ jun@Guest0:~$
screenの機能で切断(デタッチ)、接続(アタッチ)ができることを確認するため、Guest0で「top」を起動しておきます。
top - 01:46:16 up 1 min, 1 user, load average: 0.00, 0.00, 0.00 Tasks: 74 total, 1 running, 73 sleeping, 0 stopped, 0 zombie Cpu(s): 0.0%us, 0.0%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.7%hi, 0.0%si, 0.0%st Mem: 504128k total, 125356k used, 378772k free, 10728k buffers Swap: 240932k total, 0k used, 240932k free, 66612k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 894 jun 20 0 19112 1268 980 R 0.7 0.3 0:00.13 top 1 root 20 0 19320 1459 1196 S 0.0 0.3 0:00.31 init 2 root 15 -5 0 0 0 S 0.0 0.0 0:00.01 kthreadd 3 root RT -5 0 0 0 S 0.0 0.0 0:00.00 migration/0 4 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd/0 5 root RT -5 0 0 0 S 0.0 0.0 0:00.00 watchdog/0 6 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 events/0 7 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 cpuset 8 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 khelper 9 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 netns 10 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 async/mgr 11 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kintegrityd/0 12 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kblockd/0 13 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kacpid 14 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kacpi_notify 15 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kacpi_hotplug 16 root 15 -5 0 0 0 S 0.0 0.0 0:00.02 ata/0
ctrl-A d を入力してホストに戻ります。次に以下のコマンドを入力して2番目のゲストを起動します。セッション名は「Guest1」と指定します。
screen -S Guest1 sudo kvm -m 512 -boot c -nographic -serial stdio \ -drive file=u91064sB.qcow2,if=virtio,boot=on \jun -net nic,macaddr=52:54:00:12:34:01,model=virtio \ -net tap,ifname=tap1,script=/etc/qemu-ifup
2つ目の仮想マシンも5秒程度で起動します。
jun@Host:~$ sudo kvm -m 512 -boot c -nographic -serial stdio \ > -drive file=u91064sB.qcow2,if=virtio,boot=on \ > -net nic,macaddr=52:54:00:12:34:01,model=virtio \ > -net tap,ifname=tap1,script=/etc/qemu-ifup Ubuntu 9.10 Guest1 ttyS0 Guest1 login: jun Password: Last login: Thu Jan 7 01:41:14 JST 2010 on ttyS0 Linux Guest1 2.6.31-14-server #48-Ubuntu SMP Fri Oct 16 15:07:34 UTC 2009 x86_64 To access official Ubuntu documentation, please visit: https://help.ubuntu.com/ System information as of Thu Jan 7 01:47:29 JST 2010 System load: 0.0 Memory usage: 9% Processes: 78 Usage of /: 23.6% of 3.71GB Swap usage: 0% Users logged in: 0 Graph this data and manage this system at https://landscape.canonical.com/
Guest1と同様にGuest1でも「top」を起動しておきます。
top - 01:48:28 up 1 min, 1 user, load average: 0.00, 0.00, 0.00 Tasks: 74 total, 1 running, 73 sleeping, 0 stopped, 0 zombie Cpu(s): 0.0%us, 0.0%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.7%hi, 0.0%si, 0.0%st Mem: 504128k total, 125184k used, 378944k free, 10716k buffers Swap: 240932k total, 0k used, 240932k free, 66552k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 885 jun 20 0 19112 1268 980 R 0.7 0.3 0:00.09 top 1 root 20 0 19320 1459 1196 S 0.0 0.3 0:00.34 init 2 root 15 -5 0 0 0 S 0.0 0.0 0:00.01 kthreadd 3 root RT -5 0 0 0 S 0.0 0.0 0:00.00 migration/0 4 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd/0 5 root RT -5 0 0 0 S 0.0 0.0 0:00.00 watchdog/0 6 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 events/0 7 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 cpuset 8 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 khelper 9 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 netns 10 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 async/mgr 11 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kintegrityd/0 12 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kblockd/0 13 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kacpid 14 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kacpi_notify 15 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kacpi_hotplug 16 root 15 -5 0 0 0 S 0.0 0.0 0:00.01 ata/0
ctrl-A d を入力してGuest1の画面を切り離し、端末をホストのシェルに切り替えます。ネットワーク越しにSSHで端末を使っている場合に「exit」でシェルを終了して切断しても、ゲストは動作したまま残ります。後日「screen -r セッション名」で元の画面に戻ることができます。
必要な作業が終われば、ctrl-A d を入力してホストに戻ります。ここでログオフして端末を閉じても、screen で動作しているセッションの一覧は「screen -ls」で次のように表示されます。
jun@Host:~$ screen -ls There are screens on: 2382.Guest1 (01/07/2010 01:47:08 AM) (Detached) 2501.Guest0 (01/07/2010 01:44:31 AM) (Detached) 2 Sockets in /var/run/screen/S-jun.
「screen -r Guest0」で最初のゲストの画面を、「screen -r Guest1」で2番目に起動したLinuxのコンソール画面を表示して通常に操作することができます。
+-----------------+ | ゲスト 0 | +---------+ | | +-----------------+ | screen | | コンソール画面 | | ホスト端末画面 | | session +------+ | | | <---| Guest0 | | | | | +---------+ +-----------------+ | | | | +-----------------+ | | +---------+ | ゲスト 1 | | | <---| screen | | | +-----------------+ | session +------+ コンソール画面 | | Guest1 | | | +---------+ | | +-----------------+
このようにゲストのコンソールは screen コマンドのセッションとして残すことができ、必要なときにはいつでも、どこからでもゲストのコンソールを操作することができるようになります。
screen は ctrl-A を使って非常に多彩な機能を提供します。しかし、QEMUのモニター画面への切り替えにも ctrl-A を使う必要があります。その場合は 「ctrl-A a」と入力することで ctrl-A がQEMUに送られます。したがってQEMUのモニターへの切り替えは「ctrl-A ac」と入力する必要があります。
screenをスクリプト内で使用
上で書いた方法では起動した後、手動(ctrl-A d)で実端末から切断(デタッチ)する必要があります。ホストの起動時に自動的にゲストを起動することができません。そこで、スクリーン起動、ゲスト起動、screenをデタッチを連続して行うスクリプトにしてみました。
Guest0用スクリプト
Guest0を screen 内で起動してデタッチするスクリプトです。
jun@Host:~$ cat start-g0.sh #!/bin/sh screen -S Guest0 -d -m kvm -m 512 -boot c \ -localtime -nographic -serial stdio \ -drive file=u91064s.qcow2,if=virtio,boot=on \ -net nic,macaddr=52:54:00:12:34:00,model=virtio \ -net tap,ifname=tap0,script=/etc/qemu-ifup
Guest1用スクリプト
Guest1を screen 内で起動してデタッチするスクリプトです。
jun@Host:~$ cat start-g1.sh #!/bin/sh screen -S Guest1 -d -m kvm -m 512 -boot c \ -localtime -nographic -serial stdio \ -drive file=u91064sB.qcow2,if=virtio,boot=on \ -net nic,macaddr=52:54:00:12:34:01,model=virtio \ -net tap,ifname=tap1,script=/etc/qemu-ifup
実行結果
Guest0とGuest1というセッション名でscreenからkvmが起動していることが確認できます。
root@Host:~$ screen -ls There are screens on: 1285.Guest1 (01/08/2010 12:58:34 AM) (Detached) 1181.Guest0 (01/08/2010 12:53:23 AM) (Detached) 2 Sockets in /var/run/screen/S-root. root@Host:~$ pstree init─┬─atd ├─cron ├─dd ├─6*[getty] ├─nmbd ├─rsyslogd───3*[{rsyslogd}] ├─2*[screen───kvm───{kvm}] ├─smbd───smbd ├─sshd───sshd───sshd───bash───su───bash───pstree ├─udevd───2*[udevd] ├─upstart-udev-br └─winbindd───winbindd
/etc/rc.local内に記述することでホストの起動直後に自動的にゲストを起動することができます。
これで3台の普通のサーバができました。後はサーバの使い方を考えるだけです。
メモ
ディスクイメージの縮小
qcow2形式のディスクイメージは使っている部分だけを記録する形式ですが、使っているうちに大きくなってきます。イメージ中の未使用の部分を削除するには qemu-img の件肝機能を使います。以下のように qcow2 から qcow2 への変換を行うことで、イメージが再構築されて小さくすることができます。u91064s.qcow2 というディスクイメージファイルを縮小して u91064s.qcow2.new にする例です。
jun@Host:~$ sudo qemu-img convert -O qcow2 u91064s.qcow2 u91064s.qcow2.new jun@Host:~$ ls -lt -rw-r--r-- 1 jun jun 1235615744 2010-01-03 20:17 u91064s.qcow2.new -rw-r--r-- 1 jun jun 1315110912 2009-12-30 22:33 u91064s.qcow2
Apacheの設定
Ubuntu でApache を設定する方法は httpd.conf を編集するスタイルではありません。忘れてしまうのでメモ。
/home/jun/public_html/index.html を https://exsample.mztn.org/~jun/ でアクセスできるようにします。
root@Guest0/etc/apache2# a2enmod userdir Enabling module userdir. Run '/etc/init.d/apache2 restart' to activate new configuration!
設定を有効にするため、httpd を再起動します。
root@Guest0/etc/apache2# /etc/init.d/apache2 restart * Restarting web server apache2 apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName ... waiting apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName [ OK ]
新しい記事があります。Ubuntu 16.04 LTS の KVM で仮想サーバ (2016/05/06)