labunix's blog

labunixのラボUnix

debian stretchにKVMを導入する。

■debian stretchにKVMを導入する。
 初めてなら仮想マシンの作成時の画面キャプチャは下記を参照した方が良い。

 Debian 9: 仮想化のKVMをインストールする
 https://www.hiroom2.com/2017/06/26/debian-9-kvm%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B/

$ lsb_release -d
Description:	Debian GNU/Linux 9.4 (stretch)

■CPUフラグの確認
 Intel Core i7の4コア/8スレッドについて、
 vmx(Interl)/svm(AMD)フラグ(Hardware Virtualization;ハードウェア仮想化)と、
 ept(Intel)/npt(AMD)フラグ(Extended Page Tables;拡張ページテーブル)、
 それにKVMで使用する不変TSCの周波数を持つCPUフラグも、
 8スレッド分の仮想化フラグが見つかる。

 ネストに必要なvmx+eptフラグ、
 節電ポリシーに従うために周波数を変更してもタイムスタンプカウンター(TSC)が不変であるconstant_tscフラグがあるので、
 特に心配せずにKVMの機能を使用することが出来る環境。

$ sudo dmidecode -t processor | awk '/Version|Flag|[Vv]irtual|Count/'
	Flags:
		VME (Virtual mode extension)
	Version: Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz     
	Core Count: 4
	Thread Count: 8

$ grep flags /proc/cpuinfo | sed s/" "/"\n"/g | awk '/vmx|svm|[en]pt|constant_tsc/{a[$1]+=1}END{for(n in a){print n,a[n]}}'
vmx 8
ept 8
constant_tsc 8

■KVM関連パッケージをインストール
 intelなので、amd版と読み込まれるモジュールが異なる。

$ sudo apt install -y qemu-kvm libvirt0 virt-manager bridge-utils
$ sudo shutdown -r now && exit

$ lsmod | grep kvm
kvm_intel             192512  0
kvm                   593920  1 kvm_intel
irqbypass              16384  1 kvm

■ネットワーク仮想化のオーバヘッド対応のためにvhost-netを有効化

$ sudo modprobe vhost_net 
$ lsmod | grep vhost
vhost_net              20480  0
vhost                  45056  1 vhost_net
macvtap                24576  1 vhost_net
tun                    28672  2 vhost_net

$ echo vhost_net | sudo tee -a /etc/modules >/dev/null

■既にブリッジ構成なので特に何もしない。

$ ip a show dev br0 | head -1
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000

■virshコマンド実行のためにグループ権限を追加

$  sudo gpasswd libvirt -a labunix
$ id | awk 'BEGIN{RS=","}/libvirt/{print $1}'
127(libvirt)
64055(libvirt-qemu)

■netinstallのISOイメージファイルを配置

$ wget http://ftp.jaist.ac.jp/debian-cd/current/amd64/iso-cd/debian-9.4.0-amd64-netinst.iso
$ sudo mkdir /var/lib/libvirt/iso
$ sudo mv debian-9.4.0-amd64-netinst.iso  /var/lib/libvirt/iso/
$ sudo chown -R libvirt-qemu:libvirt /var/lib/libvirt/iso/
$ ls -l /var/lib/libvirt/iso/
合計 297988
-rw-r--r-- 1 libvirt-qemu libvirt 305135616  310 20:56 debian-9.4.0-amd64-netinst.iso

■xrdpでGUIに接続し、mate-terminalからvirt-managerを起動して、
 普段どおりにゲストOSをインストール。
 ※GUIでは無い点と、インストール中は英語配列のままとなる点に注意。

$ virt-manager

■xmlファイルを読んで関連を探す。
 選択項目をピックアップすると、ゲストOSはデフォルトをそのままなので、
 1vcpu、1GBメモリ、ホストのブリッジからNWを構成し、ディスクはrawなので20GB。

$ sudo awk '/vcpu|type arch|memory|device=|source bridge/' /etc/libvirt/qemu/kvm-stretch.xml 
  <memory unit='KiB'>1048576</memory>
  <vcpu placement='static'>1</vcpu>
    <type arch='x86_64' machine='pc-i440fx-2.8'>hvm</type>
    <disk type='file' device='disk'>
    <disk type='file' device='cdrom'>
      <source bridge='br0'/>

$ ls -lh /var/lib/libvirt/images/kvm-stretch.img
-rw------- 1 libvirt-qemu libvirt-qemu 21G  51 20:44 /var/lib/libvirt/images/kvm-stretch.img

■ゲストOSのその他の構成ファイルは以下。

