Rocky Linux9 で KVM ホストを構築してつまずきまくったまとめ

その他

2024.12.1

Topics

この記事はNHN テコラス Advent Calendar 2024の1日目の記事です。

挨拶

こんにちは、imr です。
検証環境用の仮想基盤を VMware ESXi から変更する必要があったため、Rocky Linux 9 を使って KVM で構築してみたところ、いくつかつまずくポイントがありました。
そこで、全体的な流れと自分がつまずいた部分についてまとめて記述します。

使用する環境について

移行元の VMware 環境は今回仮想基盤を構築するサーバーを使用していました。
事前に ovf テンプレートのエクスポートを使用して別の環境に仮想マシンのエクスポートを行っています。

OS は Rocky Linux 9.4 を使用します。
執筆時点(2024/11/19)での最新版になります
インストール時のパーティション作成は自動で行っています。

仮想基盤は KVM + QEMU を使用します。
Webコンソールは Cockpit を使用します。
仮想マシンのネットワークはホスト側でブリッジを作成して仮想基盤と同じネットワーク上の IPアドレスを使用します。

関連パッケージのインストール

dnf install コマンドで関連パッケージをインストールします。

$ sudo dnf install qemu-kvm libvirt virt-manager virt-install
$ sudo dnf install epel-release
$ sudo dnf install bridge-utils virt-top libguestfs-tools virt-viewer

つまずきポイント1:リポジトリの確認を怠らない

bridge-utils をインストールするために epel-release のインストールが必要でした。

$ sudo dnf info bridge-utils
Last metadata expiration check: 0:05:16 ago on Wed 20 Nov 2024 05:17:27 PM JST.
Installed Packages
Name         : bridge-utils
Version      : 1.7.1
Release      : 3.el9
Architecture : x86_64
Size         : 64 k
Source       : bridge-utils-1.7.1-3.el9.src.rpm
Repository   : @System
From repo    : epel
Summary      : Utilities for configuring the linux ethernet bridge
URL          : https://wiki.linuxfoundation.org/networking/bridge
License      : GPLv2+
Description  : This package contains utilities for configuring the linux
             : ethernet bridge. The linux ethernet bridge can be used for
             : connecting multiple ethernet devices together. The connecting is
             : fully transparent: hosts connected to one ethernet device see
             : hosts connected to the other ethernet devices directly.
             :
             : Install bridge-utils if you want to use the linux ethernet
             : bridge.

普段、OSインストール後に製品の検証用パッケージしかインストールしていなかったため、気づきませんでした。

状態確認

仮想化基盤として使える環境か確認します。

$ sudo lscpu |grep Virt
Virtualization:                       VT-x

Intel 製 CPU を搭載しているため、VT-x が表示されました。
AMD 製 CPU を搭載している場合は AMD-V と表示されます。

virt-host-validate コマンドで問題がないか確認します。

$ sudo virt-host-validate
  QEMU: Checking for hardware virtualization                                 : PASS
  QEMU: Checking if device /dev/kvm exists                                   : PASS
  QEMU: Checking if device /dev/kvm is accessible                            : PASS
  QEMU: Checking if device /dev/vhost-net exists                             : PASS
  QEMU: Checking if device /dev/net/tun exists                               : PASS
  QEMU: Checking for cgroup 'cpu' controller support                         : PASS
  QEMU: Checking for cgroup 'cpuacct' controller support                     : PASS
  QEMU: Checking for cgroup 'cpuset' controller support                      : PASS
  QEMU: Checking for cgroup 'memory' controller support                      : PASS
  QEMU: Checking for cgroup 'devices' controller support                     : PASS
  QEMU: Checking for cgroup 'blkio' controller support                       : PASS
  QEMU: Checking for device assignment IOMMU support                         : PASS
  QEMU: Checking if IOMMU is enabled by kernel                               : WARN (IOMMU appears to be disabled in kernel. Add intel_iommu=on to kernel cmdline arguments)
  QEMU: Checking for secure guest support                                    : WARN (Unknown if this platform has Secure Guest support)

