インストール - KVM

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

ここでは、KVM(Kernel-based Virtual Machine)とQEMUのインストールと仮想マシンの設定方法を記載する。
搭載しているCPUが仮想化機構(Intel VTやAMD-V等)を備えている必要がある。


KVMとQEMUのインストール

パッケージ管理システムからインストール

KVMとQEMUをインストールする。

# RHEL
sudo dnf install qemu-kvm libvirt virt-install virt-manager

# SUSE
sudo zypper install qemu-kvm libvirt virt-install virt-manager
または
sudo zypper install patterns-server-kvm_server patterns-server-kvm_tools


モジュールが読み込まれているか確認する。

lsmod | grep kvm


もし、パッケージのインストール後にKVMモジュールが読み込まれていない場合、以下のコマンドを実行する。

# Intel CPU
sudo modprobe kvm-intel

# AMD CPU
sudo modprobe kvm-amd


正常に読み込まれている場合は、以下のように表示される。

kvm_intel             241664  0
kvm                   704512  1 kvm_intel
irqbypass              16384  1 kvm


KVMを起動および自動起動する場合は、以下のコマンドを実行する。

sudo systemctl start libvirtd
sudo systemctl enable libvirtd


必要であれば、libvirtグループにユーザがアクセスできるように設定する。

sudo usermod -aG libvirt $USER


ソースコードからインストール

GNU TLS 3.6.14以降のインストール

パッケージ管理システムのGNU TLSのバージョンが3.6.14未満の場合は、GNU TLSのソースコードをビルドしてインストールする。
また、GNU TLS 3.6.14(2022/4現在の最新)のビルドでは、Nettle 3.4.1が必要となることに注意する。

GNU TLSのビルドに必要なライブラリをインストールする。

sudo zypper install libtasn1-devel libunistring-devel unbound-devel p11-kit-devel gmp-devel libnettle-devel


GNU TLSのソースコードをダウンロードする。
もし、パッケージ管理システムにあるGMPおよびNettleが古い場合、これらのソースコードもダウンロードする。


ビルドディレクトリを作成して、GMP、Nettle、GNU TLSをビルドおよびインストールする。

# GMP (パッケージ管理システムにあるGMPが古い場合)
../configure --prefix=<Nettle、GMP、GNU TLSのインストールディレクトリ>
make -j $(nproc)
make install

# Nettle (パッケージ管理システムにあるNettleが古い場合)
../configure --prefix=<Nettle、GMP、GNU TLSのインストールディレクトリ> --enable-openssl --enable-x86-aesni --enable-x86-sha-ni --enable-x86-pclmul
make -j $(nproc)
make install

# GNU TLS
../configure --prefix=<Nettle、GMP、GNU TLSのインストールディレクトリ> --enable-shared
make -j $(nproc)
make install


~/.profileファイル等に環境変数を追記する。

vi ~/.profile


# ~/.profileファイル

export PATH="<Nettle、GMP、GNU TLSのインストールディレクトリ>/bin:$PATH"
export LD_LIBRARY_PATH="<Nettle、GMP、GNU TLSのインストールディレクトリ>/lib64:$LD_LIBRARY_PATH"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$(pkg-config --variable pc_path pkg-config)"
export PKG_CONFIG_PATH="<Nettle、GMP、GNU TLSのインストールディレクトリ>/lib64/pkgconfig:$PKG_CONFIG_PATH"


PCを再起動する。

QEMUのインストール

QEMUのビルドに必要なライブラリをインストールする。

sudo zypper install flex bison indent dtc automake gcc gcc-c++ make glibc glibc-utils glib2-devel gtk3-devel ncurses-devel libxml2-devel \
                    libgnutls-devel gmp-devel libnettle-devel libseccomp-devel liburing-devel libgbm-devel glusterfs-devel \
                    libjpeg8-devel libpng16-devel libpulse-devel alsa-devel libjack-devel spice-protocol-devel libspice-server-devel \
                    libxkbcommon-devel libcap-devel libcap-ng-devel libpcap-devel libcurl-devel virglrenderer-devel xfsprogs-devel \
                    libiscsi-devel libzstd-devel libnfs-devel libvdeplug-devel brlapi-devel libSDL2-devel libSDL2_image-devel librados-devel \
                    lzfse-devel libmpath0 libcacard-devel lzo-devel snappy-devel libgcrypt-devel libu2f-server-devel libu2f-host-devel \
                    usbredir-devel libusb-1_0-devel libpmem-devel libkeyutils1 keyutils-devel libselinux-devel fuse-devel fuse3-devel libbpf-devel \
                    libbd_swap-devel libcapstone-devel libslirp-devel libfdt-devel sphinx libsphinxclient-devel  numad libnuma1 numactl libnuma-devel \
                    librbd-devel rdma-core-devel libnet-devel libfvde-devel libdmmp-devel multipath-tools-devel libssh-devel libssh2-devel \
                    pipewire-devel sndio-devel libjson-c-devel libcmocka-devel python3-pytest python3-flake8 python3-restructuredtext_lint vte-devel libdw-devel \
                    sysprof-devel sysprof-ui-devel gtk-vnc-devel
                    systemd-devel  # SUSE 15.4以降の場合
                    libudev-devel  # SUSE 15.3以前の場合


  • QEMUの公式Webサイトから、ソースコードをダウンロードする場合
    QEMUの公式Webサイトにアクセスして、ソースコードをダウンロードする。
    ダウンロードしたファイルを解凍する。
    tar xf qemu-<バージョン>.tar.xz
    cd qemu-<バージョン>

  • Gitからソースコードをダウンロードする場合
    git clone git://git.qemu.org/qemu.git
    cd qemu
    git submodule update --init --recursive


