Firecracker をオンプレ環境で動かしてみた #reinvent

はじめに

前回のブログにて、Firecracker の環境を構築し実機検証中であることをお伝えしましたがオンプレ環境で動きましたので共有します。

前回のブログは、こちらから参照いただけます。

Firecracker のデザインについて調べてみた #reinvent

環境について

サポート構成上、Linux Kernel 4.14 以降の KVM 環境が必要です。

What operating systems are supported by Firecracker?

Firecracker supports Linux host and guest operating systems with kernel versions 4.14 and above.

そのため、プライベートマシンである MacBook Air (11-inch, Mid 2012) に Ubuntu 18.04.1 LTS デスクトップ環境を構築し検証を行いました。

ubuntu-desktop-image

詳細は、下記のとおりです。

$ uname -a
Linux mba 4.15.0-39-generic #42-Ubuntu SMP Tue Oct 23 15:48:01 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.1 LTS
Release:    18.04
Codename:   bionic
$ lscpu
アーキテクチャ:                      x86_64
CPU 操作モード:                      32-bit, 64-bit
バイト順序:                          Little Endian
CPU:                                 4
オンラインになっている CPU のリスト: 0-3
コアあたりのスレッド数:              2
ソケットあたりのコア数:              2
ソケット数:                          1
NUMA ノード数:                       1
ベンダー ID:                         GenuineIntel
CPU ファミリー:                      6
モデル:                              58
モデル名:                            Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz
ステッピング:                        9
CPU MHz:                             1117.416
CPU 最大 MHz:                        2600.0000
CPU 最小 MHz:                        800.0000
BogoMIPS:                            3392.29
仮想化:                              VT-x
L1d キャッシュ:                      32K
L1i キャッシュ:                      32K
L2 キャッシュ:                       256K
L3 キャッシュ:                       3072K
NUMA ノード 0 CPU:                   0-3
フラグ:                              fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm cpuid_fault pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase smep erms xsaveopt dtherm ida arat pln pts flush_l1d
$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7883        1234        5983         274         665        6115
Swap:          2047           0        2047

なお、Ubuntu 環境には予め KVM などのパッケージソフトウェアをインストールしておく必要があります。

$ sudo apt install -y qemu-kvm libvirt0 libvirt-bin virt-manager libguestfs-tools bridge-utils

上記のパッケージには、Firecracker の動作に必要ではないパッケージも含まれているかもしれませんがご容赦ください。

事前作業

今回は、GitHub に記載の Getting Started と quickstart guide を元に作業を進めますのでまずは最新ソースを git clone で取得しておいてください。

$ git clone https://github.com/firecracker-microvm/firecracker
$ cd firecracker
$ tools/devtool build
:
[Firecracker devtool] Build complete. Binaries placed under /home/shimoda/local/firecracker/build/debug/
$ ls -l build/debug/firecracker
-rwxr-xr-x 1 shimoda shimoda 51746336 12月  7 09:12 build/debug/firecracker

ビルドしたバイナリは、build/debug/firecracker になります。 次に、ゲストOS 用の kernel とルートFS イメージファイルを取得します。 firecracker のバイナリと同じディレクトリに置いておく必要がある点に注意が必要です。

$ cd build/debug/
$ curl -fsSL -o hello-vmlinux.bin https://s3.amazonaws.com/spec.ccfc.min/img/hello/kernel/hello-vmlinux.bin
$ curl -fsSL -o hello-rootfs.ext4 https://s3.amazonaws.com/spec.ccfc.min/img/hello/fsfiles/hello-rootfs.ext4

最後に /dev/kvm へのアクセス権限を設定して準備作業は完了です。

$ sudo setfacl -m u:${USER}:rw /dev/kvm

詳細については、下記をご参照ください。

firecracker を動かしてみる

Firecracker を起動します。

$ ./firecracker --api-sock /tmp/firecracker.socket

別の端末を起動します。ガイドの記載を参考に、ゲストOS のカーネルやルートFS を設定します。

$ curl --unix-socket /tmp/firecracker.socket -i \
>     -X PUT 'http://localhost/boot-source'   \
>     -H 'Accept: application/json'           \
>     -H 'Content-Type: application/json'     \
>     -d '{        "kernel_image_path": "./hello-vmlinux.bin", "boot_args": "console=ttyS0 reboot=k panic=1 pci=off"    }'
HTTP/1.1 204 No Content
Date: Fri, 07 Dec 2018 00:43:18 GMT

$ curl --unix-socket /tmp/firecracker.socket -i \
>     -X PUT 'http://localhost/drives/rootfs' \
>     -H 'Accept: application/json'           \
>     -H 'Content-Type: application/json'     \
>     -d '{        "drive_id": "rootfs",        "path_on_host": "./hello-rootfs.ext4",        "is_root_device": true,        "is_read_only": false    }'
HTTP/1.1 204 No Content
Date: Fri, 07 Dec 2018 00:43:56 GMT

なお、2018/12/7 時点のビルドしたソースコードで、ガイドの記載の手順を実行した場合 下記のエラーがコンソールメッセージと共に出力されるようです。

2018-12-07T09:50:51.363657857 [:ERROR:vmm/src/lib.rs:1296] Failed to log metrics on timer trigger: Logger was not initialized.

そのため、下記の API を仮想マシンの起動前に実行し firecracker のログ設定を実施しておいた方が良いかと思われます。

$ touch /tmp/fc.log /tmp/fc.metrics
$ curl --unix-socket /tmp/firecracker.socket -i \
    -X PUT 'http://localhost/logger'   \
    -H 'Accept: application/json'           \
    -H 'Content-Type: application/json'     \
    -d '{ "log_fifo":"/tmp/fc.log", "metrics_fifo":"/tmp/fc.metrics","level":"Debug","show_level":true,"show_log_origin":true }'