$ sudo find /var/lib/libvirt/ /etc/libvirt -type f
/var/lib/libvirt/images/kvm-stretch.img
/var/lib/libvirt/images/debian-9.3.0-amd64-netinst.iso
/var/lib/libvirt/qemu/domain-1-kvm-stretch/master-key.aes
/var/lib/libvirt/iso/debian-9.4.0-amd64-netinst.iso
/etc/libvirt/virtlogd.conf
/etc/libvirt/virtlockd.conf
/etc/libvirt/qemu-lockd.conf
/etc/libvirt/libvirtd.conf
/etc/libvirt/libxl-lockd.conf
/etc/libvirt/qemu-sanlock.conf
/etc/libvirt/lxc.conf
/etc/libvirt/qemu/networks/default.xml
/etc/libvirt/qemu/kvm-stretch.xml
/etc/libvirt/storage/images.xml
/etc/libvirt/storage/labunix.xml
/etc/libvirt/qemu.conf
/etc/libvirt/libxl.conf
/etc/libvirt/nwfilter/no-mac-spoofing.xml
/etc/libvirt/nwfilter/allow-arp.xml
/etc/libvirt/nwfilter/qemu-announce-self-rarp.xml
/etc/libvirt/nwfilter/no-ip-multicast.xml
/etc/libvirt/nwfilter/no-ip-spoofing.xml
/etc/libvirt/nwfilter/no-other-l2-traffic.xml
/etc/libvirt/nwfilter/qemu-announce-self.xml
/etc/libvirt/nwfilter/no-mac-broadcast.xml
/etc/libvirt/nwfilter/clean-traffic.xml
/etc/libvirt/nwfilter/no-arp-ip-spoofing.xml
/etc/libvirt/nwfilter/no-arp-spoofing.xml
/etc/libvirt/nwfilter/allow-ipv4.xml
/etc/libvirt/nwfilter/allow-dhcp.xml
/etc/libvirt/nwfilter/allow-dhcp-server.xml
/etc/libvirt/nwfilter/allow-incoming-ipv4.xml
/etc/libvirt/nwfilter/no-other-rarp-traffic.xml
/etc/libvirt/nwfilter/no-arp-mac-spoofing.xml
/etc/libvirt/libvirt.conf
/etc/libvirt/virt-login-shell.conf

■ゲストOSはホストOS同様に以下を選択してインストール。
 FWオブジェクトを追加する必要がある以外、
 プロキシ環境でもホストのブリッジ構成を使用しているので特に何も困らない。
 さっさと進めたい時ならMATEは外せば良い。

$ sudo tasksel --list-tasks | grep ^i
i desktop	Debian デスクトップ環境
i mate-desktop	MATE
i ssh-server	SSH サーバ

■インストールで待っている間にvirshで管理できていることを確認

$ sudo virsh list --all
 Id    Name                           State
----------------------------------------------------
 1     kvm-stretch                    running

$ virsh -c qemu:///system list
 Id    Name                           State
----------------------------------------------------
 1     kvm-stretch                    running

■root同様に「qemu:///system」を省略出来るようにする。

$ export LIBVIRT_DEFAULT_URI="qemu:///system"
$ virsh list
 Id    Name                           State
----------------------------------------------------
 1     kvm-stretch                    running

■ログインしたユーザに適用されるように設定

$ echo '#!/bin/bash' | sudo tee /etc/profile.d/kvm.sh > /dev/null
$ echo 'export LIBVIRT_DEFAULT_URI="qemu:///system"' | sudo tee -a /etc/profile.d/kvm.sh > /dev/null

$ grep uri_default /etc/libvirt/libvirt.conf
# (@uri_default also prevents probing of the hypervisor driver).
#uri_default = "qemu:///system"

■virshコマンド自体がlibvirtグループの権限をチェックするので、
 グループに所属していないユーザは「Permission denied」となる。
 デフォルトではrootユーザ権限なので、下記のコメントアウトを外す。

$ grep "_r[ow]_\|_group" /etc/libvirt/libvirtd.conf
#unix_sock_group = "libvirt"
#unix_sock_ro_perms = "0777"
#unix_sock_rw_perms = "0770"
# If the unix_sock_rw_perms are changed you may wish to enable

■一応、上記のコメントアウトについて条件がいまいち不明ですが、
 デフォルトではroot、PolicyKitが有効でソケットにsetgidが使えるなら...とあるし、
 debianとして権限は0777に変更したとかあるし、実際そうなっているので...
 よく分からないけど、検証する時間のある人向けのようです。

$ apt-file search bin/libvirtd
libvirt-daemon: /usr/sbin/libvirtd

$ dpkg -L libvirt-daemon | awk '/doc/&&/gz/' | xargs zgrep -A 5 '\/etc\/libvirt\/libvirtd.conf' | tail -6
/usr/share/doc/libvirt-daemon/changelog.gz:	/etc/libvirt/libvirtd.conf prevents system libvirtd from dumping core on
/usr/share/doc/libvirt-daemon/changelog.gz:	crash. This is because we used setgid(unix_sock_group) before binding to
/usr/share/doc/libvirt-daemon/changelog.gz:	/var/run/libvirt/libvirt-sock* and setgid() back to original group.
/usr/share/doc/libvirt-daemon/changelog.gz:	However, if a process changes its effective or filesystem group ID, it
/usr/share/doc/libvirt-daemon/changelog.gz:	will be forbidden from leaving core dumps unless fs.suid_dumpable sysctl
/usr/share/doc/libvirt-daemon/changelog.gz:	is set to something else then 0 (and it is 0 by default).