QEMUをビルドおよびインストールする。

mkdir build && cd build

../configure --prefix=<QEMUのインストールディレクトリ> \
             --enable-trace-backends=simple \
             --enable-kvm --enable-spice --enable-spice-protocol --enable-usb-redir      \
             --enable-opengl --enable-tpm --enable-xkbcommon --enable-bzip2 --enable-sdl \
             --enable-gtk --enable-vdi --enable-qcow1 --enable-tools --enable-fdt        \
             --audio-drv-list=oss,alsa,sdl,pa                                            \
             --enable-vfio-user-server  # 任意 : VFIO (Virtual Function I/O) ユーザサーバー機能を有効にする場合
             --enable-libusb            # 不要の可能性あり
             --enable-hax               # QEMU 8.2以降は、このオプションは削除された
             --target-list=i386-softmmu,i386-linux-user,x86_64-softmmu,x86_64-linux-user     # ターゲットをx86およびx86_64限定する場合
             # ターゲットにARMおよびAArch64を追加する場合は、arm-softmmu,arm-linux-user,aarch64-softmmu,aarch64-linux-userを指定する

make -j $(nproc)  または  ninja -j $(nproc)
make install  または  ninja -j $(nproc) install


※注意
--enable-vfio-user-serverオプションは、QEMUのコンフィギュレーションにおいて、VFIOをユーザ空間で使用するためのサーバ機能を有効にする。

VFIO-userは、QEMUの比較的新しい機能であり、以下に示すような目的がある。

  • リモートデバイスエミュレーション
    ホストPCとは別のマシン上でデバイスエミュレーションを実行できるようにする。
  • セキュリティの向上
    デバイスエミュレーションを分離された環境で実行することで、セキュリティを強化する。
  • 柔軟性の向上
    デバイスエミュレーションをより柔軟に管理・スケーリングできるようになる。


このオプションを有効にすると、QEMUはVFIO-userプロトコルをサポートするサーバーとして動作できるようになる。
これにより、リモートクライアントがQEMUに接続し、仮想化されたデバイスにアクセスすることが可能になる。

ただし、この機能は比較的新しく、実験的な面もあるため、本番環境での使用には注意が必要である。
現状では、開発やテスト目的で使用されることが多い。

~/.profileファイル等に環境変数を追記する。

vi ~/.profile


 # ~/.profileファイル
 
 export PATH="<QEMUのインストールディレクトリ>/bin:$PATH"


もし、QEMUを/usrディレクトリ以外の場所にインストールした場合、パーミッションの問題が発生する可能性がある。
この時、AppArmorの設定を、以下に示すように編集する。

AppArmorを使用している場合、libvirtにQEMUを実行するためのAppArmorパーミッションを追加する必要がある。
まず、/etc/apparmor.d/usr.sbin.libvirtdファイルにある最後"}"記号の直前に、以下に示す設定を追記する。
(以下の例では、QEMUを/home/user/QEMUディレクトリにインストールしているものとする)

sudo vi /etc/apparmor.d/usr.sbin.libvirtd


# /etc/apparmor.d/usr.sbin.libvirtdファイル

# ...略

  # User Add
  /usr/bin/kvm rmix,
  /home/user/QEMU/bin/qemu-i386 rmix,
  /home/user/QEMU/bin/qemu-system-i386 rmix,
  /home/user/QEMU/bin/qemu-x86_64 rmix,
  /home/user/QEMU/bin/qemu-system-x86_64 rmix,
}


次に、/etc/apparmor.d/abstractions/libvirt-qemuファイルの最下行に、QEMU向けのAppArmorパーミッションを追加する。

sudo vi /etc/apparmor.d/abstractions/libvirt-qemu


# /etc/apparmor.d/abstractions/libvirt-qemuファイル

# User Add
/usr/bin/kvm rmix,
/home/user/QEMU/bin/qemu-i386 rmix,
/home/user/QEMU/bin/qemu-system-i386 rmix,
/home/user/QEMU/bin/qemu-x86_64 rmix,
/home/user/QEMU/bin/qemu-system-x86_64 rmix,


最後に、AppArmorのルールセットを再読み込みする。

sudo systemctl reload apparmor


libvirtのインストール

※注意
libvirtを手動でインストールすることは、一般的に推奨されない。
パッケージ管理システムからインストールしたlibvirtを手動でインストールしたlibvirtで上書きする場合、正常に動作しない可能性がある。

/usrディレクトリ以外のディレクトリ(ホームディレクトリ等)にインストールする場合、
ldconfigコマンドや同様のユーティリティを実行して、インストールした共有ライブラリのリストを更新、または、バイナリや共有ライブラリのパスを調整する必要がある。

libvirtは、ユーザの設定に基づいた複数のデーモンを提供している。
手動でインストールしたlibvirtが使用できるようにするには、適切なプロセスを起動する必要がある。
例えば、libvirtdは、ほとんどの構成でvirtlogdサービスを起動する必要がある。

libVirtのビルドに必要なライブラリをインストールする。