では、仮想マシンを起動しましょう。

$ curl --unix-socket /tmp/firecracker.socket -i \
>     -X PUT 'http://localhost/actions'       \
>     -H  'Accept: application/json'          \
>     -H  'Content-Type: application/json'    \
>     -d '{ "action_type": "InstanceStart" }'
HTTP/1.1 204 No Content
Date: Fri, 07 Dec 2018 00:44:36 GMT

firecracker を起動した端末側に、ゲストOS のカーネル起動ログが表示された後にコンソールのログインプロンプトが出力されます。

$ ./firecracker --api-sock /tmp/firecracker.socket
[    0.000000] Linux version 4.14.55-84.37.amzn2.x86_64 (mockbuild@ip-10-0-1-79) (gcc version 7.3.1 20180303 (Red Hat 7.3.1-5) (GCC)) #1 SMP Wed Jul 25 18:47:15 UTC 2018
[    0.000000] Command line: console=ttyS0 reboot=k panic=1 pci=off  root=/dev/vda virtio_mmio.device=4K@0xd0000000:5
:
<略>
:
[    0.000000] Memory: 111064K/130680K available (8204K kernel code, 622K rwdata, 1464K rodata, 1268K init, 2820K bss, 19616K reserved, 0K cma-reserved)
:
<略>
:
[    0.224575] Freeing unused kernel memory: 1268K
[    0.232061] Write protecting the kernel read-only data: 12288k
[    0.235271] Freeing unused kernel memory: 2016K
[    0.238603] Freeing unused kernel memory: 584K
OpenRC init version 0.35.5.87b1ff59c1 starting
Starting sysinit runlevel

   OpenRC 0.35.5.87b1ff59c1 is starting up Linux 4.14.55-84.37.amzn2.x86_64 (x86_64)

 * Mounting /proc ...
 [ ok ]
 * Mounting /run ...
 * /run/openrc: creating directory
 * /run/lock: creating directory
 * /run/lock: correcting owner
 * Caching service dependencies ...
Service `hwdrivers' needs non existent service `dev'
 [ ok ]
Starting boot runlevel
 * Remounting devtmpfs on /dev ...
 [ ok ]
 * Mounting /dev/mqueue ...
 [ ok ]
 * Mounting /dev/pts ...
 [ ok ]
 * Mounting /dev/shm ...
 [ ok ]
 * Setting hostname ...
 [ ok ]
 * Checking local filesystems  ...
[    0.442520] random: fast init done
 [ ok ]
 * Remounting filesystems ...
 [ ok ]
 * Mounting local filesystems ...
 [ ok ]
 * Loading modules ...
modprobe: can't change directory to '/lib/modules': No such file or directory
modprobe: can't change directory to '/lib/modules': No such file or directory
 [ ok ]
 * Mounting misc binary format filesystem ...
 [ ok ]
 * Mounting /sys ...
 [ ok ]
 * Mounting security filesystem ...
 [ ok ]
 * Mounting debug filesystem ...
 [ ok ]
 * Mounting SELinux filesystem ...
 [ ok ]
 * Mounting persistent storage (pstore) filesystem ...
 [ ok ]
Starting default runlevel
[    1.152100] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x1872ef8535c, max_idle_ns: 440795255355 ns

Welcome to Alpine Linux 3.8
Kernel 4.14.55-84.37.amzn2.x86_64 on an x86_64 (ttyS0)

root ユーザ(パスワード root)で、ログインすればゲストOS が利用可能です。

localhost login: root
Password:
Welcome to Alpine!

The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <http://wiki.alpinelinux.org>.

You can setup the system with the command: setup-alpine

You may change this message by editing /etc/motd.

login[856]: root login on 'ttyS0'
localhost:~# cat /proc/cpuinfo
processor   : 0
vendor_id   : GenuineIntel
cpu family  : 6
model       : 58
model name  : Intel(R) Xeon(R) Processor
stepping    : 9
microcode   : 0x1
cpu MHz     : 1696.147
cache size  : 3072 KB
physical id : 0
siblings    : 1
core id     : 0
cpu cores   : 1
apicid      : 0
initial apicid  : 0
fpu     : yes
fpu_exception   : yes
cpuid level : 13
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid pni pclmulqdq vmx ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm cpuid_fault pti ssbd ibrs ibpb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust smep erms xsaveopt arat arch_capabilities
bugs        : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass
bogomips    : 3392.29
clflush size    : 64
cache_alignment : 64
address sizes   : 36 bits physical, 48 bits virtual
power management:
localhost:~# free -m
             total       used       free     shared    buffers     cached
Mem:           112         10        101          0          0          2
-/+ buffers/cache:          7        105
Swap:            0          0          0

CPU 情報を確認すると、Intel(R) Xeon(R) Processor と表示されていました。 また、ゲストOS 起動直後のメモリ使用量は、10MB 程度でした。(さすが、Alpine Linux)

さいごに

firecracker のログに出力されますが、ゲストの起動時間は 435ms と記録がありかなり早いなという印象。

2018-12-07T10:01:24.137570989 [anonymous-instance:WARN:vmm/src/lib.rs:931] Guest-boot-time = 434235 us 434 ms, 435923 CPU us 435 CPU ms

普段お世話になっている Lambda や ECS の基盤として動作している Firecracker を、オンプレ環境で気軽に検証できるのはかなり貴重な体験です。もし、興味があれば実際に試してみるのはいかがでしょうか。

ではでは