Checking if IOMMU is enabled by kernel が WARN になっているので、/proc/cmdline に intel_iommu=on があるか確認します。

$ sudo cat /proc/cmdline
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-5.14.0-427.37.1.el9_4.x86_64 root=/dev/mapper/rl-root ro crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap rhgb quiet

つまずきポイント2:cmdline の更新には –update-bls-cmdline オプションをつけよう

/etc/grub/default に GRUB_CMDLINE_LINUX に intel_iommu=on を追記します。

GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap rhgb quiet intel_iommu=on"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true

grub2-mkconfig -o /boot/grub2/grub.cfg を実行して grub.conf を更新して再起動しても 追加したパラメータが反映されませんでした。

$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg

調べてみると Rocky Linux 9.3 で似たような事象について Rocky Linux のフォーラムにスレッドがありました。
こちらの内容によると grub2-mkconfig に–update-bls-cmdline をつけて実行すると反映されるといった内容が
ありました。

参考:Grub2-mkconfig RL9.3 fresh install bug | Rocky Linux

$ sudo grub2-mkconfig --update-bls-cmdline -o /boot/grub2/grub.cfg
$ sudo reboot

再起動して /proc/cmdline を確認します

$ sudo cat /proc/cmdline
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-5.14.0-427.42.1.el9_4.x86_64 root=/dev/mapper/rl-root ro crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap rhgb quiet intel_iommu=on

無事反映されました
virt-host-validate コマンドで Checking if IOMMU is enabled by kernel も PASS になっていました

つまずきポイント3:PASSしてなくても無視していい場合がある

Checking for secure guest support も WARN になっていたので調べてみました
QEMU の ドキュメントに以下の内容がありました。

Supported mechanisms
Currently supported confidential guest mechanisms are:

  • AMD Secure Encrypted Virtualization (SEV) (see AMD Secure Encrypted Virtualization (SEV))
  • POWER Protected Execution Facility (PEF) (see POWER (PAPR) Protected Execution Facility (PEF))
  • s390x Protected Virtualization (PV) (see Protected Virtualization on s390x)

Other mechanisms may be supported in future.
出典:Confidential Guest Support | qemu documentation

どうやら Intel 製の CPU では対応していないようです。
今回はこの項目については無視します。

libvirtd の実行と有効化

systemctl start libvirtd.service で libvirtd が起動することを確認します。
systemctl enable で libvirtd を有効化します。

$ sudo systemctl start libvirtd
$ sudo systemctl enable libvirtd.service
Created symlink /etc/systemd/system/multi-user.target.wants/libvirtd.service → /usr/lib/systemd/system/libvirtd.service.
Created symlink /etc/systemd/system/sockets.target.wants/virtlockd.socket → /usr/lib/systemd/system/virtlockd.socket.
Created symlink /etc/systemd/system/sockets.target.wants/virtlogd.socket → /usr/lib/systemd/system/virtlogd.socket.
Created symlink /etc/systemd/system/sockets.target.wants/libvirtd.socket → /usr/lib/systemd/system/libvirtd.socket.
Created symlink /etc/systemd/system/sockets.target.wants/libvirtd-ro.socket → /usr/lib/systemd/system/libvirtd-ro.socket.
Created symlink /etc/systemd/system/sockets.target.wants/libvirtd-admin.socket  → /usr/lib/systemd/system/libvirtd-admin.socket.
Created symlink /etc/systemd/system/sockets.target.wants/virtlockd-admin.socket → /usr/lib/systemd/system/virtlockd-admin.socket.
Created symlink /etc/systemd/system/sockets.target.wants/virtlogd-admin.socket  → /usr/lib/systemd/system/virtlogd-admin.socket.

systemctl status で libvirtd の状態を確認

$ sudo systemctl status libvirtd.service

つまずきポイント4:systemd socket activation を意識しよう