sudo zypper install flex bison automake gcc make glibc glibc-utils glib2-devel zlib-devel libapparmor-devel libblkid-devel bash-completion-devel \
                    numad libnuma1 numactl libnuma-devel libyajl2 yajl libyajl-devel libpixman-1-0 libpixman-1-0-devel libgsasl-devel libselinux-devel \
                    libtool libgnutls30 libgnutls-devel libnl3-devel libxml2-devel libtirpc-devel python3-docutils \
                    device-mapper-devel libpciaccess-devel rpcbind readline-devel rpcgen libxslt-devel bzip2 \
                    fuse3-devel libbpf-devel sphinx libsphinxclient-devel libcapstone-devel keyutils-devel \
                    libcurl-devel libudev-devel libiscsi-devel libzstd-devel libnfs-devel libu2f-server-devel libu2f-host-devel \
                    libcacard-devel libfdt-devel glusterfs-devel libpmem-devel libslirp-devel libSDL2-devel liburing-devel \
                    libseccomp-devel libbd_mpath-devel librados-devel usbredir-devel gtk3-devel virglrenderer-devel \
                    libspice-server-devel spice-protocol-devel libxkbcommon-devel alsa-devel libjack-devel \
                    libjpeg8-devel libpng16-devel libssh-devel libssh2-devel lzo-devel lzfse-devel libfido2-devel xfsprogs-devel \
                    snappy-devel brlapi-devel librbd-devel rdma-core-devel libnet-devel libfvde-devel libdmmp-devel multipath-tools-devel \
                    libcap-devel libcap-ng-devel libpcap-devel parted-devel audit-devel fuse-devel sanlock-devel wireshark-devel scrub \
                    python3-flake8 libcorosync-devel python3-capng python3-openwsman libwsman_clientpp-devel libattr-devel polkit-devel


libvirtの公式Webサイトにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。

tar xf libvirt-<バージョン>.tar.xz
cd libvirt-<バージョン>


または、Githubからソースコードをダウンロードすることもできる。

git clone https://github.com/libvirt/libvirt.git


libvirtをビルドおよびインストールする。
この時、libvirtの一部のファイルは、/usrディレクトリにインストールされることに注意する。

# libvirt 6.7.0以降 (SLES / openSUSE推奨)
meson build -Dsystem=false -Ddriver_qemu=enabled --prefix=<libvirtのインストールディレクトリ>
ninja -C build
ninja -C build install

# libvirt 6.7.0以降 (SLED推奨)
meson build -Dsystem=true -Ddriver_qemu=enabled --prefix=<libvirtのインストールディレクトリ>
ninja -C build
sudo ninja -C build install  # AppArmorやFirewalld、Polkit等の各種設定ファイルとログファイルを作成するためにスーパーユーザ権限でインストールする

# libvirt 6.7.0未満
mkdir build && cd build
../autogen.sh --prefix=<libvirtのインストールディレクトリ>
make -j $(nproc)
make install


libvirtdの実行に必要なライブラリをインストールする。

sudo zypper install libwsman3


libvirtのバイナリファイルは/usrディレクトリにインストールされるが、libvirtのインストールディレクトリにrunファイルというヘルパースクリプトがインストールされる。
runファイルを実行することにより、libvirtのバイナリファイルを実行することができる。
runファイルは、libvirtユーティリティを実行するための環境変数を設定することができる。

libvirtのインストールディレクトリにあるrunファイルを実行して、libvirtサービス(libvirtd)を起動する。
libvirtサービスのファイルは、/<libvirtのインストールディレクトリ>/etc/libvirtディレクトリに配置されている。
runファイルは、ビルドされたバージョンのツールを実行するために使用することができる。

sudo ./run src/virtlockd &  # バックグラウンドで実行する必要がある
sudo ./run src/virtlogd &   # バックグラウンドで動作させる必要がある
sudo ./run src/libvirtd     # ログを見るためにフォアグラウンドで実行するlibvirtdデーモン


libvirtdデーモンを起動した後、virshコマンドを使用して仮想マシンを操作することができる。
以下の例では、virsh destroyコマンドを使用して仮想マシンを破壊した後、virsh list --allコマンドを使用して仮想マシンが破壊されたことを確認している。

sudo ./run tools/virsh destroy  apic_test

# 出力例
Domain apic_test destroyed


sudo ./run tools/virsh list --all

# 出力例
Id   Name        State
----------------------------
-    apic_test   shut off


Virt-Managerのインストール

Virt-ManagerのGithubからソースコードをダウンロードして、ビルドおよびインストールする。
Virt-Managerのビルドに必要なライブラリをインストールする。

sudo zypper install glib2-devel gtk3-devel gtksourceview-devel \
                    python3-devel python3-docutils python3-gobject-devel python3-libvirt-python python3-libguestfs \
                    libosinfo-devel gobject-introspection gobject-introspection-devel libguestfs0 libguestfs-devel gettext


Virt-Managerのソースコードをダウンロードする。

git clone https://github.com/virt-manager/virt-manager.git


先に特定のインストールディレクトリを作成する必要がある。

mkdir -p /<Virt-Managerのインストールディレクトリ>/share/glib-2.0/schemas
mkdir -p /<Virt-Managerのインストールディレクトリ>/share/icons/hicolor


Virt-Managerをビルドおよびインストールする。

./setup.py configure --prefix=<Virt-Managerのインストールディレクトリ>
./setup.py build
./setup.py install



仮想ネットワークの設定

このセクションでは、Br0という名前のブリッジを作成する。
まず、以下のコマンドを実行して、ブリッジユーティリティをインストールする。

sudo zypper install bridge-utils


RHEL

仮想マシンがブリッジ接続できるように、ブリッジネットワークを構成する。
ens2のインターフェース名の部分は環境によって異なるため、自身の環境に読み替えること。
ブリッジbr0を追加する。

nmcli connection add type bridge autoconnect yes con-name br0 ifname br0

Connection 'br0' (a7fa989a-798e-40ac-acc4-3d1733189b82) successfully added.


br0のIPアドレスを設定する。

nmcli connection modify br0 ipv4.addresses 10.0.0.30/24 ipv4.method manual


br0のゲートウェイを設定する。

nmcli connection modify br0 ipv4.gateway 10.0.0.1


br0のDNSを設定する。

nmcli connection modify br0 ipv4.dns 10.0.0.1


既存のインターフェースは一旦削除する。

nmcli connection del ens2


