2016年2月28日日曜日

QEMU/KVM, libvirtのインストールと設定

QEMU/KVMとlibvirtのインストール
仮想マシンインストール関連記事
仮想環境の関連記事は、「Linuxマシン上でWindowsを使う」のページにまとてあります。

はじめに
Linux環境にQEMU/KVMをインストールして仮想マシンを使えるようにしたので、方法をまとめておく。QEMU/KVMのGUIフロントエンドとしては、virt-managerを使用する。QEMU/KVM環境は「Guest Support Status - KVM」のページに書いてあるように、非常に多くのOSをサポートしている。

インストールと設定に移る前に、仮想マシンを実行する上で必要となる機能ついてまとめておく。
  • KVM: Kernel-based Virtual Machineの略。Linuxカーネルに搭載されている、仮想化を支援する機能(モジュール)。このモジュールは、バージョン2.6.20以降のLinuxカーネルに実装されている。KVMはモジュールでしかないので、KVM単体では機能しない。KVMの機能を実際使うためには、QEMUのようなエミュレータが必要になる。
  • QEMU: プロセッサー、及びネットワークデバイスやビデオデバイスなどのサブシステムをエミュレートするエミュレータ。
  • libvirt: 仮想化されたストレージや、ネットワークデバイスなどの管理、制御を担うライブラリ(API)。Xen, VirtualBox, VMwareなどをサポートしている。
  • virt-manager: 仮想マシンを管理するためのGUIフロントエンド。Xen、KVM、QEMUなどの仮想化システムに対応している。Windowsなどの、GUIモードでしかインストールできないOSで仮想マシンを作るには、必須となる。

これらの機能を構成は、以下の図のようになる。(Inside Linux KVM(3):libvirt探訪(基礎編) - @ITより)



環境
今回、QEMU/KVMのインストールと設定を行った環境は以下の通り。ディストリビューションの違いによって、パッケージ名の違いなど多少があるかもしれない。
  • ホストOS: Arch Linux x86_64
  • Kernel: Linux 4.4.1-2
  • CPU: Intel i7 3770S
  • MB: ASUS P8Z77-M PRO (BIOS Version: 2105)

CPUのサポート確認とBIOSの設定
CPUの仮想化支援の確認
KVMを使うためには、CPUが仮想化に対応している必要がある。Intel製であれば、Intel VT-x (Virtualization Technology)、AMD製であればAMD-V (AMD Virtualization) と呼ばれる機能が必要である。確認は端末からできる。次のコマンドで何か表示されれば、対応していることになる。
$ grep -E "(vmx|svm|0xc0f)" --color=always /proc/cpuinfo

flags  : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush 
dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts 
rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl 
vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes 
xsave avx f16c rdrand lahf_lm ida arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid 
fsgsbase smep erms xsaveopt
...

またメーカーのウェブページからも確認できる。インテル バーチャライゼーション・テクノロジー リストまたは、AMD 公式ページから確認する。

BIOSの設定
CPUがIntel VT-xまたは、AMD-Vに対応していたとしても、BIOSの設定でこの機能が無効にされていることがある。ASUS P8Z77-M PROの場合、買ったときから設定を変更した覚えはないが、確認したら無効になっていた。以下の手順でIntel VT-xを有効にした。それぞれのマザーボードで項目の名称等が変わっているかもしれないが、取説等を見れば設定箇所が載っている。AMD-VはBIOSで無効にできないので、常に有効になっているらしい。

パソコン起動時に、Delキーを押してBIOS(UEFI BIOS)画面を起動する。 Advanced Modeをクリックして、Advanced Modeに入る。



Advancedのタブから「CPU Configuration」をクリック。


Intel Virtualization Technologyの項目がDisableになっているので、クリックしてEnableに変更する。


Exitをクリックして、さらにSave Changes & Resetを選択する。


これで、CPUの仮想化支援機能が有効になる。

カーネールモジュールの確認とロード
次に、KVMモジュールが有効になっているか確認する。yまたはmが設定されていれば、有効になっている。もし有効になっていなければ、有効にしたうえでカーネルをビルドする。
$ zgrep CONFIG_KVM /proc/config.gz