libvirtd が手動起動後 2分経つと inactive (dead) のステータスになっていたため原因を調べました。

systemctl start libvirtd.service で手動起動後に ps コマンドでプロセスを確認すると –timeout 120 のオプションがついており使用するものがない場合、タイムアウトで停止するようになっています

$ sudo systemctl start libvirtd.service
[root@aw0012-rocky-kvm ~]$ sudo ps aux|grep libvirtd
root        4452  0.8  0.3 1686988 53848 ?       Ssl  13:12   0:00 /usr/sbin/libvirtd --timeout 120

既定値で systemd socket activation を使用するように設定されているため、libvirtd.service が必要になった場合、自動で起動されるようになっています。

$ sudo systemctl status libvirtd
○ libvirtd.service - libvirt legacy monolithic daemon
     Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; preset: disabled)
     Active: inactive (dead) since Tue 2024-11-12 13:34:38 JST; 17min ago
   Duration: 2min 105ms
TriggeredBy: ● libvirtd-admin.socket
             ● libvirtd-ro.socket
             ● libvirtd.socket
       Docs: man:libvirtd(8)
             https://libvirt.org/
    Process: 3408 ExecStart=/usr/sbin/libvirtd $LIBVIRTD_ARGS (code=exited, status=0/SUCCESS)
   Main PID: 3408 (code=exited, status=0/SUCCESS)
        CPU: 193ms

Nov 12 13:32:38 aw0012-rocky-kvm systemd[1]: Starting libvirt legacy monolithic daemon...
Nov 12 13:32:38 aw0012-rocky-kvm systemd[1]: Started libvirt legacy monolithic daemon.
Nov 12 13:34:38 aw0012-rocky-kvm systemd[1]: libvirtd.service: Deactivated successfully.

ネットワーク設定の確認

ネットワーク設定の確認、この時点でまだブリッジ接続は作成していません

$ sudo brctl show
$

ネットワークブリッジの作成

Cockpit から作成しました
ネットワーキングから「ブリッジの追加」を選択します
Cockpit ネットワーク設定画面
IPアドレスが割り当てられているポートを選択して「追加」を選択します。
ネットワークブリッジ作成画面
できました。
作成されたネットワークブリッジの状態画面

$ sudo brctl show
bridge name     bridge id               STP enabled     interfaces
virtbr0         8000.901b0e61e567       no              eno1

$ sudo nmcli connect show
NAME     UUID                                  TYPE      DEVICE
virtbr0  8273f683-1815-4396-8d87-cf7f2bad5677  bridge    virtbr0
eno1     0b735036-4ddc-3583-863c-bfee409c8b6f  ethernet  eno1
lo       e504d563-3b78-434f-a325-deb39853c6d0  loopback  lo

コマンドでもネットワークブリッジが作成されたことを確認できました。

ここまでで仮想基盤の構築が完了しました、次からはこの仮想基盤に仮想マシンの作成やインポート作業とそこでつまずいた内容について記載していきます。

仮想マシンの作成では Rocky Linux8 を使用しています。

仮想マシンの作成

準備ができたので仮想マシンを作成します。
Cockpit をインストールしているので Cockpit で操作していきます。

つまずきポイント5:OSインストール時のパーティション作成は利用用途を考えて作成しよう

今回使用した環境は合計で 570GB の HDDを搭載しています。しかしながら「仮想マシンの作成」で使用することができるストレージ容量が少なく表示されていました。

Cockpit で「仮想マシンの作成」をクリックします。
Cockpit 仮想マシン画面
ストレージの制限に記載されている使用可能容量が 57.1GiB しかないように見えます
Cockpit仮想マシン作成画面
ストレージプールの default は既定値で /var/lib/libvirt/images が指定されています

