hiroの長い冒険日記

主にコンピュータ周辺の興味を持った内容を綴ります

qemu (kvm) に Ubuntu 18.04 minimal install その3

前回は qemu (kvm) の画面周りを設定し、Host と Guest の間で Cut & Paste できるようにした。また、初期状態の「ユーザーモードネットワーク」だと Host から Guest に接続できない事が分かった。
hiro20180901.hatenablog.com
Windows10 Hyper-V 仮想マシンだと ssh で入って色々出来ていた。このままだと不便なのと、ArchLinux Wiki でオススメされているようなのと、Guest 間や Host との通信を一度ちゃんと理解しておきたかった事から、virtio を試してみた。

virtio (block, network)

準仮想化 (Paravirtualization) された I/O framework が virtio である。真面目に全部を仮想化すると無駄が多いので、Guest 側に driver (Windows 版もある) を入れて Host 側と協調する事で効率的に動かそう、という技術だと理解した。仮想環境について調べていると英語の記事が見つかり Paravirtualization という単語がよく出てきて、その時には理解できなかったが、やっと意味が分かった。

次の Qiita の記事が、リンク先を含めて参考になった。
qiita.com

ArchLinux Wiki も日本語で助かっている。
wiki.archlinux.jp
「9 virtio ドライバーのインストール」の項に記載がある。

debianubuntu 共に kernel module が入っていた。

$ find /lib/modules | grep -i virtio_blk.ko
/lib/modules/4.9.0-8-amd64/kernel/drivers/block/virtio_blk.ko

block device

virtual disk image を指定するのに、-hda の代わりに -boot order=c -drive file=filename,if=virtio を使用する。今回は Guest は Ubuntu 18.04 なので、grub も fstab も UUID で指定されているので、何も変更しなくても OK。
Host:

$ kvm -vga qxl -spice port=5930,disable-ticketing -device virtio-serial-pci -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent -boot order=c -drive file=./qemu_image/ubuntu_test_minimal,if=virtio -m 2048 -smp 2 -monitor stdio

体感で分かる位、向上した。
Guest:

$ sudo lsmod | grep virtio
virtio_blk             20480  2
$ sudo dmesg -t | grep vda
 vda: vda1
EXT4-fs (vda1): mounted filesystem with ordered data mode. Opts: (null)
EXT4-fs (vda1): re-mounted. Opts: errors=remount-ro
input: spice vdagent tablet as /devices/virtual/input/input5

sda の代わりに vda で認識していた。

network

Guest の default では e1000 で動作していた。
Guest:

$ sudo dmesg -t | grep eth0
e1000 0000:00:03.0 eth0: (PCI:33MHz:32-bit) 52:54:00:12:34:56
e1000 0000:00:03.0 eth0: Intel(R) PRO/1000 Network Connection
e1000 0000:00:03.0 ens3: renamed from eth0

www.nexia.jp
こちらを参考に、bridge を作成、接続してイチから network を作ってみた。以下、記載なき場合は Host 側での作業となる。

bridge-utils install

bridge を作成するための brctl を入れる。

$ sudo apt install bridge-utils

Host 側の物理 NIC を bridge に接続する

Host の NIC は eth0 ではなく enp3s0 になっている。

# ifconfig enp3s0 0.0.0.0 promisc up
# brctl addbr br0
# brctl addif br0 enp3s0
# ifconfig br0 up
# dhclient br0

やっている内容は以下の通り。

  1. enp3s0 の ip address を無効にして、promiscuous mode(Wikipedia) にする
  2. bridge br0 を作成する
  3. br0 に enp3s0 を追加
  4. br0 を up
  5. br0 に ip address を割り当てる (お家LAN の dhcpd = router から)

だが、LXDE Desktop 環境では、これだけではダメ。上記 1 の段階で、ip address を無効にしても勝手に ip address が振られ、br0 と重なって通信できなくなる。どうしようか...たぶん、dhclient が掴みっぱなしなのか。

