背景
我が家には、常時稼働の本番用のサーバと、必要な時に電源を入れる開発用のサーバがある。前者は Debian11 + LXC で、後者は Proxmox VE (KVM+LXC) で運用している。
ちょっとした検証等は常時稼働のサーバでやりたい*1が、本番環境に怪しいコンテナを作るのも嫌なので、KVMでサンドボックス化したい。一方、本番環境では KVM を使っておらず、不必要なものでホストOSを汚したくない。
そこで、KVM を使える コンテナを構築して、その中に Proxmox VE を導入しようと考えた。
検証環境
なお、本番サーバへの適用前に、開発用サーバ上の VM で検証したので、実際には以下のような構成となった。
KVM ホスト化
方針
大まかな方針としては、KVMの動作に必要なデバイスファイルを、LXC コンテナの中から扱えるようにする。以前、LXC コンテナ内で GPGPU するために採った策と基本的には同じ。
コンテナの作成と健全性確認
Proxmox VE 化は後からするとして、まずは普通の Debian 11 コンテナを作り。
$ sudo lxc-create -n kvm-in-container -t download -- -d debian -r bullseye -a amd64
起動する。
$ sudo lxc-start -n kvm-in-container
KVMやLXCをホストできるか検証してくれる virt-host-validate
コマンドを導入する。
$ sudo lxc-attach -n kvm-in-container -- apt install libvirt-clients
何も対策していない素の状態だと以下の通り。
$ sudo lxc-attach -n kvm-in-container -- virt-host-validate setlocale: No such file or directory QEMU: Checking for hardware virtualization : PASS QEMU: Checking if device /dev/kvm exists : FAIL (Check that the 'kvm-intel' or 'kvm-amd' modules are loaded & the BIOS has enabled virtualization) QEMU: Checking if device /dev/vhost-net exists : WARN (Load the 'vhost_net' module to improve performance of virtio networking) QEMU: Checking if device /dev/net/tun exists : FAIL (Load the 'tun' module to enable networking for QEMU guests) 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 : WARN (No ACPI IVRS table found, IOMMU either disabled in BIOS or not supported by this hardware platform) QEMU: Checking for secure guest support : WARN (Unknown if this platform has Secure Guest support) LXC: Checking for Linux >= 2.6.26 : PASS LXC: Checking for namespace ipc : PASS LXC: Checking for namespace mnt : PASS LXC: Checking for namespace pid : PASS LXC: Checking for namespace uts : PASS LXC: Checking for namespace net : PASS LXC: Checking for namespace user : PASS LXC: Checking for cgroup 'cpu' controller support : PASS LXC: Checking for cgroup 'cpuacct' controller support : PASS LXC: Checking for cgroup 'cpuset' controller support : PASS LXC: Checking for cgroup 'memory' controller support : PASS LXC: Checking for cgroup 'devices' controller support : PASS LXC: Checking for cgroup 'freezer' controller support : FAIL (Enable 'freezer' in kernel Kconfig file or mount/enable cgroup controller in your system) LXC: Checking for cgroup 'blkio' controller support : PASS LXC: Checking if device /sys/fs/fuse/connections exists : PASS
対策すべきは以下の項目。
/dev/kvm
が無い/dev/vhost-net
が無い/dev/net/tun
が無い
あと、/dev/fuse
が無くて Proxmox VE 化する際に失敗するため、合わせて対応する。単なる KVM ホストとしての動作には必須では無いので、その場合はスルーでよい。
それぞれ、ホストでデバイス番号を調べておく。
$ ls -l /dev/kvm /dev/vhost-net /dev/net/tun /dev/fuse crw-rw---- 1 root kvm 10, 232 10月 30 10:05 /dev/kvm crw-rw-rw- 1 root root 10, 200 10月 30 10:05 /dev/net/tun crw------- 1 root root 10, 238 10月 30 10:05 /dev/vhost-net crw------- 1 root root 10, 229 10月 30 10:05 /dev/fuse
コンテナ定義ファイルの修正
一旦コンテナを終了させる。
$ sudo lxc-stop -n kvm-in-container
次に、コンテナの定義ファイル /var/lib/lxc/<コンテナ名>/config
を編集する。
$ sudo vim /var/lib/lxc/kvm-in-container/config
LXCをネストさせるための設定。
lxc.include = /usr/share/lxc/config/common.conf lxc.include = /usr/share/lxc/config/nesting.conf lxc.apparmor.profile = unconfined lxc.apparmor.allow_nesting = 1
必要なデバイスファイルへのアクセス権を与える設定。
lxc.cgroup.devices.allow = c 10:232 rwm lxc.cgroup.devices.allow = c 10:200 rwm lxc.cgroup.devices.allow = c 10:238 rwm lxc.cgroup.devices.allow = c 10:229 rwm lxc.cgroup2.devices.allow = c 10:232 rwm lxc.cgroup2.devices.allow = c 10:200 rwm lxc.cgroup2.devices.allow = c 10:238 rwm lxc.cgroup2.devices.allow = c 10:229 rwm
ホストのデバイスファイルを bind mount する設定。なお、bind mount せずに、コンテナの中で mknod
コマンドでデバイスファイルを作成するのでもよい。
lxc.mount.entry = /dev/kvm dev/kvm none bind,optional,create=file lxc.mount.entry = /dev/net/tun dev/net/tun none bind,optional,create=file lxc.mount.entry = /dev/vhost-net dev/vhost-net none bind,optional,create=file lxc.mount.entry = /dev/fuse dev/fuse none bind,optional,create=file
コンテナの再起動と健全性再確認
コンテナを再起動する。
$ sudo lxc-start -n kvm-in-container
改めて virt-host-validate
コマンドで確認する。
$ sudo lxc-attach -n kvm-in-container -- virt-host-validate setlocale: No such file or directory 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 : WARN (No ACPI IVRS table found, IOMMU either disabled in BIOS or not supported by this hardware platform) QEMU: Checking for secure guest support : WARN (Unknown if this platform has Secure Guest support) LXC: Checking for Linux >= 2.6.26 : PASS LXC: Checking for namespace ipc : PASS LXC: Checking for namespace mnt : PASS LXC: Checking for namespace pid : PASS LXC: Checking for namespace uts : PASS LXC: Checking for namespace net : PASS LXC: Checking for namespace user : PASS LXC: Checking for cgroup 'cpu' controller support : PASS LXC: Checking for cgroup 'cpuacct' controller support : PASS LXC: Checking for cgroup 'cpuset' controller support : PASS LXC: Checking for cgroup 'memory' controller support : PASS LXC: Checking for cgroup 'devices' controller support : PASS LXC: Checking for cgroup 'freezer' controller support : FAIL (Enable 'freezer' in kernel Kconfig file or mount/enable cgroup controller in your system) LXC: Checking for cgroup 'blkio' controller support : PASS LXC: Checking if device /sys/fs/fuse/connections exists : PASS
問題なし。ここまできたら、後は qemu-kvm
や virt-manager
などを導入し、通常の KVM ホストと同じように扱える。
Proxmox VE 化(おまけ)
Debian 11 を Proxmox VE 化する際は以下のWebページが参考になる。
ただ、今回はコンテナなので、専用カーネルでの差し替えはできない。詳細は割愛するが、大まかな流れは以下となる。
$ sudo lxc-start -n kvm-in-container $ sudo lxc-attach -n kvm-in-container -- systemctl disable systemd-networkd systemd-resolved $ sudo lxc-stop -r -n kvm-in-container $ sudo lxc-attach -n kvm-in-container -- rm /etc/resolv.conf $ sudo lxc-attach -n kvm-in-container -- vim /etc/resolv.conf nameserver <DNSサーバのIPアドレス> search <検索ドメイン名> $ sudo lxc-attach -n kvm-in-container -- vim /etc/hosts <コンテナのIPアドレス> kvm-in-container $ sudo lxc-attach -n kvm-in-container -- dpkg-reconfigure locales <任意のロケールを選択> $ sudo lxc-attach -n kvm-in-container -- apt install wget $ sudo lxc-attach -n kvm-in-container -- vim /etc/apt/sources.list.d/pve-install-repo.list deb [arch=amd64] http://download.proxmox.com/debian/pve bullseye pve-no-subscription $ sudo lxc-attach -n kvm-in-container -- wget https://enterprise.proxmox.com/debian/proxmox-release-bullseye.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bullseye.gpg $ sudo lxc-attach -n kvm-in-container -- apt update $ sudo lxc-attach -n kvm-in-container -- apt full-upgrade $ sudo lxc-attach -n kvm-in-container -- apt install proxmox-ve
結果
こんな感じに仕上がった。
KVM on LXC on KVM 環境に、Proxmox VE を入れて、VM を作ることに成功した。実はホストも Proxmox VE なので、これで、Proxmox VE with KVM on LXC on Proxmox VE with KVM になった。
— kWatanabe (@WWatchin) 2022年11月21日
パススルーしすぎて、中央の LXC の中で virt-what を叩いたら、LXCとKVM の両方だと判定された。もはやカオス。 https://t.co/cgcn9BHQ1m pic.twitter.com/rI0NuyVwVT
まとめ
*1:目の前のマシンに Docker 入れればええやん、とか言わないで。禁止。