$ sudo df -h --total
Filesystem           Size  Used Avail Use% Mounted on
devtmpfs             4.0M     0  4.0M   0% /dev
tmpfs                7.7G     0  7.7G   0% /dev/shm
tmpfs                3.1G   17M  3.1G   1% /run
/dev/mapper/rl-root   70G   13G   58G  19% /
/dev/sda2            960M  434M  527M  46% /boot
/dev/mapper/rl-home  479G   24G  455G   6% /home
/dev/sda1            599M  7.1M  592M   2% /boot/efi
tmpfs                1.6G  4.0K  1.6G   1% /run/user/1000
total                563G   38G  526G   7% -

基盤として構築しているサーバーは、OS インストール時にパーティション作成を自動で行っていました。
そのため /var を含むルートパーティションには 70 GiB しか割り当てられませんでした。
/home 配下に 479 GiB の容量を割いていますので、default のストレージプールを /home 配下に作り直しました。

「仮想マシン」の画面からストレージプールを選択します。
Cockpit 仮想マシン画面ストレージプールを選択
名前が default のストレージプールの右端にある縦に三つの点が並んでいるオプションメニューから削除を選択します。
Cockpit ストレージプール画面
削除するか聞かれるので「削除」ボタンをクリックします
ストレージプール削除確認画面
削除されたことを確認出来たらストレージプール作成をクリックして default ストレージプールを新たに作成します
ストレージプール作成画面
今回はサーバー上のディレクトリ /home/vm を指定します。
接続:System
名前:default
タイプ:ファイルシステムのディレクトリー
ターゲットパス:/home/vm
起動:ホスト起動時にプールを起動する にチェック

作成できました、作成した直後は非アクティブ状態のため有効化をクリックしてアクティブにします
新しく作成した default ストレージプールの画面
ストレージプールを有効化した後の表示

改めて「仮想マシンの作成」を行っていきます
仮想マシンは検証でよく使う Rocky Linux 8 の iso ファイルを使用してインストールします。
仮想マシン作成画面、パラメータ入力済み
テスト用に作成した仮想マシンのスペックは以下のとおりです

名前:test2024
接続:System
インストールタイプ:ローカルメディア
インストールソース:isoファイルのパスを指定
オペレーティングシステム:Rocky Linux 8 (Green Obsidian) ※システム上対応しているものは iso から判別して自動で入力されます
ストレージ:qcow2 ボリュームの新規作成
ストレージの制限:20GiB
メモリ:4GiB

入力できましたら「作成して編集する」をクリックします
作成した仮想マシン概要画面
作成された仮想マシンのファームウェアが BIOS になっているので UEFI に変更します
変更できましたらインストールをクリックして Cockpit 上からコンソールを操作して Rocky Linux 8 をインストールします
Rocky Linux 8 のインストール作業の流れについては割愛します。

無事インストールできました
Rocky Linux8 ログイン画面を表示した Cockpit の画面

VMDK ファイルからのインポート

本記事の冒頭に記載した旧環境から事前に VMware 環境から 「ovf テンプレートのエクスポート」でエクスポートした仮想マシンをインポートします。
エクスポートした vmdk ファイルなどは default ストレージプールの /home/vm 配下にディレクトリを作成して配置しました。

qemu-img コマンドで vmdk ファイルから qcow2 ファイルにコンバートします。

$ sudo ll
total 5263016
-rw-r--r--. 1 root root 5389306368 Oct 10 10:36 test176-0.vmdk
-rw-r--r--. 1 root root         87 Oct 10 10:36 test176.mf
-rw-r--r--. 1 root root      14858 Oct 10 10:27 test176.ovf
$ sudo qemu-img convert -f vmdk -O qcow2 test176-0.vmdk test176-0.qcow2
$ ll
total 12342156
-rw-r--r--. 1 root root 7248019456 Nov 19 17:53 test176-0.qcow2
-rw-r--r--. 1 root root 5389306368 Oct 10 10:36 test176-0.vmdk
-rw-r--r--. 1 root root         87 Oct 10 10:36 test176.mf
-rw-r--r--. 1 root root      14858 Oct 10 10:27 test176.ovf