br0のメンバーとして再度追加する。

nmcli connection add type bridge-slave autoconnect yes con-name ens2 ifname ens2 master br0


RHELを再起動する。

sudo systemctl reboot


正常にbr0が起動しているか確認する。

ip a


SUSE

仮想マシンをブリッジ接続する場合は、NetworkManagerをwickedに変更して、ブリッジネットワークを構成する。

sudo mv /etc/sysconfig/network/ifcfg-eth0 /etc/sysconfig/network/ifcfg-br0
sudo vi /etc/sysconfig/network/ifcfg-br0


以下の内容を、/etc/sysconfig/network/ifcfg-br0ファイルに追記する。

# 最終行に追記
BRIDGE='yes'
BRIDGE_FORWARDDELAY='0'
BRIDGE_PORTS='eth0'
BRIDGE_STP='off'


次に、以下の内容を、/etc/sysconfig/network/routesファイルに追記する。

sudo vi /etc/sysconfig/network/routes


# 最終行:br0のデフォルトゲートウェイを追記する
default 192.168.1.1 - br0


wickedサービスを再起動する。

sudo systemctl restart wickedd wicked


正常にbr0が起動しているか確認する。

ip a



仮想マシンの作成(CLI)

仮想マシンをインストールして作成する。
ここでは、仮想マシンとしてSUSE Linxu Enterprise Server 15(以降、SUSEという)をインストールする。

取得したSUSEのisoファイルを/tmpディレクトリに配置して、テキストモードでインストールする。
コンソールからでもPutty等のエミュレータ経由からでも実行できる。
初期設定では、仮想マシンの保管場所(ストレージプール)は、/var/lib/libvirt/imagesディレクトリであるが、ここでは、別の場所に新たにストレージプールを作成して進める。

ストレージプールディレクトリの作成

まず、ストレージプールディレクトリを作成する。

sudo mkdir -p /var/kvm/images


仮想マシンの作成とインストール
sudo virt-install \
--name sle15 \
--ram 4096 \
--disk path=/var/kvm/images/sle15.img,size=30 \
--vcpus 2 \
--os-type linux \
--os-variant sle15 \
--network bridge=br0 \
--graphics none \
--console pty,target_type=serial \
--location /tmp/SLE-15-Installer-DVD-x86_64-GM-DVD1.iso \
--extra-args 'console=ttyS0,115200n8 serial'

Starting install...     # インストールが開始される


上記の例で指定しているオプションの意味を以下に示す。その他多数のオプションは、man virt-installで確認できる。

  • --name
    仮想マシンの名前を指定する。
  • --ram
    仮想マシンのメモリ容量を指定する。(単位は、M)
  • --disk path=xxx ,size=xxx
    [path=]で仮想マシンのディスクの保管場所を指定する。(初期設定では、/var/lib/libvirt/imagesディレクトリ)
    [size=]で仮想マシンのディスク容量を指定する。(単位は、G)
  • --vcpus
    仮想マシンの仮想CPU数を指定する。
  • --os-type
    仮想マシンのOタイプを指定する。
  • --os-variant
    仮想マシンの種類を指定する。
    osinfo-query osで指定可能な種類を確認できる。
  • --network
    仮想マシンのネットワークタイプを指定する。
    ここでは、仮想マシンにブリッジ接続させるため、--network bridge=br0としている。
    br0は、上記セクションの[仮想ネットワークの設定]で設定したブリッジインターフェースを指定している。
    ホストがNICを複数持っていて、かつ、ブリッジインターフェースを複数設定しており、仮想マシンからも同様に複数のネットワークインターフェースを使用する場合は、改行して複数指定する。
  • --graphics
    グラフィクスを指定する。
    noneを指定するとグラフィックスを使用しない。
  • --console
    コンソールタイプを指定する。
  • --location
    インストール元を指定する。
  • --extra-args
    インストール時にカーネルに渡すパラメータを指定する。


インストーラ起動後は、CLIでインストール作業を進める。CLIもGUIと同様なのでインストール過程は省略する。
インストールが完了すると、一旦再起動がかかり、以下のようにターミナル上に仮想マシンのログインプロンプトが表示される。

Welcome to SUSE Linux Enterprise Server 15  (x86_64) - Kernel 4.12.14-25.25-default (ttyS0).

eth0: 10.0.0.204 fe80::5054:ff:feff:cfce

linux-6am4 login:


ホストと仮想マシンの切り替え

仮想マシン側からホスト側へのコンソールの切り替えは、[Ctrl]キー + []]キーである。
また、ホスト側から仮想マシン側へのコンソールの切り替えは、virsh console <仮想マシン名>]と入力して実行する。

仮想マシンの複製

作成した仮想マシンは容易に複製できる。

sudo virt-clone --original sle15 --name template --file /var/kvm/images/template.img

Allocating 'template.img' | 30 GB 00:00:02
Clone 'template' created successfully.


# ディスクイメージ
ll /var/kvm/images/template.img

-rw------- 1 root root 2835087360 Jan 18 19:09 /var/kvm/images/template.img


# 定義ファイル
ll /etc/libvirt/qemu/template.xml

-rw------- 1 root root 3681 Jan 18 11:09 /etc/libvirt/qemu/template.xml



仮想マシンの作成(GUI)

ここでは、GUIの操作で、仮想マシンを作成およびインストールする。

  1. ターミナルにてsudo virt-managerコマンドを実行して、Virtual Machine Managerを起動する。
    左上のPCアイコンまたは[ファイル] - [新しい仮想マシンの作成]を選択して、新規仮想マシン作成ウィザードを開く。
  2. [新しい仮想マシン]画面が開くので、仮想マシンのインストール元を指定する。
    インストールメディアまたはISOファイルとアーキテクチャを選択して、OSのタイプとバージョンを指定する。
  3. 仮想マシンのメモリ容量と仮想CPU数を指定する。
  4. 仮想ディスクの場所や容量を指定する。
  5. 仮想マシン名を入力する。また、これまでの設定内容を確認しておく。
  6. インストーラが起動するので、画面に従ってインストールする。


