Firecrackerつかいたい
本記事はwhywaita Advent Calendar 2019 16日目の記事です。
初めまして、uronです。 ちなみにwhywaita界隈ではかなり新入りです。ご容赦ください。
ちなみに概要にwaitawhyのすべらない話
と書いてありますが、whywaitとは少ししか被らない事もご容赦ください。
#0
自分は今年の4月からwhy君と仲良くさせて貰ってるんですが、彼のインフラチックなところがかなり好きですし尊敬してます。 なので、自分も見習わなきゃと自分なりに調べている所存であります。そんな事もありながら最近では彼の敵とも言える aws の海外カンファレンスに行って帰ってきてからの話。
このように治安の悪い話をしながらしたい事を語り合ってます。(雑談なんでご容赦を)
と言う事でFargate作ります!!!!!(作れません)
どうやらFargateはFirecrackerと言われる仮想化技術を使っているそうです。しかも最近ではfirecracker-containerdと呼ばれるコンテナランタイムを使っているらしいです。
仮想化とかコンテナとかはまあ詳しくはないんですが、触ってみたいなと言う事でwhy君のアドベントカレンダーを使わせていただきます。
Firecracker is 何
awsによって開発された、仮想化技術で、使用しないデバイスやゲスト向けの機能を排除して、起動や実行に必要なメモリー量と攻撃されそうな領域を減らす。それによってFirecrackerで作られたvmはセキュリティーが向上し起動時間も早くなり、ハードウェアの使用率が向上するらしいです。
起動が早くてセキュリティも考慮された小さいvmを立ち上げるものだと解釈してます。 起動・停止が早い分Fargateやlambdaのようにすぐスケールアウトしてすぐスケールインして欲しい用件があるサービスの基板にはいいんだろうなと思います。
firecracker-containerd is 何
continerdのコンテナランタイムとしてFirecracker microVMを管理できるようにするソフトウェアらしいです。
どう言う事かと言うと、
例えばkubernetesで podを作る時を考えると
- podとかを作る要求を僕らがする
- 高レベルランタイムに要求がくる
- 高レベルランタイムから低レベルランタイムに要求がくる
- 低レベルランタイムがコンテナを作る
のように動いているっぽいです。
webで例えるなら フロント(kubelet)があって、webサーバー(高レベルランタイム)に要求が行って、webサーバーから、データベース(低レベルランタイム)にクエリが投げられて、データベースが処理をしてデータを永続化する。自分はこのようになんとなく理解しています。
上記の話の高レベルランタイムに当たるのがcontainerdでFirecracker microVMは低レベルランタイムに当たるのかなと思います。
間違っていたら教えて!why君!
実際にコンテナ作ってみる
前提条件
Linux (4.14+), an Intel x86_64 processor and KVM enabled.
対応のマシン- git
- ルートファイルシステム
- Docker CE
- Go 1.11以降
マシンの用意
Linux (4.14+), an Intel x86_64 processor and KVM enabled.
対応のマシンを用意していきます。
優しいことにドキュメントには候補が書いてありました。
An i3.metal running Amazon Linux 2 is a good candidate.
EC2の普通のインスタンスはすでに仮想化されていてNested VMは許可されてないようなのでやはりベアメタルのインスタンスになるってことなんでしょうね。値段は高いですが少しの勉強の間ならまあ大丈夫です。
用意しました。ここからが勝負!
firecrackerが使えるか確認しましょう。
#!/bin/bash err=""; \ [ "$(uname) $(uname -m)" = "Linux x86_64" ] \ || err="ERROR: your system is not Linux x86_64."; \ [ -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. Firecracker is not well tested under nested virtualization."; \ [ -z "$err" ] && echo "Your system looks ready for Firecracker!" || echo -e "$err"
$ 上記のスクリプト.sh ERROR: /dev/kvm is innaccessible.
- kvmの有効化
$ sudo setfacl -m u:${USER}:rw /dev/kvm
$ 上記のスクリプト.sh Your system looks ready for Firecracker!
いけてそうですね。
Dockerとgoのインストールは省略します。
firecracker-containerdのセットアップ
カーネルのダウンロード
$ curl -fsSL -o hello-vmlinux.bin https://s3.amazonaws.com/spec.ccfc.min/img/hello/kernel/hello-vmlinux.bin $ ls hello-vmlinux.bin
firecrackerのセットアップ
- firecracker-containerdをクローンしてくるこの時Goのプロジェクトに準拠した場所に配置する
- セットアップ
$ git clone --recurse-submodules https://github.com/firecracker-microvm/firecracker-containerd $ GO111MODULE=on make all
- 以下の3つにPATHを通すかPATHの通ってるところに配置する
- runtime/containerd-shim-aws-firecracker
- firecracker-control/cmd/containerd/firecracker-containerd
- firecracker-control/cmd/containerd/firecracker-ctr
$ sudo make install
上記のコマンドでも可
firecrackerのビルド
$ make firecracker
- 以下の2つにPATHを通すかPATHの通ってるところに配置する
$ sudo make install-firecracker
上記のコマンドでも可
ルートファイルシステムのビルド
このリポジトリにはDebianベースのvm用のルートファイルシステムを構築するためのイメージビルダーコンポーネントが含まれてました。
$ make image $ sudo mkdir -p /var/lib/firecracker-containerd/runtime $ sudo cp tools/image-builder/rootfs.img /var/lib/firecracker-containerd/runtime/default-rootfs.img
firecracker-containerdバイナリの設定
disabled_plugins = ["cri"] root = "/var/lib/firecracker-containerd/containerd" state = "/run/firecracker-containerd" [grpc] address = "/run/firecracker-containerd/containerd.sock" [plugins] [plugins.devmapper] pool_name = "fc-dev-thinpool" base_image_size = "10GB" root_path = "/var/lib/firecracker-containerd/snapshotter/devmapper" [debug] level = "debug"
$ sudo mkdir -p /etc/firecracker-containerd $ sudo vim /etc/firecracker-containerd/config.toml 上記の設定を書く
snapshotterの準備と設定
- 指定されたスクリプトを実行
#!/bin/bash # Sets up a devicemapper thin pool with loop devices in # /var/lib/firecracker-containerd/snapshotter/devmapper set -ex DIR=/var/lib/firecracker-containerd/snapshotter/devmapper POOL=fc-dev-thinpool mkdir ${DIR} if [[ ! -f "${DIR}/data" ]]; then touch "${DIR}/data" truncate -s 100G "${DIR}/data" fi if [[ ! -f "${DIR}/metadata" ]]; then touch "${DIR}/metadata" truncate -s 2G "${DIR}/metadata" fi DATADEV="$(losetup --output NAME --noheadings --associated ${DIR}/data)" if [[ -z "${DATADEV}" ]]; then DATADEV="$(losetup --find --show ${DIR}/data)" fi METADEV="$(losetup --output NAME --noheadings --associated ${DIR}/metadata)" if [[ -z "${METADEV}" ]]; then METADEV="$(losetup --find --show ${DIR}/metadata)" fi SECTORSIZE=512 DATASIZE="$(blockdev --getsize64 -q ${DATADEV})" LENGTH_SECTORS=$(bc <<< "${DATASIZE}/${SECTORSIZE}") DATA_BLOCK_SIZE=128 # see https://www.kernel.org/doc/Documentation/device-mapper/thin-provisioning.txt LOW_WATER_MARK=32768 # picked arbitrarily THINP_TABLE="0 ${LENGTH_SECTORS} thin-pool ${METADEV} ${DATADEV} ${DATA_BLOCK_SIZE} ${LOW_WATER_MARK} 1 skip_block_zeroing" echo "${THINP_TABLE}" if ! $(dmsetup reload "${POOL}" --table "${THINP_TABLE}"); then dmsetup create "${POOL}" --table "${THINP_TABLE}" fi
containerd runtime pluginの設定
# /etc/containerd/firecracker-containerd.json # サンプル設定 { "firecracker_binary_path": "/usr/local/bin/firecracker", "kernel_image_path": "/var/lib/firecracker-containerd/runtime/hello-vmlinux.bin", "kernel_args": "console=ttyS0 noapic reboot=k panic=1 pci=off nomodules ro systemd.journald.forward_to_console systemd.unit=firecracker.target init=/sbin/overlay-init", "root_drive": "/var/lib/firecracker-containerd/runtime/default-rootfs.img", "cpu_template": "T2", "log_fifo": "fc-logs.fifo", "log_level": "Debug", "metrics_fifo": "fc-metrics.fifo" }
- kernel_image_pathで設定してあるのはダウンロードしてきたカーネルなので該当の場所に配置する
コンテナを立ち上げていく
default shim 用のディレクトリを作成
$ mkdir -p /var/lib/firecracker-containerd
containerdを起動
$ sudo PATH=$PATH /usr/local/bin/firecracker-containerd \ --config /etc/firecracker-containerd/config.toml
コンソールを一つ占有します
imageをpullしてきます
$ sudo firecracker-ctr --address /run/firecracker-containerd/containerd.sock images \ pull --snapshotter devmapper \ docker.io/library/busybox:latest
Dockerより可愛いですね。
実際にコンテナを起動
$ sudo firecracker-ctr --address /run/firecracker-containerd/containerd.sock \ run \ --snapshotter devmapper \ --runtime aws.firecracker \ --rm --tty --net-host \ docker.io/library/busybox:latest busybox-test
/ # cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 63 model name : Intel(R) Xeon(R) Processor @ 2.30GHz stepping : 2 microcode : 0x1 cpu MHz : 2300.006 cache size : 46080 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 syscall nx rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid smap xsaveopt arat arch_capabilities bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass bogomips : 4600.01 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management:
性能は上記の通り
コンテナ一覧
$ firecracker-ctr --address /run/firecracker-containerd/containerd.sock containers list CONTAINER IMAGE RUNTIME busybox-test docker.io/library/busybox:latest aws.firecracker
コンテナ削除
$ firecracker-ctr --address /run/firecracker-containerd/containerd.sock containers delete busybox-test
一通りの操作はできました。
ここまでかかった時間は1時間30分でした。課金もランチ1回分で抑えられて良かったです。それぐらいGetting Startはわかりやすかったです。
終わりに
触りはなんとなくわかってよかったです。Fargateに一歩近くこともできたかもしれません(?) 次はスケールアウト・イン機構をFirecrackerで作ってみたいです。
ここ最近で仮想化とかに興味が湧いてきたのでそのためにももっと基礎知識みたいなのは欲しいなと思いました。
why君に弟子入りでもしてみようかな。。。
明日はjoniy_joniyさんの尿酸値と痛風、私とwhywaita氏です。