CONFIG_KVM_GUEST=y
# CONFIG_KVM_DEBUG_FS is not set
CONFIG_KVM_APIC_ARCHITECTURE=y
CONFIG_KVM_MMIO=y
CONFIG_KVM_ASYNC_PF=y
CONFIG_KVM_VFIO=y
CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
CONFIG_KVM_COMPAT=y
CONFIG_KVM=m
CONFIG_KVM_INTEL=m
CONFIG_KVM_AMD=m
CONFIG_KVM_MMU_AUDIT=y
CONFIG_KVM_DEVICE_ASSIGNMENT=y

VIRTIOモジュールが有効になっているかも確認する。
$ zgrep CONFIG_VIRTIO /proc/config.gz

CONFIG_VIRTIO_BLK=m
CONFIG_VIRTIO_NET=m
CONFIG_VIRTIO_CONSOLE=m
CONFIG_VIRTIO=m
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_PCI_LEGACY=y
CONFIG_VIRTIO_BALLOON=m
CONFIG_VIRTIO_INPUT=m
CONFIG_VIRTIO_MMIO=m
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y

kvm, kvm_intel(またはkvm_amd)モジュールをが読み込まれているか確認する。kvm, kvm_intelモジュールが読み込まれていれば、以下のようにkvm, kvm_intelモジュールがリストアップされる。デフォルトで、自動でロードされるようになっている。
$ lsmod | grep -E "(kvm|kvm_intel)"

kvm_intel             167936  0
kvm                   462848  1 kvm_intel
irqbypass              16384  1 kvm

読み込まれていなかったら、ロードする。
# modprobe kvm_intel

もし自動でロードされるよう設定されていない場合は、/etc/modules-load.d/kvm_intel.confのようなファイルを作って、以下のように記載する。
# vim /etc/modules-load.d/kvm_intel.conf

#起動時にkvm_intelをロード
kvm_intel

ゲストOSでネットワークデバイスや、記憶デバイスなどを高速で使用したい場合、ホストマシンでvirtioモジュールをロードする。ただし、virtioモジュールを使うためには、ホストマシンでvirtioモジュールをロードしたうえで、さらに、ゲストOSでvirtioドライバをインストールしなければならない。virtioモジュールを使わなくても、デバイス速度はある程度出ていたので、今回はvirtioモジュールは使用しなかった。

もしネットワークデバイスのvirtioを使う場合はvirtio、virtio_net、virtio_pci モジュール、ブロックデバイスのvirtioを使用する場合はvirtio、virtio_ring、virtio_blk、virtio_pciモジュールをロードする必要がある。「第2回 Linux KVMで動かすWindows :本気で使いたいユーザのためのLinux KVM活用法」に、ゲストOSをWindowsとして、ゲストドライバのインストール方法が説明してある。

QEMU, libvirtパッケージのインストールとネットワーク設定
QEMU, libvirtのインストール
準備ができたら、必要なパッケージをインストールする。まず、QEMU, libvirtをインストールする。qemuというパッケージ名はディストリビューションによっては、qemu-kvmとなっていると思う。Arch Linuxでもかつては、qemu-kvmという名前のパッケージがあったが、qemuで置き換えられている。
# pacman -S qemu libvirt

次にネットワーク関連のパッケージをインストールする。ざっくり言うと、ゲストを仮想サーバーとして使わないなら、ケース 1、ゲストを仮想サーバーとして使うならケース 2の設定に移る。

ケース1 | ebtables, dnsmasqのインストール(デフォルトのNAT/DHCP接続)
libvirtでデフォルトに設定されているNAT/DHCP接続を利用する場合は、ebtables, dnsmasqをインストールする。ゲストを仮想サーバーとして使用しない場合は、ゲストをプライベート・ネットワークに置けるため、デフォルトで立ち上がる接続を利用する方がいいと思う。ゲストOSの用途が仮想サーバーであり、NAT/DHCP接続を利用しない場合は、代わりに次で説明するbridge-utilsをインストールして手動でブリッジ接続を設定する。

dnsmasqはゲストOS用のDHCPを提供する。ebtablesはNATブリッジ用のフィルター。libvirtのデーモンを起動すると、defaultという名前のNATブリッジが自動で作成され、ゲストが外部ネットワークに接続できるようになるため、ebtables, dnsmasqをインストールしておけば特にネットワークの設定は必要ない(デーモンの起動は後で行う)。この後、ゲストOSのインストールも解説するが、NAT/DHCP接続を利用する方法で解説する。
# pacman -S ebtables dnsmasq