ストレージや光学式ドライブをパススルーする場合、以下の手順に従う。

  1. virt-managerの起動後、仮想マシンのアイコンを右クリックして、[開く]を選択する。
  2. 画面左下にある[ハードウェアの追加]を選択して、画面左の[ストレージ] - 画面右の[カスタムストレージの選択または作成]項目に、/dev/sdXや/dev/srX等のデバイスファイル名を指定する。
  3. 画面右下の[完了]ボタンを押下する。
  4. 自動的にSCSIコマンドのパススルーが行われる。



KVMの操作方法

Libvirtに含まれるVirshコマンドを使用した仮想マシンの操作方法を記載する。

  • 仮想マシンを起動する。
sudo virsh start <仮想マシン名>


  • 仮想マシンを起動して同時にコンソールに接続する。
sudo virsh start <仮想マシン名> --console


  • 仮想マシンを停止する。
sudo virsh shutdown <仮想マシン名>


  • 仮想マシンを強制停止
sudo virsh destroy <仮想マシン名>


  • 仮想マシンの削除
# ゲストOSの定義の削除
sudo virsh undefine <仮想マシン名>

# 仮想マシンの定義ファイルの<仮想マシン名>.xmlファイルを確認する
sudo ls /etc/libvirt/qemu

# 仮想マシンの割り当てディスク(仮想マシンの物理ファイル)を削除する
sudo rm -f <仮想マシンの割り当てディスク(仮想マシンの物理ファイル)>.qcow2


  • 仮想マシンをシステム起動時に自動起動の設定をする。
sudo virsh autostart <仮想マシン名>


  • 仮想マシンの自動起動設定を解除する。
sudo virsh autostart --disable <仮想マシン名>


  • 仮想マシンの一覧を表示する。
sudo virsh list


  • 全ての仮想マシンを一覧を表示する。
sudo virsh list --all


  • コンソールを切り替える。
    仮想マシン側からホスト側へのコンソールの切り替えは、 [Ctrl]キー + []]キーである。
    ホスト側から仮想マシン側へのコンソールの切り替えは、sudo virsh console <仮想マシン名>コマンドを実行する。


  • imgファイルをqcow2ファイルに変換する。
sudo qemu-img convert -f raw -O qcow2 <イメージ名>.img <イメージ名>.qcow2


  • 他、多くのサブコマンドが用意されている。
sudo virsh --help



仮想マシンのバックアップおよび復元

仮想マシンのバックアップ

仮想マシンを停止する。

sudo virsh shutdown <仮想マシン名>


設定ファイルをバックアップする。

sudo virsh dumpxml <仮想マシン名> > /<バックアップ先のディレクトリ>/<仮想マシン名>.xml


仮想マシンのイメージをバックアップする。

sudo cp -p /<仮想マシンのファイルが存在するディレクトリ>/<仮想マシン名>.qcow2 <バックアップ先のディレクトリ>


また、各仮想マシンの定義ファイルは、/etc/libvirt/qemuディレクトリに存在する。
その定義ファイルを指定してvirsh defineコマンドを実行することで、仮想マシンをvirshコマンドで管理できるようになる。

sudo virsh define /etc/libvirt/qemu/<仮想マシン名>.xml


なお、この定義ファイルは直接編集せず、virsh editコマンドを使用して編集すること。
なぜなら、virsh editコマンドを使用することで、定義ファイルに誤りがあった場合にエラーを出力してくれるので安全である。

sudo virsh edit <仮想マシン名>

# 標準エディタをnanoに変更する場合
sudo EDITOR=nano virsh edit <仮想マシン名>


仮想マシンの復元

バックアップした仮想マシンのイメージを復元する。

sudo cp -p /<仮想マシンのイメージをバックアップしたディレクトリ>/<仮想マシン名>.qcow2 <仮想マシンのイメージを保存するディレクトリ>


バックアップした設定ファイルを復元する。

sudo cp -p /<仮想マシンのイメージをバックアップしたディレクトリ>/<仮想マシン名>.xml /etc/libvirt/qemu


復元した設定ファイルをKVMに反映する。

sudo virsh define /etc/libvirt/qemu/<仮想マシン名>.xml


バックアップに成功すると、以下のようなメッセージが出力される。

ドメイン <仮想マシン名> が /etc/libvirt/qemu/<仮想マシン名>.xml から定義されました


復元されたSUSEを起動する。

sudo virsh start <仮想マシン名>



KVMを使用した仮想マシンのスナップショット

スナップショットの概要

KVMにおけるスナップショットとは、仮想マシンのある時点の状態を保持する機能である。
スナップショットは、一般的なバックアップのように全てのデータを保持せずに、仮想マシン上の変更が発生した時に差分のみを保持する。

スナップショットは、仮想マシン本体またはスナップショットファイルのいずれかが破損すると、元の状態に戻すことはできなくなるので、
バックアップの代わりとして利用する場合は注意すること。

スナップショットの作成手順として、親スナップショット(external)を作成して、それから派生する子スナップショット(internal)を作成する。

親スナップショット(external)の取得

virsh snapshot-create-asコマンドを使用することで、仮想マシンの親スナップショット(external)を取得することができる。
スナップショットの取得は、仮想マシンが起動中でも可能である。

sudo virsh snapshot-create-as <仮想マシン名> <スナップショット名> "<コメント>" --disk-only --atomic