$ ls -l /var/run/libvirt/libvirt-sock*
srwxrwxrwx 1 root root 0  51 16:02 /var/run/libvirt/libvirt-sock
srwxrwxrwx 1 root root 0  51 16:02 /var/run/libvirt/libvirt-sock-ro

$ stat /var/run/libvirt/libvirt-sock* | awk '/File|Access.*id/'
  File: /var/run/libvirt/libvirt-sock
Access: (0777/srwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
  File: /var/run/libvirt/libvirt-sock-ro
Access: (0777/srwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)

$ sudo systemctl status libvirtd.service | awk '/PID/{print "ps u "$3}' | sh
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root       976  0.0  0.2 1416928 42128 ?       Ssl  16:02   0:04 /usr/sbin/libvirtd

$ grep -A 5 "only root" /etc/libvirt/libvirtd.conf
# Default allows only root. If PolicyKit is enabled on the socket,
# the default will change to allow everyone (eg, 0777)
#
# If not using PolicyKit and setting group ownership for access
# control, then you may want to relax this too.
#unix_sock_rw_perms = "0770"

$ dpkg -L libvirt-daemon | awk '/doc/&&/gz/' | zgrep -B 3 -A 2 "mode 077[07]\|077[07].*mode" `xargs` | grep -v '@'
/usr/share/doc/libvirt-daemon/changelog.Debian.gz:  * [da11813] Use polkit instead of socket permissions.  As before membership
/usr/share/doc/libvirt-daemon/changelog.Debian.gz:    in the libvirt group gives r/w access to all VMs.
/usr/share/doc/libvirt-daemon/changelog.Debian.gz:  * [98cdfca] Allow for libvirt's socket activation. Now that we're using
/usr/share/doc/libvirt-daemon/changelog.Debian.gz:    polkit by default having the rw socket mode 0777 is fine.
/usr/share/doc/libvirt-daemon/changelog.Debian.gz:
/usr/share/doc/libvirt-daemon/changelog.gz:
/usr/share/doc/libvirt-daemon/changelog.gz:	   /hugepageMount/libvirt/qemu
/usr/share/doc/libvirt-daemon/changelog.gz:
/usr/share/doc/libvirt-daemon/changelog.gz:	Our only option there would be to set 0777 mode on the qemu dir
/usr/share/doc/libvirt-daemon/changelog.gz:	which is totally unsafe. Therefore, we can create dir on
/usr/share/doc/libvirt-daemon/changelog.gz:	per-domain basis, i.e.:

■ゲストOSインストール後のSSH接続確認
 ディスクが「/dev/vda」扱いなので、物理環境とは異なるが、
 1コア(仮想化フラグなし)、1GBメモリ、20GBディスクが認識されていることが分かる。
 不変TSCの周波数を持つCPUのフラグのみ。

# dmidecode -t processor | awk '/Version|Flag|[Vv]irtual|Count/'
	Version: pc-i440fx-2.8
	Core Count: 1
	Thread Count: 1

# grep flags /proc/cpuinfo | sed s/" "/"\n"/g | awk '/vmx|svm|[en]pt|constant_tsc/{a[$1]+=1}END{for(n in a){print n,a[n]}}'
constant_tsc 1

# free -m
              total        used        free      shared  buff/cache   available
Mem:            996         102         725           6         168         755
Swap:          1021           0        1021

# ip a show dev ens3 | head -1
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

# dmesg | grep vda
[    1.204327]  vda: vda1 vda2 < vda5 >
[    1.440855] EXT4-fs (vda1): mounted filesystem with ordered data mode. Opts: (null)
[    1.591729] EXT4-fs (vda1): re-mounted. Opts: errors=remount-ro
[    1.830306] Adding 1046524k swap on /dev/vda5.  Priority:-1 extents:1 across:1046524k FS

# fdisk -l
Disk /dev/vda: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2999f25c

Device     Boot    Start      End  Sectors  Size Id Type
/dev/vda1  *        2048 39845887 39843840   19G 83 Linux
/dev/vda2       39847934 41940991  2093058 1022M  5 Extended
/dev/vda5       39847936 41940991  2093056 1022M 82 Linux swap / Solaris

■ホストが起動したときに自動起動するように設定

$ virsh autostart kvm-stretch
Domain kvm-stretch marked as autostarted

■自動起動を解除するには。。。

$ virsh autostart --disable kvm-stretch
Domain kvm-stretch unmarked as autostarted