NAT接続によるネットワーク構成「第3回 Debian GNU/Linux 6.0で試すKVM:エンジニアなら知っておきたい仮想マシンのしくみ」より)



ケース2 | bridge-utilsのインストール(NAT/DHCPを介さない場合)
もし、ゲストOSを物理NICと直接ブリッジ接続したい場合は、bridge-utilsをインストールし、ネットワーク接続の設定をする必要がある。ゲストOSを仮想サーバーとして使いたい場合は、この構成のほうが便利になる。直接ブリッジ接続することで、ホストOS(NAT)を介さずにゲストOSを直接外部ネットワークに繋ことができるようになるためである。直接ブリッジ接続する方法は、第5回 Linux KVMを使ってみよう:実践!仮想化ソフトウェア 2009などを参照する。

NATを介さないネットワーク構成「第3回 Debian GNU/Linux 6.0で試すKVM:エンジニアなら知っておきたい仮想マシンのしくみ」より)



libvirtdのデフォルトのネットワーク構成
libvirtdにデフォルトで設定されているNAT/DHCPのネットワーク構成を確認しておく。このデフォルトの構成では、LinuxカーネールがサポートするTAP機能、iptablesによるNAT、dnsmasqのDHCP機能を利用する。以下の図にある「② IPマスカレード」のイメージになる。(「第3回 KVMのネットワーク構成:KVMで始めるプライベート・クラウドへの第一歩」より)



libvirtdのデフォルトのネットワーク設定ファイルは、/etc/libvirt/qemu/networks/default.xmlにある。/etc/libvirt/qemu/networks/autostart/default.xmlにシンボリックリンクが作られており、自動起動するようになっている。
$ ls -l /etc/libvirt/qemu/networks/autostart/default.xml

lrwxrwxrwx 1 root root 14  1月 29 17:32 /etc/libvirt/qemu/networks/autostart/default.xml -> ../default.xml

設定ファイルの編集は直接せず、virshから行うよう推奨されている。詳しい情報はlibvirt: Wiki: Networkingに載っている。デフォルトの設定を確認する。
#  virsh net-edit default

<network>
  <name>default</name>
  <uuid>5908833a-9de8-4739-8a78-bf58b8066e9b</uuid>
  <forward mode="nat">
  <bridge delay="0" name="virbr0" stp="on">
  <mac address="52:54:00:5d:ab:d8">
  <ip address="192.168.122.1" netmask="255.255.255.0">
    <dhcp>
      <range end="192.168.122.254" start="192.168.122.2">
    </range></dhcp>
  </ip>
</mac></bridge></forward></network>

libvirtdによって作られたデバイスを確認しておく。ゲストOSがデフォルトゲートウェイとして使うインターフェイス(virbr0, 192.168.122.1/24)ができていることがわかる。DHCPサーバーのアドレスも192.168.122.1/24となる。
$ ip a

1: lo: <loopback> mtu 65536 qdisc noqueue state UNKNOWN group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp3s0: <broadcast> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether c8:60:00:ce:62:31 brd ff:ff:ff:ff:ff:ff
    inet 10.10.1.18/24 brd 10.10.1.255 scope global enp3s0
       valid_lft forever preferred_lft forever
    inet6 fe80::c327:cedc:ef7:8707/64 scope link 
       valid_lft forever preferred_lft forever
3: virbr0: <no-carrier> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:5d:ab:d8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <broadcast> mtu 1500 qdisc noqueue master virbr0 state DOWN group default qlen 500
    link/ether 52:54:00:5d:ab:d8 brd ff:ff:ff:ff:ff:ff
</broadcast></no-carrier></broadcast></loopback>

iptablesによりNATの設定がされているか確認する。
# iptables --list

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     udp  --  anywhere             anywhere             udp dpt:domain
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:domain
ACCEPT     udp  --  anywhere             anywhere             udp dpt:bootps
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:bootps

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             192.168.122.0/24     ctstate RELATED,ESTABLISHED
ACCEPT     all  --  192.168.122.0/24     anywhere            
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     udp  --  anywhere             anywhere             udp dpt:bootpc

