LoginSignup
5
3

More than 3 years have passed since last update.

ARM (Raspberry pi 4) 上で Firecracker を動かしてみる

Last updated at Posted at 2020-05-10

初めに

ARM の仮想化支援機能に興味を持って Raspberry Pi 4 を買ったので、何か試したくなりました。
とりあえず何か動かせそうなものを探したら、Firecracker が一番簡単そうだったので試してみました。

参考にしたページ

この記事は基本的に下記ページの通りを参考にしました。
ほぼ手順通りにやっただけです。

ラズパイ4にFirecrackerの環境を構築してMicroVMを動かそう!!: https://dev.classmethod.jp/articles/firecracker-with-raspi4b/

上記記事は Firecracker のレポジトリにある Getting Started に沿っているようです。
本記事の本文中には適宜 Getting Started の該当箇所へのポインタを貼っていきます。

動作環境

  • Raspberry Pi: Raspberry Pi 4 Modeb B (4GB RAM)
  • Firecracker: v0.21.1
  • OS: Ubuntu 19.10
  • Linux kernel: ubuntu 5.3.0-1014-raspi2

Host OS の用意

現状 KVM が初めから有効になっている OS イメージは限られているようです。
(メジャーなディストリビューションである Raspbian は対応していませんでした)

今回は、 Ubuntu Wiki で公開されている Ubuntu server 19.10 のイメージを使います。
このイメージは KVM が有効になっています。
おそらくこれを使うのが今のところ一番簡単に KVM を試す方法じゃないかと思います。

上記イメージをダウンロードして, unxz で解凍したものを、SD カードに書き込み、Raspberry Pi 4 に差し込んで起動します。

Firecracker のバイナリ取得

Getting Started 該当箇所

Firecracker の latest release タグの情報を取得

latest=$(basename $(curl -fsSLI -o /dev/null -w  %{url_effective}  https://github.com/firecracker-microvm/firecracker/releases/latest))

このワンライナーは個人的に面白いと思ったので少し説明を加えてみます(KVM や Firecracker とは直接関係ないですが…)。
- curl -fsSLI -o /dev/null -w %{url_effective} <URL> でリダイレクト先の URL を取得
- basename でURL のファイルパスの最下層の文字列を取得 (これ URL でも動くんですね)

あとは、以下の通りコマンドを実行し, firecracker コマンドを準備します。

curl -LOJ https://github.com/firecracker-microvm/firecracker/releases/download/${latest}/firecracker-${latest}-$(uname -m)
mv firecracker-${latest}-$(uname -m) firecracker
sudo chmod +x firecracker

ACL の設定

Getting Started 該当箇所

/dev/kvm にアクセスできるよう拡張 ACL の設定を行います。

まず、ACL の設定に必要なコマンドのインストール

sudo apt install acl

設定を変更する前に、一度 ACL の設定を確認してみます。

deep@ubuntu:~$ sudo getfacl /dev/kvm
getfacl: Removing leading '/' from absolute path names
# file: dev/kvm
# owner: root
# group: kvm
user::rw-
group::rw-
other::---

/dev/kvm へアクセスできるように権限を追加します。

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

設定の変更を確認してみます。

deep@ubuntu:~$ sudo getfacl /dev/kvm
getfacl: Removing leading '/' from absolute path names
# file: dev/kvm
# owner: root
# group: kvm
user::rw-
user:deep:rw-
group::rw-
mask::rw-
other::---

システム要件の確認

Getting Started 該当箇所
(Click here to see a BASH script that will check if your system meets the basic requirements to run Firecracker. を押すと表示される)

以下のスクリプトを実行することで、 Firecracker を実行するための要件を満たしているか否かをチェックできます。
Your system looks ready for Firecracker! と表示されれば OK です。


    err="";
    [ "$(uname) $(uname -m)" = "Linux x86_64" ]  \
        || [ "$(uname) $(uname -m)" = "Linux aarch64" ] \
        || err="ERROR: your system is not Linux x86_64 or Linux aarch64."; \
        [ -r /dev/kvm ] && [ -w /dev/kvm ] \
            || err="$err\nERROR: /dev/kvm is innaccessible."; \
        (( $(uname -r | cut -d. -f1)*1000 + $(uname -r | cut -d. -f2) >= 4014 )) \
            || err="$err\nERROR: your kernel version ($(uname -r)) is too old."; \
        dmesg | grep -i "hypervisor detected" \
            && echo "WARNING: you are running in a virtual machine." \
            && echo "Firecracker is not well tested under nested virtualization."; \
        [ -z "$err" ] && echo "Your system looks ready for Firecracker!" || echo -e "$err"

サンプルイメージの取得

Getting Started 該当箇所
(get the kernel and rootfs, if you don't have any available: のコードブロック)

下記スクリプトを実行すると、Firecracker 上で動作するサンプルイメージを取得できます。


    arch=`uname -m`
    dest_kernel="hello-vmlinux.bin"
    dest_rootfs="hello-rootfs.ext4"
    image_bucket_url="https://s3.amazonaws.com/spec.ccfc.min/img"

    if [ ${arch} = "x86_64" ]; then
            kernel="${image_bucket_url}/hello/kernel/hello-vmlinux.bin"
            rootfs="${image_bucket_url}/hello/fsfiles/hello-rootfs.ext4"
    elif [ ${arch} = "aarch64" ]; then
            kernel="${image_bucket_url}/aarch64/ubuntu_with_ssh/kernel/vmlinux.bin"
            rootfs="${image_bucket_url}/aarch64/ubuntu_with_ssh/fsfiles/xenial.rootfs.ext4"
    else
            echo "Cannot run firecracker on $arch architecture!"
            exit 1
    fi

    echo "Downloading $kernel..."
    curl -fsSL -o $dest_kernel $kernel

    echo "Downloading $rootfs..."
    curl -fsSL -o $dest_rootfs $rootfs

    echo "Saved kernel file to $dest_kernel and root block device to $dest_rootfs."

ちなみに、ダウンロードしたファイルのサイズは以下の通りでした。

deep@ubuntu:~$ ls -lh | grep hello
-rw-rw-r-- 1 deep deep 200M May 10 05:04 hello-rootfs.ext4
-rw-rw-r-- 1 deep deep 8.2M May 10 05:02 hello-vmlinux.bin

Firecracker 起動

Getting Started 該当箇所

Firecracker を起動します。非常に単純なコマンドですね。

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

このコマンドを実行すると、次に述べる API コールを待つ状態になります。

API 呼び出しによる MicroVM の起動

Getting Started 該当箇所
set the guest kernel (assuming you are in the same directory as the above script was run) および
set the guest rootfs のコードブロック

Firecracker は ソケット越しに API を呼び出すことで VM を起動できるようです。
下記手順を別コンソールで行います。

カーネルをロードするための API コール


    arch=`uname -m`
    kernel_path=$(pwd)"/hello-vmlinux.bin"

    if [ ${arch} = "x86_64" ]; then
      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\": \"${kernel_path}\",
                \"boot_args\": \"console=ttyS0 reboot=k panic=1 pci=off\"
           }"
    elif [ ${arch} = "aarch64" ]; then
        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\": \"${kernel_path}\",
                \"boot_args\": \"keep_bootcon console=ttyS0 reboot=k panic=1 pci=off\"
           }"
    else
        echo "Cannot run firecracker on $arch architecture!"
        exit 1
    fi

rootfs をロードするための API コール


    rootfs_path=$(pwd)"/hello-rootfs.ext4"
    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\": \"${rootfs_path}\",
            \"is_root_device\": true,
            \"is_read_only\": false
       }"