# ps x | grep dhclient
 1010 ?        Ss     0:00 /sbin/dhclient -v -cf /var/lib/wicd/dhclient.conf enp3s0
 2278 pts/0    S+     0:00 grep dhclient
# dpkg -S /var/lib/wicd
wicd-daemon: /var/lib/wicd
# apt list --installed | grep wicd
python-wicd/stable,now 1.7.4+tb2-5~deb9u1 all [インストール済み、自動]
wicd/stable,now 1.7.4+tb2-5~deb9u1 all [インストール済み、自動]
wicd-daemon/stable,now 1.7.4+tb2-5~deb9u1 all [インストール済み、自動]
wicd-gtk/stable,now 1.7.4+tb2-5~deb9u1 all [インストール済み、自動]
# apt show wicd-daemon
... 略 ...
Description: wired and wireless network manager - daemon
 Wicd is a general-purpose network configuration server which aims
 to provide a simple but flexible interface for connecting to networks.
... 略 ...

なので、wicd が network の設定を掴んでいそう。

# dpkg -L wicd-daemon | grep etc
/etc
/etc/dbus-1
/etc/dbus-1/system.d
/etc/dbus-1/system.d/wicd.conf
/etc/default
/etc/default/wicd
/etc/init.d
/etc/init.d/wicd
... 略 ...

system.d と init.d の2つあるけど、どちらが停止 script かな...
www.debian.org
debian のネットワーク設定を見ると、おそらく init.d の方だろう。

# /etc/init.d/wicd stop

で停止できた。この後で上記の1〜5の設定を行えば、Host は外界と接続された状態となった。最近の新しいやり方で、bridge を自動で設定する方法は後で調べよう。

Guest の virtio-net を bridge に接続する

tap を使うには sudo で実行しないとダメだった。
Host:

$ sudo kvm -vga qxl -spice port=5930,disable-ticketing -device virtio-serial-pci -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent -boot order=c -drive file=./qemu_image/ubuntu_test_minimal,if=virtio -net nic,model=virtio -net tap,ifname=tap0 -m 2048 -smp 2 -monitor stdio

前回のように spicy で接続すると、お家 router から ip address を渡されて network に接続された状態となった。
Host:

# brctl show
bridge name	bridge id		STP enabled	interfaces
br0		8000.20cf30877f51	no		enp3s0
							tap0

ちゃんと bridge に接続されている。Guest 側でも外界に接続できている。ICMP も通るので ping や traceroute も通った。Host -> Guest へ ssh で接続できた。

spicy が落ちた時の error message

GSpice-Message: main channel: opened

(spicy:3888): Gdk-ERROR **: The program 'spicy' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadMatch (invalid parameter attributes)'.
  (Details: serial 3384 error_code 8 request_code 139 (RENDER) minor_code 27)
  (Note to programmers: normally, X errors are reported asynchronously;
   that is, you will receive the error a while after causing it.
   To debug your program, run it with the GDK_SYNCHRONIZE environment
   variable to change this behavior. You can then get a meaningful
   backtrace from your debugger if you break on the gdk_x_error() function.)
Trace/breakpoint trap

殆ど毎回のように起動直後に落ちる。やっぱり不安定だなぁ。2回目からは大丈夫なのだが。変更したoption が悪影響しているのか。別の接続ソフトも探してみる。

結果

qemu (kvm) で virtio を使用してみた。

  • block device (virtual disk image) は体感できる程速くなった。
  • network は host 側の bridge に tap で接続できた。TCP/UDP/ICMP も双方向に通り、ssh で Host -> Guest へ接続できた。

調べる事:

  • 最近の「新しい」やり方で network、bridge を設定する。起動時から有効に出来るようにする。
  • 最近の daemon 起動方法について調べる。
  • spycy が落ちる件を調べる。代替があれば試してみる。

libvirtvirt-manager を使うと楽なのは分かっているが、基礎からやらないと身につかない性分だし、裏で動いている事を理解しないで進めるのは気持ち悪いので、今回は qemu (kvm) の command line から直接 option を設定してみた。もう少し試してから virt-manager を使ってみる。