コンバートができたら Cockpit 画面を操作してインポートしていきます。
「VMのインポート」を選択します。
Cockpit 仮想マシンメニュー、VMのインポートを選択

今回インポートした仮想マシンは CentOS 7 になります。
仮想マシンインポートメニュー
名前:test176
接続:System
ディスクイメージ:/home/vm/test176/test176-0.qcow2
オペレーティングシステム:CentOS 7
メモリ 2GiB
「インポートして編集する」を選択します。

つまずきポイント6:ドライバに注意しよう

このまま起動すると OSの起動プロセスが停止して起動できませんでした。
Cockpit 仮想マシン画面、ディスクとネットワークインターフェースの状態
ディスクのバスとネットワークインターフェースのモデルタイプが virtio になっています。

virtio を使うためには仮想マシン側で 修正が必要でした。
virtio を使用しないのであれば、編集をクリックしてディスクのバスとネットワークインターフェースのモデルタイプを変更することでインポートした仮想マシンが起動できることを確認しました。

Cockpit 仮想マシン画面、ディスクとネットワークインターフェースの編集
Cockpit ディスクの編集画面
Cockpitネットワークインターフェース編集画面

インポートした仮想マシンで virtio を使う

virtio を使う場合はインポートした仮想マシンをレスキューイメージで起動して initramfs の書き換えを行います。
VMware 環境で virtio ドライバをインストールしてからエクスポートすることををお勧めします。
今回の移行作業にあたりエクスポートした仮想マシンは VMware 環境で virtio ドライバをインストールしていませんでした。
そのため以下の作業を実施しています。

以下の操作は Cockpit画面で操作したため、 VNCコンソールの画面キャプチャになります。

仮想マシンOS起動画面、レスキューイメージを選択

/boot/config-$(uname -r) で virtio が使用可能か確認します。

grep -i virtio /boot/config-$(uname -r)

/boot/config-$(uname -i) の結果表示

CONFIG_VIRTIO_BLK と CONFIG_VIRTIO_NET が ともに =m になっているため使用可能です。

CONFIG_VIRTIO_BLK=m
CONFIG_VIRTIO_NET=m

lsinitrd コマンド を使用して initramfs に virtio が含まれていないことを確認します。

lsinitrd /boot/initramfs-$(uname -r).img |grep virtio

lsinitrd コマンドの結果に virtio がないことを確認

initramfs のバックアップを作成します。

cp /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r)img.bak

initramfs のバックアップ

dracut コマンドで initramfs を更新します。

dracut -f /boot/initramfs-$(uname -r).img $(uname -r) 

dracutコマンドでinitramfs を更新、更新した結果で virtio が含まれていることを確認
更新ができたら lsinitrd コマンド を使用して virtio が含まれていることを確認します。
確認出来たら仮想マシンを再起動します。

無事仮想マシンが起動できました。

つまずきポイント7:ネットワークインターフェースの設定を確認しよう

起動した仮想マシンに SSH 接続できませんでした。
Cockpit 画面から VNCコンソールで確認してみると OS上のネットワークインターフェースの設定がおかしいことがわかりました。
ネットワークインターフェースの状態

nmtui コマンドを使用して NAME がおかしいネットワークインターフェースの情報を削除して ens192 と eth0 を関連付けます。
一度 Device の項目に入力されている情報を削除してから eth0 と入力しなおすことで関連付けすることができました。
nmtui 設定画面1
nmtui設定画面2
設定変更後 nmcli connect show コマンド実行結果

これでインポートした仮想マシンに SSH接続ができるようになりましたのでインポート作業も完了です。

まとめ

所々つまずくところがあったためいろいろなサイトを見ながら作業を実施しました。
せっかくなので自分がつまずいたところをまとめましたので誰かのためになれば幸いです。

NHN テコラスの採用情報はこちら

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

imr

逆流性食道炎で大好きな麻婆豆腐を食べると胸やけがすごい。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら