新しい PC を買って KVM をインストールしたので手順をまとめてみました。
#[1. Linux のインストール](#1-Linux のインストール)
まずは Linux をインストールします。今回は Ubuntu 20.04 をインストールしました。
自分の使っている PC で仮想化をサポートしているか確認します。結果が 0 などとなる場合は BIOS の CPU の設定を確認してください。
$ egrep -c '(vmx|svm)' /proc/cpuinfo
12
これはお好みですがデフォルトのエディタを vi にして sudo をパスワードなしで実行できるようにします。
$ sudo update-alternatives --config editor
$ sudo visudo
[ユーザー名] ALL=(ALL:ALL) NOPASSWD:ALL
上記の行を以下の行より後ろに追加します。[ユーザー名] は自分が使っているユーザー名に変更します。
%sudo ALL=(ALL:ALL) ALL
参考: Set Vim as your default editor for Unix
#[2. KVM のインストール](#2-KVM のインストール)
KVM ホストに VM に関連するパッケージをインストールします。
$ sudo apt update
$ sudo apt install -y qemu qemu-kvm libvirt-daemon libvirt-clients bridge-utils virt-manager
$ sudo reboot
次に自分が使用しているユーザーを libvirt と kvm グループに追加します。既に追加されている場合は必要ありません。
$ sudo adduser `id -un` libvirt
Adding user '<username>' to group 'libvirt' ...
$ sudo adduser `id -un` kvm
Adding user '<username>' to group 'kvm' ...
virt-top や virt-df などのツールもインストールしても良いかもしれません。Python や jq なども必要あであればインストールします。
参照: KVM/Installation
libvirtd が active か、QEMU 上でもハードウェア仮想化が有効かを確認します。
$ sudo systemctl is-active libvirtd
active
$ virt-host-validate
QEMU: Checking for hardware virtualization : PASS
QEMU: Checking if device /dev/kvm exists : PASS
<snip>
QEMU: Checking for secure guest support : WARN (AMD Secure Encrypted Virtualization appears to be disabled in kernel. Add kvm_amd.sev=1 to the kernel cmdline arguments)
参照: KVM: Bare metal virtualization on Ubuntu with KVM
AMD Secure Encrypted Virtualization は仮想マシンで使用しているメモリ暗号化をハードウェアでサポートする技術のようですが KVM ホストを共有する使い方はしないのでここでは一旦無視します。
参照: AMD Secure Encrypted Virtualization (SEV)
例えば qcow2 イメージ用にシステムディスクとは別のディスクを使用する場合はディスクのフォーマットなどを行います。まずパーティション作成で使用する parted はここら辺が参考になりました。
参照: Parted
KVM に swap が必要かという話。あっても良いようです。
ファイルシステムの比較をここで軽くしてみました。ここら辺は好みだと思います。
以下では KVM でのストレージプールの設定を変更しデフォルトで使用するディレクトリを変更しています。
現在の pool のストレージプールのリストを表示します。
$ virsh pool-list
Name State Autostart
-------------------------------
default active yes
default を削除します。
$ virsh pool-destroy default
Pool default destroyed
~$ virsh pool-undefine default
Pool default has been undefined
$ virsh pool-list
Name State Autostart
------------------------------
新しく default を作成します。ここでは新しいストレージプールのディレクトリを /datasotore1/images としています。
$ virsh pool-define-as --name default --type dir --target /datastore1/images
Pool default defined
$ virsh pool-autostart default
Pool default marked as autostarted
$ virsh pool-start default
Pool default started
$ virsh pool-list
Name State Autostart
-------------------------------
default active yes
参照: デフォルトのストレージプールをlibvirtから変更するにはどうすればよいですか?
対象のディレクトリのパーミッションは以下の通りとなっていました。
drwxrwxr-x 2 libvirt-qemu kvm 247 Jan 11 18:10 images
この作業はもしかすると virsh pool-edit --pool default として既存の設定を変更したほうが早いかもしれません。
デフォルトでは KVM インストール時に virbr0 と言う仮想ブリッジが作成されます。
$ ip addr show virbr0
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:5e:9e:a2 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
$ brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.5254005e9ea2 yes virbr0-nic
$ virsh net-list
Name State Autostart Persistent
--------------------------------------------
default active yes yes
このブリッジを NAT として利用して仮想マシンは外のネットワークにアクセスできます。使わない場合は消してしまっても良いと思います。もちろん消さなくても良いと思います。消すならこのあたり。
$ virsh net-destroy default
$ virsh net-undefine default
参照: https://www.cyberciti.biz/faq/linux-kvm-disable-virbr0-nat-interface/
こことか見ると以下の sysctl のパラメータを 0 にするように書かれています。
net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-arptables=0
これは恐らく br_netfilter というモジュールがロードされている場合の話。Ubuntu 20.04 ではデフォルトではロードされて無かったので必要ないと思います。多分w
仮想マシンに割り当てた IP アドレス宛に外から通信したい場合は Linux 上でブリッジを作成します。Ubuntu 20.04 で netplan を使用する場合はこんな感じ。
$ cat /etc/netplan/60-eno1-config.yaml
network:
version: 2
ethernets:
eno1:
dhcp4: false
dhcp6: false
bridges:
br0:
interfaces:
- eno1
dhcp4: false
dhcp6: false
addresses:
- 10.0.0.249/24
gateway4: 10.0.0.1
nameservers:
addresses:
- 1.1.1.1
- 1.0.0.1
parameters:
forward-delay: 0
stp: false
optional: true
上記を明示的に KVM に登録することもできるが KVM ホストでブリッジを作った時点で KVM ゲストは見えるようになります。STP をどうするかは文章に寄って違ったりしますが多いのは無効。有効でも動かない落ちうことはないみたいです。
参考: CentOSのKVMで使う仮想ネットワークについて調べてみた
CentOS ではデフォルトで使用されているためと思いますが、Network Manager を使った例も沢山あります。ここら辺もお好みで。
作成したブリッジは brctl コマンドで確認することができます。
$ brctl show
bridge name bridge id STP enabled interfaces
br0 8000.a0369fa9f098 no enp4s0f0
上記で作成したブリッジを KVM ゲストに割り当てて IP アドレスを割り振れば該当の IP に対して KVM 環境の外からもアクセスすることができます。
KVM の内部で使用するネットワークを作成します。virt-manager でも作れますがここでは xml ファイルから作成してみます。
まずは xml ファイルを作成します。恐らく以下が一番シンプルな記述だと思います。ここで IP アドレスや DHCP などの設定もできます。
$ cat virbr1.xml
<network>
<name>virbr1</name>
<bridge name='virbr1' stp='on' delay='0' />
</network>
参照: KVM (Kernel-based Virtual Machine) による仮想環境の構築手順(KVMのインストールと仮想ネットワーク作成手順)
以下のコマンドで KVM にブリッジを作成し起動時に自動で構成されるようにします。
$ virsh net-define ./virbr1.xml
Network virbr1 defined from ./virbr1.xml
$ virsh net-autostart virbr1
Network virbr1 marked as autostarted
$ virsh net-start virbr1
Network virbr1 started
正常に作成されたかは以下のコマンドで確認ができます。
$ brctl show
bridge name bridge id STP enabled interfaces
virbr1 8000.525400a99a82 yes virbr1-nic
$ virsh net-list
Name State Autostart Persistent
--------------------------------------------
default active yes yes
virbr1 active yes yes
実際の設定ファイルはここにあります。uuid や mac address は自動で付与してくれます。一度登録したものは virsh net-edit コマンドで編集することができます。
$ sudo cat /etc/libvirt/qemu/networks/virbr1.xml
<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
virsh net-edit virbr1
or other application using the libvirt API.
-->
<network>
<name>virbr1</name>
<uuid>379d3199-365e-4c99-b331-77d50ed7b2ac</uuid>
<bridge name='virbr1' stp='on' delay='0'/>
<mac address='52:54:00:a9:9a:82'/>
</network>
参照: net-define
#[7. virsh をリモートで実行する](#7-virsh をリモートで実行する)
KVM ホストに直接 ssh などでログインするのはあまり好ましくない場合もあります。virsh や virt-manager で KVM の設定をしますがリモートでの実行も可能です。
virsh をリモートから実行するにはまずクライアントに libvirt-clients をインストールします。
$ sudo apt install libvirt-clients
次に以下のようなコマンドを実行します。
$ virsh -c qemu+ssh://test@10.0.0.250/system list
Id Name State
----------------------
1 c20h running
上記の場合は ssh で接続しているため ssh の公開鍵認証などの設定をする必要があります。また .bash_aliases などに以下のように書いておくと便利かもしれません。
$ cat .bash_aliases | grep vir
alias virsh='virsh -c qemu+ssh://test@10.0.0.250/system'
$ virsh list
Id Name State
----------------------
1 c20h running
virt-manager は GUI の File > Add Connection から設定が可能です。virsh, virt-manager 共に Windows Subsystem for Linux(WSL)上の Linux でも実行できるので便利です。
参照: SSHSetup
#[8. KVM ゲストを移行する](#8-KVM ゲストを移行する)
KVM ゲストを移行する際に古い KVM ホストから新しい KVM ホストにコピーしなければならないファイルは最低 2 つ。KVM ゲストのイメージ本体(qcow2)と設定ファイル(xml)ファイルです。
KVM ゲストのイメージは qcow2 という拡張子を持っていて、もっと良い方法もあるかもしれないですが virsh dumpxml コマンドで場所が確認できます。qcow2 ファイルをコピーする際には予め該当の KVM ゲストを shutdown させて置いたほうが良いと思います。
$ virsh dumpxml c20h | grep .qcow2
<driver name='qemu' type='qcow2'/>
<source file='/mnt/datastore1/images/c20h.qcow2'/>
KVM ゲストの設定ファイル (xml) の取得は同様に virsh dumpxml コマンドを使用します。
$ virsh dumpxml c20h > c20h.xml
新しい KVM ホストに移行する KVM ゲストを登録するには以下のコマンドを実行します。
$ virsh define c20h.xml
上記コマンドを実行する前に考慮する点としてはまず qcow2 ファイルの場所です。同じディレクトリに qcow2 ファイルを配置する場合は変更しなくて構いませんがもし異なる場合はテキストエディタで xml ファイルを予め編集します。
<source file='/mnt/datastore1/images/c20h.qcow2'/>
また同じく xml ファイルの中に cpu の種類の記述がある場合があります。もし CPU の種類が異なる場合はこの記述を変更します。
<cpu mode='custom' match='exact' check='partial'>
<model fallback='allow'>Haswell-noTSX-IBRS</model>
</cpu>
単に KVM ホストの CPU の情報を引き継ぐように変更してあげるのが良いと思います。
<cpu mode='host-model' check='partial'/>
上記設定は virsh define コマンドを事項した後に virtsh や virt-manage で変更することもできます。virt-manager で変更していしまうのも簡単で良いかもしれません。
virsh define コマンドを実行すると/etc/libvirt/qemu 以下に設定ファイルが作成されます。
$ ls -al /etc/libvirt/qemu/c20h.xml
-rw------- 1 root root 4663 Jan 10 18:10 /etc/libvirt/qemu/c20h.xml
参照: Linux備忘録 KVM仮想化ホスト間での仮想マシン移動
移行後の KVM ゲストは起動するようであれば virt-manager や virt-viewer でコンソールに接続し設定を変更することができます。
libguestfs-tools をインストールすれば KVM ゲストのディスクをマウントし編集することができます。この方法であれば KVM ゲストの起動前に設定を変更することができます。
$ sudo guestmount -d c20h -i /mnt/c20h/
$ sudo ls /mnt/c20h/etc/netplan
50-cloud-init.yaml
$ sudo vi /mnt/c20h/etc/netplan
$ sudo vi /mnt/c20h/etc/netplan/50-cloud-init.yaml
参照: How to mount VM virtual disk on KVM hypervisor with Libguestfs Tools
参照: virsh commands cheatsheet to manage KVM guest virtual machines