Guest 起動のための API コール

    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"
       }'

上記 3つの API コールを実行すると、 ./firecracker を実行したコンソールで Guest の起動ログやログインシェルが見れるようになるはずです。

perf で kvm のイベントとる

最後に、ちゃんと KVM が動いているのか確認してみたかったので、 perf コマンドで kvm のイベント回数を表示してみました。
(これがこの記事唯一の新規ポイントです。)

perf コマンドのインストール

sudo apt install linux-tools-common
sudo apt install linux-tools-5.3.0-1014-raspi2

kvm 関連のイベントを取得、表示

sudo perf stat -e 'kvm:*'  -a sleep 1

結果は以下の通りでした。
ちなみに、ゲストで何も負荷をかけないと何もイベント起きなかったので、適当なコマンドを実行しながら測るといいと思います。

deep@ubuntu:~/firecracker_ws$ sudo perf stat -e 'kvm:*'  -a sleep 1
libtraceevent: No such file or directory
  [kvm:kvm_sys_access] bad op token :

 Performance counter stats for 'system wide':

               118      kvm:vgic_update_irq_pending
                 3      kvm:kvm_wfx_arm64
                 0      kvm:kvm_hvc_arm64
                60      kvm:kvm_arm_setup_debug
                60      kvm:kvm_arm_clear_debug
               120      kvm:kvm_arm_set_dreg32
                 0      kvm:kvm_arm_set_regset
                 0      kvm:trap_reg
                 0      kvm:kvm_handle_sys_reg
                 0      kvm:kvm_sys_access
                 0      kvm:kvm_set_guest_debug
                60      kvm:kvm_entry
                60      kvm:kvm_exit
                51      kvm:kvm_guest_fault
                 0      kvm:kvm_access_fault
                 0      kvm:kvm_irq_line
                 0      kvm:kvm_mmio_emulate
                 0      kvm:kvm_unmap_hva_range
                 0      kvm:kvm_set_spte_hva
                 0      kvm:kvm_age_hva
                 0      kvm:kvm_test_age_hva
                 0      kvm:kvm_set_way_flush
                 0      kvm:kvm_toggle_cache
                58      kvm:kvm_timer_update_irq
               120      kvm:kvm_get_timer_map
                56      kvm:kvm_timer_save_state
                56      kvm:kvm_timer_restore_state
                 0      kvm:kvm_timer_hrtimer_expire
                56      kvm:kvm_timer_emulate
                51      kvm:kvm_userspace_exit
                 3      kvm:kvm_vcpu_wakeup
                60      kvm:kvm_set_irq
                 0      kvm:kvm_ack_irq
                66      kvm:kvm_mmio
                 0      kvm:kvm_fpu
                 0      kvm:kvm_age_page
                 0      kvm:kvm_halt_poll_ns

       1.005360291 seconds time elapsed

おわりに

今回は ARM で動く VMM として Firecracker を試してみました。
KVM が有効な OS とサンプルの VM イメージが手に入るので簡単に試すことができました。
今後は自分で ARM の仮想化支援機能に触れてみたいところです。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3