QEMU, libvirtのパーミッション設定
デフォルトでは、QEMU, libvirtはroot権限で操作するように設定されている。ここでは、一般ユーザーから操作できるようにパーミッションの設定を行う。

パーミッション関連の説明は、「openSUSE 13.1: 第6章 接続と権限」に詳しく記載されている。以下の設定については、 を参考にした。

QEMUの設定
一般ユーザーが「システム接続」できるように設定を変更する。

/etc/libvirt/qemu.confを、以下のように3行編集する。
# vim /etc/libvirt/qemu.conf

...
# The user for QEMU processes run by the system instance. It can be
# specified as a user name or as a user id. The qemu driver will try to
# parse this value first as a name and then, if the name doesn't exist,
# as a user id.
#
# Since a sequence of digits is a valid user name, a leading plus sign
# can be used to ensure that a user id will not be interpreted as a user
# name.
#
# Some examples of valid values are:
#
#       user = "qemu"   # A user named "qemu"
#       user = "+0"     # Super user (uid=0)
#       user = "100"    # A user named "100" or a user with uid=100
#
user = "ユーザー名" ←「ユーザー名」は普段使う一般ユーザーのユーザー名に変える。

# The group for QEMU processes run by the system instance. It can be
# specified in a similar way to user.
group="libvirt" ←グループをlibvirtに変える。

# Whether libvirt should dynamically change file ownership
# to match the configured user/group above. Defaults to 1.
# Set to 0 to disable file ownership changes.
dynamic_ownership = 1 ←コメントアウトを解除。
...

さらに、kvmグループに一般ユーザーを追加する。「ユーザー名」は普段使う一般ユーザーのユーザー名に変える。libvirtグループへの追加は、次のlibvirtの設定とともに行う。
# gpasswd -a ユーザー名 kvm

libvirtの設定
デフォルトでlibvirtは、認証システムとしてPolicyKitを採用している。ここでは、PolicyKitによる認証を使わず、ファイルのパーミッションベースで管理する方法を採る。

まず、libvirt グループのユーザーが仮想マシンを管理できるように、ファイルベースのパーミッションを定義する。/etc/libvirt/libvirtd.confの以下の行のコメントアウトを解除する。
# vim /etc/libvirt/libvirtd.conf

...
unix_sock_group = "libvirt"
...
unix_sock_ro_perms = "0777"  # set to 0770 to deny non-group libvirt users
...
unix_sock_rw_perms = "0770"
...
auth_unix_ro = "none"
...
auth_unix_rw = "none"
...
...

次に、一般ユーザーとして使用しているユーザーを、libvirtグループに追加する。「ユーザー名」は普段使う一般ユーザーのユーザー名に変える。
# gpasswd -a ユーザー名 libvirt

libvirtdデーモンを起動する。
# systemctl start libvirtd.service
# systemctl enable libvirtd.service

設定を反映させるため、PCの再起動を行う。

GUIフロントエンドのインストール
GUIフロントエンドvirt-managerのインストール
今回は、GUIフロントエンドとして一般的に使われているvirt-managerを使用する。QEMU/KVMのフロントエンドとしては、virt-managerの他、GNOME Boxesやqemu-launcherなどがある。GNOME BoxesからWindowsをインストールしようとしたが、CDの形式がサポートされていないとメッセージが出てインストールできなかった。GNOME Boxesは操作が簡単になっているため、非Windows OSをゲストOSとするのであれば便利なツールだと思う。

pacman からvirt-managerをインストールする。
# pacman -S virt-manager

virt-managerを起動すると、以下のようなウィンドウが開く。


ここまでで、QEMU/KVM環境の設定は終了。設定を有効にするため、PCを再起動する。この後、virt-managerを使い仮想マシンを作成し、作成した仮想マシンにゲストOSをインストールする。


参考:
[1]KVM - ArchWiki
[2]QEMU - ArchWiki
[3]libvirt - ArchWiki
[4]第3回 Debian GNU/Linux 6.0で試すKVM:エンジニアなら知っておきたい仮想マシンのしくみ

スポンサーリンク

スポンサーリンク


関連コンテンツ


この記事をシェアする

0 件のコメント:

コメントを投稿