親スナップショット(external)の復元

親スナップショットの復元は、virsh snapshot-revertコマンドを使用する。
親スナップショットの復元については、子スナップショット(internal)を取得してから行うこと。

sudo virsh snapshot-revert <仮想マシン名> <スナップショット名>


親スナップショット(external)の削除

親スナップショット(external)を削除する場合は、--metadataオプションを付けることで削除できる。

sudo virsh snapshot-delete <仮想マシン名> <親スナップショット名> --metadata


子スナップショット(internal)の取得

親スナップショット(external)を取得した状態で、以下のコマンドを実行すると、スナップショットを取得することができる。
なお、スナップショット名は親スナップショット(external)や他の子スナップショット(internal)と被らないようにすること。

sudo virsh snapshot-create-as <仮想マシン名> <子スナップショット名> "<コメント>"


子スナップショット(internal)の復元

特定のスナップショットに復元するには、virsh snapshot-revertコマンドを使用する。
指定するスナップショットは、子スナップショット(internal)を指定するようにする。

sudo virsh snapshot-revert <仮想マシン名> <子スナップショット名>


子スナップショット(internal)の削除

virsh snapshot-deleteコマンドを実行することで、スナップショットを削除することができる。

sudo virsh snapshot-delete <仮想マシン名> <子スナップショット名>


スナップショットの確認
sudo virsh snapshot-list <仮想マシン名>


# 出力例
 Name                 Creation Time             State
------------------------------------------------------------
 SN01_KVM_SUSE        2020-01-01 00:00:00 +0900 shutoff


スナップショットのツリー表示

スナップショットの派生関係を確認する場合、--treeオプションを付けることで確認できる。

sudo virsh snapshot-list <仮想マシン名> --tree


# 出力例
SN01_KVM_SUSE
 |
 +- SN02_KVM_SUSE
     |
     +- MariaDB_KVM_SUSE
     +- PostgreSQL_KVM_SUSE


現在の状態が、どのスナップショットからの派生か確認する

virsh snapshot-listコマンドに--tree --currentオプションを使用することで確認することができる。

sudo virsh snapshot-list <仮想マシン名> --tree --current


# 出力例
MariaDB_KVM_SUSE



QEMUを使用した仮想マシンのスナップショット

このセクションでは、QEMUイメージツールを使用して、QCOW2形式で利用できる高度な機能のいくつかを記載する。
Virt-Managerには、QCOW2形式のファイルにおいて、スナップショットの作成等の行う機能は無い。

QCOW2形式のファイル(バッキングファイル)に基づくスナップショットを作成と、バッキングファイルへの参照を削除する手順を記載する。

仮想マシンの情報の表示

仮想マシンのファイルに関するいくつかの基本情報を表示する。
ファイルのディスク上のサイズ、参照されているバッキングファイルの名前、使用可能なスナップショットのリストが含まれる。

qemu-img info <仮想マシン名またはスナップショット名>.qcow2


仮想マシンのファイルの作成

単純なQCOW2形式の仮想マシンのファイルを作成する。
このファイルに使用されるディスク容量は比較的小さくなるが、最大ストレージ容量は<ストレージ容量>となる。

qemu-img create -f qcow2 <仮想マシン名> <仮想マシンの最大ストレージ容量>

例.
qemu-img create -f qcow2 openSUSE_15_3.qcow2 100G


バックアップファイルの作成

バッキングファイル(仮想マシンのファイル)に基づくQCOW2形式のバックアップファイルを作成する。
バックアップファイルは、バッキングファイルの変更を回避するために、Redirect-on-Writeを使用してバッキングファイルを参照するファイルである。

KVM / QEMUにより書き込まれたクラスタは、全てバックアップファイルに書き込まれるため、バッキングファイルは変更されない。

バックアップファイルを使用する場合は、KVM / QEMUを使用してバックアップファイルに対して新しい仮想マシンを作成する。

バッキングファイルを変更すると、それに基づく全てのバックアップファイルが破損するため注意すること。

qemu-img create -f qcow2 -b <仮想マシンのファイル名>.qcow2 -l <バックアップファイル名>.qcow2
または
qemu-img create -f qcow2 -b <仮想マシンのファイル名>.qcow2 <バックアップファイル名>.qcow2


もし、バッキングファイルを実行する場合は、必ずバックアップファイルを削除すること。
また、以下のコマンドを実行することで、バックアップファイルの情報を表示することができる。

qemu-img <バックアップファイル名>.qcow2


スナップショットの一覧の表示

指定された仮想マシンのファイルに存在する全てのスナップショットの一覧を表示する。

qemu-img snapshot -l <仮想マシンのファイル名>.qcow2


スナップショットの作成

スナップショットを作成する。
QEMUのスナップショットは、スナップショットが作成された時の仮想マシンの状態の簡単な図である。

qemu-img snapshot -c <スナップショット名> <仮想マシンのファイル名>.qcow2


スナップショットの復元

スナップショットを適用する。
スナップショットが作成された時に保存されたクラスタを単純に復元するため、仮想マシンをその時点の状態に戻すことができる。

qemu-img snapshot -a <スナップショット名> <仮想マシンのファイル名>.qcow2


スナップショットの削除

指定された仮想マシンのファイルから各スナップショットを削除する。
スナップショットはファイルサイズが大きいため、ディスク領域を大きく消費する可能性がある。
このコマンドは、仮想マシンのファイルに割り当てたディスク領域ではなく、関連するクラスタを解放する。

qemu-img snapshot -d <スナップショット名> <仮想マシンのファイル名>.qcow2


仮想マシンのファイルの変換

