Mewz (WebAssembly x Unikernel) を libkrun で動かしてみた - 外部記憶装置 の詳細を記すシリーズ
- その1 libkrun を試す ← この記事
- その2 libkrun の構造
- その3 Mewz 追加実装(Linux zeropage, kernel cmd params)
- その4 Mewz 追加実装(Virtio MMIO)
- その5 Mewz on libkrun してみた
- その6 Mewz 追加実装(virtio-console)
- その7 virtio-vsock について
- その8 Mewz 追加実装(virtio-vsock)
- その9 TSI の仕組み
目次
libkrun とは
libkrun は RedHat のエンジニアである Sergio López 氏によって開発されている、コンテナ向けのVMMである。
VMM としては QEMU が代表例として知られているが、 QEMU はコンテナ向けに利用するにはフットプリントが大きく、コンテナ向けとしては扱いにくい問題がある。 そういった点を踏まえ、libkrun は、コンテナ向けにカスタマイズされた専用の Linux カーネルを動かすために必要最低限な仮想デバイスのみ提供するシンプルなVMMとして設計されている。 Kubernetes 等のコンテナオーケストレーションシステムと合わせて利用されることも想定され、ホストの Network Namespace 経由で通信するための passt との統合や、TSI と呼ばれる virtio-vsock を用いて通信する仕組みを持つ。
libkrun 自体はその名のとおり共有ライブラリとして提供され、CAPI経由で呼び出すことができるため、crun などの既存のコンテナソフトウェアと組み合わせやすいという特徴を持つ。
専用の Linux カーネルについても libkrunfw という共有ライブラリとして提供されている。 実体としては、Linux カーネル全体が配列として定義され、CAPI経由でエントリアドレスやバイナリ自体が提供される仕組みとなっている。
詳細については以下の記事にて詳しく解説されている。
libkrun をビルドする
libkrun のビルドには Rust ツールチェインが必要であるため、あらかじめインストールしておく。
$ rustc --version rustc 1.82.0 (f6e511eec 2024-10-15)
libkrunfw のビルド
まず、libkrunfw をビルド、インストールする。Linux kernel も同時にビルドされるため、必要なパッケージ群をインストールしておく。
$ sudo apt install libncurses-dev gawk flex bison openssl libssl-dev libelf-dev autoconf python3-pyelftools $ git clone https://github.com/containers/libkrunfw $ cd libkrunfw $ mkdir build $ make -j $(nproc) $ DESTDIR=./build make install
kernel のビルドが走るため、暫く待つ。ビルドに成功すると、libkrunfw.so.4.6.0
という共有ライブラリが生成される。
$ ls -l build/usr/local/lib64/ total 19204 lrwxrwxrwx 1 naoki naoki 14 Dec 28 17:22 libkrunfw.so -> libkrunfw.so.4 lrwxrwxrwx 1 naoki naoki 18 Dec 28 17:22 libkrunfw.so.4 -> libkrunfw.so.4.6.0 -rwxr-xr-x 1 naoki naoki 19662520 Dec 28 17:22 libkrunfw.so.4.6.0
libkrun のビルド
次に、libkrun をビルドする。patchelf
が必要なため、これもインストールしておく。
$ sudo apt install patchelf $ git clone https://github.com/containers/libkrun $ cd libkrun
libkrunfw.so
を通常とは異なるパスにインストールしたため、rustc の探索パスに上記のパスを追加しておく。
diff --git a/src/libkrun/build.rs b/src/libkrun/build.rs index a3ccc22..7e78f2d 100644 --- a/src/libkrun/build.rs +++ b/src/libkrun/build.rs @@ -1,4 +1,6 @@ fn main() { + println!("cargo:rustc-link-search=../libkrunfw/build/usr/local/lib64"); + #[cfg(target_os = "macos")] println!("cargo:rustc-link-lib=framework=Hypervisor"); #[cfg(target_os = "macos")]
今回はネットワーク機能を利用するために NET=1
をオプションに追記してビルドする。
なお、オプションとしてはブロックデバイス(virtio-blk
) を有効化するBLK=1
なども存在する。
$ make NET=1 $ ls -l target/release/libkrun.so -rwxr-xr-x 2 naoki naoki 3712296 Dec 28 17:28 target/release/libkrun.so
ビルドに成功すると、libkrun.so
が得られる。
libkrun では、この共有ライブラリを呼び出す形で利用する。
そのため、libkrun を利用するためには自分で呼び出すコードを書く必要があるが、今回はexamples
に含まれるchroot_vm
を利用する。
一旦共有ライブラリをまとめ、examples/Makefile
に共有ライブラリの探索パスを追加する。
$ cp -r ../libkrunfw/build/usr/local/lib64 lib $ cp target/release/libkrun.so* lib/.
diff --git a/examples/Makefile b/examples/Makefile index 8c16305..4059676 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,6 +1,6 @@ ARCH = $(shell uname -m) OS = $(shell uname -s) -LDFLAGS_x86_64_Linux = -lkrun +LDFLAGS_x86_64_Linux = -lkrun -L../lib -Wl,-rpath-link,../lib LDFLAGS_aarch64_Linux = -lkrun LDFLAGS_arm64_Darwin = -L/opt/homebrew/lib -lkrun LDFLAGS_sev = -lkrun-sev
ビルドし、LD_LIBRARY_PATH
で共有ライブラリを配置したディレクトリを指定して実行する。
$ make $ LD_LIBRARY_PATH=../lib ./chroot_vm Missing COMMAND argument Missing NEWROOT argument Usage: ./chroot_vm [OPTIONS] NEWROOT COMMAND [COMMAND_ARGS...] OPTIONS: -h --help Show help --net=NET_MODE Set network mode --passt-socket=PATH Instead of starting passt, connect to passt socket at PATHNET_MODE can be either TSI (default) or PASST NEWROOT: the root directory of the vm COMMAND: the command you want to execute in the vm COMMAND_ARGS: arguments of COMMAND
rootfs の作成
最後に、libkrun で利用する rootfs を作成する。podman を利用した rootfs 作成用のコマンドが用意されているため、それを利用する。
$ sudo apt install podman $ make rootfs $ ls -l ... drwxr-xr-x 18 naoki naoki 4096 Dec 28 17:49 rootfs_fedora ...
libkrun を動かす
rootfs として rootfs_fedora
が作成されるため、それを利用して chroot_vm
を実行する。
なお、/dev/kvm
を利用するため、通常は sudo
で起動する必要がある。
$ sudo LD_LIBRARY_PATH=../lib ./chroot_vm ./rootfs_fedora /bin/sh sh-5.2# uname -a Linux localhost 6.6.63 #1 SMP PREEMPT_DYNAMIC Mon Dec 2 11:39:28 CET 2024 x86_64 GNU/Linux sh-5.2# echo "nameserver 8.8.8.8" > /etc/resolv.conf sh-5.2# curl example.com <!doctype html> <html> <head> <title>Example Domain</title> <meta charset="utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <style type="text/css"> ...
ネットワーク機能付きでビルドしたため、外部のウェブサイトにもアクセス可能であることがわかる。
まとめ
今回の記事では、 libkrun のビルドから実際に動作させるまでをまとめた。 次の記事では libkrun の内部をまとめる。