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 仮想マシンのパフォーマンスは確認していませんが、検証環境が簡単に準備できるようになって良いかもと感じました。

Vagrant assumes that this means the command failed! (Virtualbox 6.0.6 + Vagrant 2.2.4 + vagrant-vbguest 環境でのエラー)

The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

 setup

Stdout from the command:



Stderr from the command:

bash: 行 4: setup: コマンドが見つかりません

vagrant up 時に上記のエラーが出た場合は、次の設定で VirtualBox Guest Addition の自動更新を無効にする。

Vagrant.configure("2") do |config|
  config.vbguest.auto_update = false
end

vagrant-vbguest doesn't work with vagrant-reload · Issue #333 · dotless-de/vagrant-vbguest · GitHub

Docker 入門(1) ~ Docker インストールから apache サービスが稼働しているコンテナの生成まで ~

とりあえず Docker 動かしてみる的な手順のまとめです。

環境

Docker for Mac を使います。
コンテナ側の OS は CentOS 7.6 です。

  • ホスト OS: macOS Mojava
  • Docker バージョン
    • docker: 18.09.2
    • docker-compose: 1.23.2
    • docker-machine: 0.16.1

Docker インストール

Homebrew*1 でインストールします。

$ brew install docker  
$ brew cask install docker  

Docker.app 初回起動時に Docker ID でのログインを求められます。

コンテナの生成

$ docker container run -it --name centos-base centos:7.6.1810 /bin/bash   

コンテナが起動すると、プロンプトが root@xxxxxxxxxxxx(container id) になります。

@コンテナ
# cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)

status が up なコンテナが起動しています。

@ホスト
$ docker container ls -a  
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
xxxxxxxxxxxx        centos:7.6.1810     "/bin/bash"         About a minute ago   Up About a minute                       centos-base

コンテナに httpd パッケージをインストール

OS を最新版にして、httpd をインストールします。

@コンテナ  
# yum check-update     
# yum update -y   
# yum install -y httpd   
# systemctl enable httpd.service   

Docker イメージの作成

httpd をインストールしたコンテナを Docker イメージ化します。
exit を実行して、コンテナを停止します。

@コンテナ
# exit

次のコマンドで Docker イメージ(centos:7.6.1810-httpd)を作成します。

@ホスト
$ docker container commit centos-base centos:7.6.1810-httpd   
$ docker images  
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              7.6.1810-httpd      xxxxxxxxxxxx        2 minutes ago       422MB

systemd に対応したコンテナの生成

これまではコンテナ生成時に /bin/bash を起動していましたが、systemd で httpd を起動するようにコンテナを生成します。
CentOS 7 では、/sbin/init が /lib/systemd/systemd へのシンボリックリンクになっているので、コンテナ生成時に /sbin/init を起動します。

@ホスト
$ docker container run -itd --tmpfs /tmp --tmpfs /run \   
-v /sys/fs/cgroup:/sys/fs/cgroup:ro --stop-signal SIGRTMIN+3 \   
--name centos-httpd -p 8080:80 centos:7.6.1810-httpd /sbin/init   
$ docker container ls -a   
CONTAINER ID        IMAGE                   COMMAND             CREATED              STATUS                   PORTS                  NAMES
xxxxxxxxxxxx        centos:7.6.1810-httpd   "/sbin/init"        About a minute ago   Up About a minute        0.0.0.0:8080->80/tcp   centos-httpd

今回はホストの 8080 ポートをコンテナの 80 ポートへマッピングしているので、ホスト (localhost) の 8080 へアクセスして、apache のデフォルトページが取得できることを確認します。

@ホスト
$ curl http://localhost:8080/   

systemd で起動したコンテナへのログインとコンテナ停止

コンテナ生成時に /sbin/init を起動しているので、最初に起動したコンテナのようにコンテナ側プロンプトが表示されません。
コンテナへログインしたい場合は、次のコマンドを実行します。

$ docker container exec -it centos-httpd /bin/bash

コンテナのプロンプト root@xxxxxxxxxxxx(container id) が表示されます。
コンテナからログアウトする場合は、[ control + p ] -> [ control + q] を押します。
コンテナを停止する場合は、コンテナへログインした状態で exit を実行します。

www.docker.com

*1:Homebrew は事前にインストールしてください。https://brew.sh/

技術書典6

技術書典6に行ってきました。
後日、何買ったか忘れてしまうので、購入した書籍の備忘録です。

結構買ったなぁという感じです。
簡単後払いが便利でした。

techbookfest.org

YAPC::Tokyo 2019 に行ってきた #yapcjapan


遅くなりましたが、去る 1/26(土) YAPC::Tokyo 2019 に参加してきました。
今回も良い YAPC でした。
以下、セッションの感想などなど。

Perl 6 でのアプリケーション開発と実用

インストールが簡単になっていたり、エコシステムも揃ってきているので、Perl 6 書きたい機運が高まりました。

Perl to Go

GOPATH の呪縛とパッケージ管理で挫折した組ですが、セッション聞いて Go 勉強しようと思いました。

Perl on Rails

「レールに乗せたい」という考え方は分かるなぁーという感じでした。
Perl プロダクトに Rails の便利機能を導入しているのは凄いなぁと思いました。

ログにやさしいDB設計

ログテーブルの設計難しい。
ログテーブル設計は、自分の中でこれといった答えがないので、いろいろ考えさせられるセッションでした。

Keynote

コミュニティへの貢献方法とか、非常に参考になる内容でした。

コミュニティとは「利用するもの」であり、かつまた「貢献するもの」

雑感

Perl 成分多めな YAPC でした。 Perl 利用者は減少傾向だと思うけど、Perl は便利だし、何より好きな言語なので使っていくだろうなぁと思いました。
tokuhirom さんの Keynote にあったように、気負わないでコミュニティに貢献していこうと思いました。
運営スタッフと関係者のみなさん、参加者のみなさん、ありがとうございました。

yapcjapan.org