同じQCOW2形式との間で変換する場合、仮想マシンのファイルの現在の状態のみを出力ファイルにコピーする。
出力ファイルには、参照されたバッキングファイルの全てのクラスタが含まれる。ただし、スナップショットの情報はコピーされない。
この変換は、バッキングファイルへの参照なしで、スタンドアロンイメージを作成する効果がある。

-pオプションは、コピー操作中に進行状況情報を表示する。(変換 / コピーは時間が掛かるため、-pオプションを使用する)

qemu-img convert -p -f qcow2 <変換元の仮想マシンのファイル名>.qcow2 -O qcow2 <変換後の仮想マシンのファイル名>.qcow2


一時的なスナップショット

QEMUは一時的なスナップショットもサポートしており、ユーザは個別のQCOW2形式のファイルを明示的に作成する必要はない。

-snapshotオプションを使用すると、実行中に仮想マシンに加えられた変更は、
全て一時ファイルに書き込まれて、仮想マシンがオフになると自動的に破棄される。
この時、仮想マシンのファイルへの変更は保存されない。

qemu -hda <仮想マシンのファイル名>.qcow2 -snapshot



仮想マシンの保存先の変更

別のHDD / SSDに仮想マシンを配置する場合、初期設定ではアクセス権限エラーになる。
そこで、/etc/libvirt/qemu.confファイルに以下の設定を追記する。

# /etc/libvirt/qemu.confファイル
・
・
・
user = "root"
group = "root"


また、別のHDD / SSDに仮想マシンを配置する時は、配置先のディレクトリで以下のコマンドを実行する。
以下では、<仮想マシン名>.qcow2ファイルを最大100[GB]の領域で仮想マシンを作成している。

qemu-img create -f qcow2 <仮想マシン名>.qcow2 100G


QXLを使用する場合、VRAMの容量が足りない時は、以下の設定を記述する。

<video>
  <model type='qxl' ram='65536' vram='65536' vgamem='65536' heads='1' primary='yes'/>
</video>



仮想マシンに割り当てるIPアドレス

存在するKVMのネットワーク名を確認する。

sudo virsh net-list


IPアドレスの変更を行うため、KVMのネットワークを編集する。

sudo virsh net-edit <KVMのネットワーク名>

例. sudo virsh net-edit default


 <network>
 
   <!-- ...略 -->
 
   <ip address='192.168.xxx.1' netmask='255.255.255.0'>
     <dhcp>
       <range start='192.168.xxx.2' end='192.168.xxx.254'/>
     </dhcp>
   </ip>
 </network>



エラー時の対処方法

QEMUのアクセス権限の付与

別のHDD / SSDに仮想マシンを配置する場合、初期設定ではアクセス権限エラーになる。
そこで、/etc/libvirt/qemu.confファイルに以下の設定を追記する。

sudo vi /etc/libvirt/qemu.conf


# /etc/libvirt/qemu.confファイル
・
・
・
user = "root"
group = "root"


また、別のHDD / SSDに仮想マシンを配置する時は、配置先のディレクトリで以下のコマンドを実行する。
以下では、<仮想マシン名>.qcow2ファイルを最大100[GB]の領域で仮想マシンを作成している。

qemu-img create -f qcow2 <仮想マシン名>.qcow2 100G


ネットワーク

VM起動時に下記のエラーが出力されて、VMが起動できないことがある。

ERROR    Requested operation is not valid: network 'default' is not active


まず、以下のコマンドを実行する。
この時、以下のメッセージが出力された場合は、sudo virsh net-start defaultを実行する。
今後、このネットワークを自動起動するには、sudo virsh net-autostart --network defaultを実行する。

# 実行
sudo virsh net-list --all

# 出力
名前      状態       自動起動      永続
------------------------------------------------
default   停止状態   いいえ (no)   はい (yes)


また、以下のようにネットワークが表示されない場合がある。

Name                 State      Autostart     Persistent
----------------------------------------------------------


その時は、/run/libvirt/network/default.xmlファイルを作成して、以下に示す内容を記述する。(デフォルトネットワークを作成する)

# /run/libvirt/network/default.xmlファイル

<networkstatus>
   <class_id bitmap='0-2'/>
   <floor sum='0'/>
   <network>
      <name>default</name>
      <uuid>e8a9f86b-1c3a-4fa5-ab03-1fb563b12b84</uuid>
      <forward mode='nat'>
         <nat>
            <port start='1024' end='65535'/>
         </nat>
      </forward>
      <bridge name='virbr0' stp='on' delay='0'/>
      <mac address='52:54:00:a3:0d:b0'/>
      <ip address='192.168.122.1' netmask='255.255.255.0'>
         <dhcp>
            <range start='192.168.122.2' end='192.168.122.254'/>
         </dhcp>
      </ip>
   </network>
</networkstatus>


次に、そのネットワークをKVMホストに永続的に追加するには、以下のコマンドを実行する。

sudo virsh net-define --file default.xml


ファイアーウォール

VM起動時に下記のエラーが出力されて、VMが起動できないことがある。

error: Failed to start network default
error: internal error: Failed to initialize a valid firewall backend


この時、ファイアーウォールサービスをインストールする。

sudo zypper install firewalld


サービスを有効にして、ネットワークを再び機能させるために、次のコマンドを実行する。

sudo systemctl enable --now firewalld
sudo systemctl restart libvirtd


DNSマスカレード

VM起動時に下記のエラーが出力されて、VMが起動できないことがある。

error: Failed to start network default
error: Cannot check dnsmasq binary /usr/sbin/dnsmasq: No such file or directory


この時、DNSマスカレードをインストールする。

sudo zypper install dnsmasq


ホストOSのスリープ / ハイバネート

ゲストOSの起動中にホストOSのスリープ / ハイバネートを実行する場合、ホストOSがロックアップするバグが存在する。

