Run KVM in nested virtual environment of VitualBox

いまさら感はありますが、VitualBox で サポートされた Nested Virtualization を試してみました。
VirtualBox 6.0 で AMD CPU、VirtualBox 6.1 で Intel CPU での Nested Virtualization がサポートされました。

(VirtualBox 6.0.0)

(VirtualBox 6.1.0)

Nested Virtualization とは

Nested Virtualization とは、仮想マシンの中で Hypervisor を実行できる機能のことです。
簡単に言うと、仮想マシン入れ子です。
以下のレイヤが連携して動きます。

  • Level 0 layer (L0) : 実ハードウェア上で動作する Hypervisor
  • Level 1 layer (L1) : L0上で仮想マシンとして動作する Hypervisor
  • Level 2 layer (L2) : L1上で動作する仮想マシン

試してみる

今回使った環境は、以下の通りです。
VitualBoxVagrant はインストール済みという前提です。

$ sw_vers  
ProductName:    Mac OS X  
ProductVersion: 10.15.5  
BuildVersion:   19F101  
$ sysctl -a | grep brand_string  
machdep.cpu.brand_string: Intel(R) Core(TM) i7-6567U CPU @ 3.30GHz  
$ vboxmanage | head -n 1  
Oracle VM VirtualBox Command Line Management Interface Version 6.1.10  
$ vagrant version | head -n 1  
Installed Version: 2.2.9  

レイヤは以下のような感じです。

L1 仮想マシン

Vagrant + VirtualBox を使用して、L1 仮想マシンとなる CentOS 7.8.2003 (centos/7) をインストールします。

(L0)$ vagrant box add centos/7
(L0)$ vagrant init centos/7

Vagrantfile を編集して、L1 仮想マシンで CPU 仮想化支援機能が有効になるように設定します。
また、Nested Virtualization はオーバーヘッドが大きいので、普段 VirtualBox仮想マシンを動かすよりもマシンリソースを多めにします。

config.vm.provider "virtualbox" do |vb|
  vb.cpus = "2"
  vb.memory = "2048"
  vb.customize ["modifyvm", :id, "--nested-hw-virt", "on"]
end

仮想マシンを起動して、ssh ログインします。

(L0)$ vagrant up
(L0)$ vagrant ssh

CPU 仮想化支援機能フラグ (Intel CPU : vmx / AMD CPU : svm) が立っていることを確認します。

(L1)$ cat /etc/centos-release
CentOS Linux release 7.8.2003 (Core)
(L1)$ egrep '(vmx|svm)' /proc/cpuinfo 
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq vmx ssse3 cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single tpr_shadow flexpriority fsgsbase avx2 invpcid rdseed clflushopt md_clear flush_l1d
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq vmx ssse3 cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single tpr_shadow flexpriority fsgsbase avx2 invpcid rdseed clflushopt md_clear flush_l1d

L2 仮想マシン

L1 仮想マシンKVM 環境を構築して、L2 仮想マシンを起動します。
今回は、Vagrant + Libvirt を使用して、L2 仮想マシンとなる Debian 10.4 (debian/buster64) をインストールします。

まず、L1 仮想マシンに、KVM 関連パッケージと Vagrant をインストールします。

(L1)$ sudo yum install -y qemu-kvm libguestfs libvirt libvirt-client libvirt-devel virt-manager virt-top virt-viewer virt-who virt-install bridge-utils nfs-utils
(L1)$ sudo yum install -y https://releases.hashicorp.com/vagrant/2.2.9/vagrant_2.2.9_x86_64.rpm

libvirt グループに現在のユーザを追加します。

(L1)$ sudo gpasswd -a vagrant libvirt

Vagrant の provider として libvirt が使用できるように、vagrant-libvirt プラグインをインストールします。

(L1)$ vagrant plugin install vagrant-libvirt

L1 仮想マシンを再起動して、ssh ログインします。

(L0)$ vagrant reload
(L0)$ vagrant ssh

KVM に必要なカーネルモジュールが有効になっているか確認します。

(L1)$ lsmod | grep 'kvm'
kvm_intel             188688  0 
kvm                   636965  1 kvm_intel
irqbypass              13503  1 kvm

libvirt 用の box をダウンロードします。

(L1)$ vagrant box add --provider libvirt debian/buster64
(L1)$ vagrant box list
debian/buster64 (libvirt, 10.4.0)

L2 仮想マシンを起動して、ssh ログインします。

(L1)$ vagrant init debian/buster64
(L1)$ vagrant up --provider libvirt
(L1)$ vagrant ssh

L2 仮想マシンを確認します。

(L2)$ cat /etc/debian_version 
10.4
(L2)$ uname -a
Linux buster 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) x86_64 GNU/Linux

まとめ

VirtualBox の Nested Virtualization 機能を使用して、macOS -> CentOS 7.8.2003 -> Debian 10.4 という仮想マシン入れ子環境が構築できました。
L2 仮想マシンのパフォーマンスは確認していませんが、検証環境が簡単に準備できるようになって良いかもと感じました。