Compute EngineのNested Virtualizationを使ってFirecrackerの開発環境を構築してみた
CX事業部@大阪の岩田です。
少し前に社内でこんなつぶやきをしていました。
re:invent初日の今日、本当に来ましたね。
Lambdaの基盤で利用されているVMMのFirecrackerは以前からスナップショット機能の開発が進んでいて、re:Invent 2019の時点で既にMicroVMを5ミリ秒で起動することに成功していました。Firecrackerの開発動向から考えるとある程度予想できた流れだったと言えるでしょう。
この発表をきっかけにFirecrackerのスナップショット機能を触ってみたい!という人が増えるかもしれないので、このブログではFirecrackerの開発環境構築手順についてご紹介します。
Firecrackerをどこで動かすか?
Firecrackerをなるべく手頃に試せる場所を探すでも紹介されているように、Firecrackerを動かす環境はいくつか候補が考えられます。この中でもお手頃に試せそうなのが、Nested Virtualizationを利用するという選択肢です。自前でハードを用意する必要がありませんし、ベアメタルインスタンスを利用するのに比べてお手軽な料金でFirecrackerを試すことができます。今回はnested virtualizationが利用可能なGoogle CloudのCompute Engine上にFirecrackerの開発環境を構築してみます。
Compute EngineでNested Virtualizationを有効化したインスタンスを起動する
まずはCompute Engineのマネジメントコンソールから「インスタンスを作成」をクリックし、諸々必要事項を入力していきましょう。今回は以下の設定で作成していきます。
- マシンタイプ: n2-standard-2
- CPUプラットフォーム: x86/64
- OS: Ubuntu 18.04 LTS
- ブートディスク: 40G
一通り入力できたら「作成」ではなく「同等のコマンドライン」をクリックします。
すると以下のようなコマンドがコピーできます。
gcloud compute instances create firecracker-dev-x86-64 --project=<プロジェクト名> --zone=asia-northeast2-a --machine-type=n2-standard-2 --network-interface=network-tier=PREMIUM,subnet=default --maintenance-policy=MIGRATE --provisioning-model=STANDARD --service-account=<プロジェクトNO>-compute@developer.gserviceaccount.com --scopes=https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/trace.append --create-disk=auto-delete=yes,boot=yes,device-name=firecracker-dev-x86-64,image=projects/ubuntu-os-cloud/global/images/ubuntu-1804-bionic-v20221125,mode=rw,size=40,type=projects/<プロジェクト名>/zones/asia-northeast2-a/diskTypes/pd-balanced --no-shielded-secure-boot --shielded-vtpm --shielded-integrity-monitoring --reservation-affinity=any
このコマンドの末尾にNested Virtualizationを有効化するためのオプション--enable-nested-virtualization
を付与して実行しましょう。最終的なコマンドは
gcloud compute instances create firecracker-dev-x86-64 --project=<プロジェクト名> --zone=asia-northeast2-a --machine-type=n2-standard-2 --network-interface=network-tier=PREMIUM,subnet=default --maintenance-policy=MIGRATE --provisioning-model=STANDARD --service-account=<プロジェクトNO>-compute@developer.gserviceaccount.com --scopes=https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/trace.append --create-disk=auto-delete=yes,boot=yes,device-name=firecracker-dev-x86-64,image=projects/ubuntu-os-cloud/global/images/ubuntu-1804-bionic-v20221125,mode=rw,size=40,type=projects/<プロジェクト名>/zones/asia-northeast2-a/diskTypes/pd-balanced --no-shielded-secure-boot --shielded-vtpm --shielded-integrity-monitoring --reservation-affinity=any --enable-nested-virtualization
のようになります。
コマンドが実行できたらしばらく待ってからSSH接続します。
gcloud compute ssh firecracker-dev-x86-64
以下のコマンドを実行し、0以外の値が出力されればNested Virtualizationが有効化されています。
grep -cw vmx /proc/cpuinfo 2
Firecrackerの開発環境を整える
インスタンスが起動したので、ここからはFirecrackerの開発に必要な環境を整えていきます。Firecrackerの開発に便利なDockerイメージ&Dockerfileが公開されるので、基本的にこのDockerイメージを利用していきます。
Dockerのインストール
まずはDockerのインストール
sudo apt-get update sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
ログインユーザーをdockerグループに追加してdockerコマンドを実行できるようにします。
sudo usermod -a -G docker $USER
一旦ログアウトしてから再度SSH 接続
exit Connection to xxx.xxx.xxx.xxx closed. gcloud compute ssh firecracker-dev-x86-64
sudo無しでdockerコマンドが叩けることを確認しておきます。
docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete Digest: sha256:faa03e786c97f07ef34423fccceeec2398ec8a5759259f94d99078f264e9d7af Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
ソースコードのClone
続いてFirecrackerのソースコードをCloneします
git clone https://github.com/firecracker-microvm/firecracker.git Cloning into 'firecracker'... remote: Enumerating objects: 38971, done. remote: Counting objects: 100% (327/327), done. remote: Compressing objects: 100% (234/234), done. remote: Total 38971 (delta 133), reused 235 (delta 91), pack-reused 38644 Receiving objects: 100% (38971/38971), 23.54 MiB | 24.35 MiB/s, done. Resolving deltas: 100% (24624/24624), done.
取得できたらディレクトリ内に移動しておきましょう
cd firecracker
開発用コンテナイメージのPULL
cloneしたリポジトリ内に含まれるDockerfileから開発用のコンテナイメージをビルドしても良いんですが、それなりに時間がかかるのでECR Publicで公開されているビルド済みイメージをPULLします。現時点ではv44のタグが最新なので、v44のタグを指定してPULLします。
docker pull public.ecr.aws/firecracker/fcuvm:v44 v44: Pulling from firecracker/fcuvm 726b8a513d66: Pull complete c902087c353a: Pull complete bd49ff15459a: Pull complete a19aa9ec83e7: Pull complete 4ca7e6d4b702: Pull complete 2116b4920242: Pull complete 4e88412695d9: Pull complete bc5294c03c96: Pull complete f88c91f9b95e: Pull complete aa0be5182a1d: Pull complete a9a3533f84b3: Pull complete 8317680728d5: Pull complete ad17528d5766: Pull complete a7d5eb0fa1b2: Pull complete 5a06dea846a3: Pull complete Digest: sha256:f92ff74d3de6b174dbec1cb53e71fe578ca881819f5ab244f046e7d6ba32d8c7 Status: Downloaded newer image for public.ecr.aws/firecracker/fcuvm:v44 public.ecr.aws/firecracker/fcuvm:v44
Firecrackerのビルド
これで必要な準備が整ったので、Firecrackerをビルドしてみましょう。以下のコマンドを実行すると、開発用のコンテナが起動しFirecrackerのバイナリのビルドがスタートします。
./tools/devtool build
warning: patch for `kvm-bindings` uses the features mechanism. default-features and features will not take effect because the patch dependency does not support this mechanism Updating git repository `https://github.com/firecracker-microvm/kvm-bindings` Updating git submodule `https://github.com/rust-vmm/rust-vmm-ci.git` Updating git repository `https://github.com/firecracker-microvm/micro-http` Updating git submodule `https://github.com/rust-vmm/rust-vmm-ci.git` Updating crates.io index Downloaded ryu v1.0.9 Downloaded proc-macro2 v1.0.36 Downloaded serde_derive v1.0.136 Downloaded syn v1.0.86 Downloaded unicode-xid v0.2.2 Downloaded itoa v1.0.1 Downloaded vmm-sys-util v0.11.0 Downloaded derive_more v0.99.17 Downloaded bincode v1.3.3 Downloaded serde v1.0.136 Downloaded quote v1.0.15 Downloaded libc v0.2.117 ...略 Compiling libc v0.2.117 Compiling serde v1.0.136 Compiling regex-syntax v0.6.25 Compiling jailer v1.1.0 (/firecracker/src/jailer) Compiling regex v1.5.5 Compiling vmm-sys-util v0.11.0 Compiling serde_derive v1.0.136 Compiling derive_more v0.99.17 Compiling utils v0.1.0 (/firecracker/src/utils) WARN rustc_codegen_ssa::back::link Linker does not support -static-pie command line option. Retrying with -static instead. Finished dev [unoptimized + debuginfo] target(s) in 20.80s
最終的にBuild successful.
と表示されればビルド完了です。
[Firecracker devtool] Build successful. [Firecracker devtool] Firecracker and Jailer binaries placed under /home/<ユーザー名>/firecracker/build/cargo_target/x86_64-unknown-linux-musl/debug [Firecracker devtool] Seccompiler-bin binary placed under /home/<ユーザー名>/firecracker/build/seccompiler/x86_64-unknown-linux-musl/debug [Firecracker devtool] Rebase_snap binary placed under /home/<ユーザー名>/firecracker/build/rebase-snap/x86_64-unknown-linux-musl/debug
スナップショットを作ってみる
これで一応Firecrackerの開発環境は構築できたんですが、せっかくなのでスナップショットを作ってみます。とりあえあずスナップショット作成を試すだけであれば、開発用のシェルスクリプトであるdevtoolのサブコマンドを実行するだけで簡単に試せるので、以下のコマンドで試してみましょう。
./tools/devtool create_snapshot_artifacts [Firecracker devtool] Creating snapshot artifacts ... Creating snapshot of microVM with kernel vmlinux-4.14.bin and disk ubuntu-18.04.ext4. Copied snapshot memory file, vmstate file, disk and ssh key to: snapshot_artifacts/4.14_None_guest_snapshot. Creating snapshot of microVM with kernel vmlinux-5.10.bin and disk ubuntu-18.04.ext4. Copied snapshot memory file, vmstate file, disk and ssh key to: snapshot_artifacts/5.10_None_guest_snapshot. Creating snapshot of microVM with kernel vmlinux-4.14.bin and disk ubuntu-18.04.ext4. Copied snapshot memory file, vmstate file, disk and ssh key to: snapshot_artifacts/4.14_C3_guest_snapshot. Creating snapshot of microVM with kernel vmlinux-5.10.bin and disk ubuntu-18.04.ext4.
snapshot_artifacts
ディレクトリ配下にMicroVMのスナップショットが作成されているので、このディレクトリを確認してみましょう。
ls -l snapshot_artifacts/4.14_C3_guest_snapshot/ total 1441832 -rw-r--r-- 1 root root 402653184 Nov 29 12:12 ubuntu-18.04.ext4 -rw-r--r-- 1 root root 1679 Nov 29 12:11 ubuntu-18.04.id_rsa -rw-r--r-- 1 root root 1073741824 Nov 29 12:11 vm.mem -rw-r--r-- 1 root root 28130 Nov 29 12:11 vm.vmstate
ファイル名から察するにubuntu-18.04.ext4
がディスクのイメージでubuntu-18.04.id_rsa
が秘密鍵、vm.mem
がMicroVMのメモリ、vm.vmstate
がMicroVMのステートを保持していると考えて良さそうです。
この辺りの詳細に興味があればFirecrackerのスナップショットに関するドキュメントを確認してみて下さい。試しにvm.vmstate
ファイルを少し覗いてみましょう。
strings snapshot_artifacts/4.14_C3_guest_snapshot/vm.vmstate vmlinux.bin console=ttyS0 reboot=k panic=1 pci=off GenuntelineI Intel(R) Xeon(R) Processor @ 2.8 0GHz @KVMKVMKVM :::::::::::::::: ZZZZZZZZZZZZZZZZ GenuntelineI Intel(R) Xeon(R) Processor @ 2.8 0GHz @KVMKVMKVM rootfs rootfs ubuntu-18.04.ext4 tap0 tap3 tap1 tap2 vsock /v.sock balloon
なにやら仮想ハードウェアの情報らしきものが垣間見えました。
まとめ
Firecrackerの開発環境構築手順をご紹介しました。思ったよりも簡単ですね。
スナップショット機能を試すだけならNested Virtualizationが有効なインスタンス上にFirecrackerのバイナリをDLするだけで試せるんですが、せっかくなんで開発環境を構築して色々と触ってみるのが楽しいと思います。目指せFirecrackerコントリビューター!!