VFIOを有効にしたゲストOSは、スリープ / ウェイクアップサイクルを通して実行したままにすると不安定になる傾向があり、
シャットダウンを実行する時、ホストOSがロックアップすることが知られている。

これを回避する方法は、libvirtフックスクリプトとsystemdユニットを使用して、
ゲストOSの実行中にホストOSがスリープ状態になることを防ぐ。

また、libvirtフックスクリプトを実行するためには、実行可能なパーミッションが必要である。

sudo vi /etc/libvirt/hooks/qemu


 # libvirtフックスクリプト
 
 #!/bin/bash
 
 OBJECT="$1"
 OPERATION="$2"
 SUBOPERATION="$3"
 EXTRA_ARG="$4"
 
 case "$OPERATION" in
    "prepare")
       systemctl start libvirt-nosleep
       ;;
    "release")
       systemctl stop libvirt-nosleep
       ;;
 esac


スリープ / ハイバネートを無効化するデーモンを作成する。

sudo vi /usr/lib/systemd/system/libvirt-nosleep.service


# /usr/lib/systemd/system/libvirt-nosleep.serviceファイル

[Unit]
Description=Preventing sleep while libvirt domain "%i" is running

[Service]
Type=simple
ExecStart=/usr/bin/systemd-inhibit --what=sleep --why="Libvirt domain \"%i\" is running" --who=%U --mode=block sleep infinity


上記のデーモンのシンボリックリンクを/etc/systemd/systemディレクトリに張る。

sudo ln -s /usr/lib/systemd/system/libvirt-nosleep.service /etc/systemd/system/


上記で作成したデーモンを有効にする。

sudo systemctl daemon-reload


上記で作成したデーモンを開始する。

sudo systemctl start libvirt-nosleep.service


上記で作成したデーモンを停止する。

sudo systemctl stop libvirt-nosleep.service



各ゲストOSのインストール

Windows 11

TPM 2.0を有効にするために、SWTPMをインストールする。

  • パッケージ管理システムからインストールする場合
    sudo zypper install swtpm

  • ソースコードからインストールする場合
    まず、SWTPMのビルドに必要な依存関係のライブラリをインストールする。
    sudo zypper install automake autoconf bash coreutils expect expect-devel libtool sed libtpms0 libtpms-devel \
    fuse fuse-devel libglib-2_0-0 glib2-devel json-glib-devel net-tools net-tools-deprecated python3 python3-Twisted \
    libselinux-devel socat trousers trousers-devel gnutls libgnutls-devel libtasn1 libtasn1-6 libtasn1-devel libseccomp-devel libunistring-devel

    次に、SWTPMのGithubからソースコードをダウンロードする。
    wget https://github.com/stefanberger/swtpm/archive/refs/tags/<バージョン>.tar.gz
    または
    git clone https://github.com/stefanberger/swtpm.git

    ダウンロードしたファイルを解凍して、ビルドディレクトリを作成する。
    tar xf swtpm-<バージョン>.tar.gz
    cd swtpm-<バージョン> && mkdir build && cd build

    tssグループとそのユーザを作成する必要がある。
    sudo zypper install system-user-tss
    SWTPMをビルドおよびインストールする。
    ../autogen.sh --prefix=<SWTPMのインストールディレクトリ> --libdir=/<SWTPMのインストールディレクトリ>/lib64 \
    --with-openssl --with-tss-user=root --with-tss-group=tss # tcsdはファイルを通常ユーザ/通常グループまたはroot/tssにする必要がある
    または
    ../autogen.sh --prefix=<SWTPMのインストールディレクトリ> --libdir=/<SWTPMのインストールディレクトリ>/lib64 \
    --with-openssl --with-tss-user=$USER --with-tss-group=<$USERが所属しているグループ名> # tcsdはファイルを通常ユーザ/通常グループまたはroot/tssにする必要がある

    make -j $(nproc)
    make check -j $(nproc) # 実行は任意である
    make install

    ~/.profileファイル等に環境変数PATHおよびLD_LIBRARY_PATHを追記する。
    # ~/.profileファイル
    export PATH="<SWTPMのインストールディレクトリ>/bin:$PATH"
    export LD_LIBRARY_PATH="<SWTPMのインストールディレクトリ>/lib64:$LD_LIBRARY_PATH"


Virt-ManagerでTPM 2.0を追加する時、XMLファイルは以下のように設定される。

 ... 略
 
 <devices>
   <tpm model='tpm-tis'>
     <backend type='emulator' version='2.0'/>
   </tpm>
 </devices>
 
 ...略


openSUSE

openSUSEをインストールする場合、KMSが有効化されていると、udevの確認でインストーラがフリーズする。

回避方法は、openSUSEのインストール画面において、[F3]キーを押下する。
カーネルパラメータエントリにnomodesetと入力して、KMSを無効にする。

  • QXLを使用する場合
    1. openSUSEのインストールが完了した後、YaSTを起動して、ブートローダの設定にあるnomodesetの記述を削除する。
    2. 次に、以下のコマンドを実行して、QXLをロードする。
      sudo modprobe qxl modeset=1
    3. initrdを再構築するために、以下のコマンドを実行する。
      sudo dracut -f /boot/initrd $(uname -r)
  • GPUパススルーを使用する場合
    1. ホストOSがSUSEの場合、ホストのブートローダの設定にpci=noaerを記述する。(不要の可能性がある)
    2. ゲストOSのopenSUSEのインストールが完了した後、YaSTを起動して、ブートローダの設定にあるnomodesetの記述を確認する。
      GPUパススルーを使用する場合、nomodesetの記述は削除しない。
    3. もし、ブートローダの設定において、nomodesetの記述が削除されている場合、nomodesetを追記する。