論文紹介:Firecracker: Lightweight Virtualization for Serverless Applications

元論文:https://www.usenix.org/conference/nsdi20/presentation/agache

2018年末、AWS Lambdaを提供するためのシステムとしてFirecrackerという仮想マシンモニター(VMM)がオープンソースとして公開されて注目を集めました。

この論文は、その中身を解説・評価する論文です。

論文概要

USENIX協会主催のNSDIで発表されました。
USENIXはもともとはUnix User Groupという団体でしたが、現在はシステムやネットワーク、セキュリティなどの会議やワークショップを開催しています。
そのなかでもNSDIはネットワーク系の会議としてトップクラスの会議の1つです。
書いている人たちはAWSの中の人のようです。

AWS Lambdaとは、いわゆるサーバーレスコンピューティングといわれるサービスで、イベントの発生ごとに実行されるアプリケーションを設定しておくと、サーバーの設定無しでアプリケーションを実行して応答を返してくれる、というものです。
このアプリケーションを動かすのに使われているフレームワークで使われているのがFirecrackerです。

この論文ではFirecrackerのことをVMMと呼んでいますが、KVMやXenのような「VMM」ではありません。これはちょっと私も混乱したポイントなのですが、ここでのVMMとは各ゲストOSに対してのサンドボックスを提供するためのコンポーネントというような位置づけです。
KVMとQEMUの組み合わせでは、QEMUがこのVMMに相当します。
このブログではVMMをこの論文の使い方にそうように使いますが、私は普段はVMMという言葉をXenやKVMのようなフレームワークに対して使っている(ハイパーバイザと同義の意味で使っている)ので、他の記事とは使い方が異なることに注意してください。
ちなみにFirecrackerはRust製です。

背景・動機

AWS Lambdaをつくるにあたり、以下のような性質を持つ仮想化フレームワークが必要とされました

  • 独立性:複数の関数が同一のハードウェアで走ってもセキュアであること(互いに干渉したり、権限昇格のようなことが起きない)
  • オーバーヘッドと密度:たくさんの関数が同一ハードウェアで動かせるよう、少ないオーバーヘッドで動かせること
  • パフォーマンス:ネイティブ実行に近い速度が出せること
  • コンパチビリティ:任意のLinuxバイナリやライブラリがコード変更や再コンパイルなしで動かせること
  • 高速な切り替え:古い関数実行をクリーンアップし、新しい関数を実行が素早く行えること
  • ソフトアロケーション:CPUやメモリのオーバーコミットが可能なように、関数は必要なリソースしか使わないようにする

現状の類似した独立した環境を提供する既存のものとして、コンテナ・仮想化・言語のVMを使った独立化を挙げています。
Dockerでお馴染みのコンテナは、seccomp-bpfでシステムコールを制限するという形でセキュリティを担保してますが、200を超えるLinuxのシステムコールを制御しなければならず、Linuxのシステムコールのバグの危険性もあります。
Xenなどを使ったハードウェア仮想化は、ゲストOSに完全独立な仮想のCPUを与えるという方法ですが、カーネルまるまるを使うとスタートアップの時間がかかり、メモリのオーバーヘッドも大きいため、密度を上げることが難しいことで知られています。
また、仮想化のフレームワークそのもののコード量が多いことも問題です(trusted computing base、すなわちTCBが大きい)。
Java Virtual Machine(JVM)などの言語のVMは、言語や機能が限定されるため、これも条件を満たしません。

そこで、Firecrackerの取る方法は仮想化のアプローチをベースとしたものになっています。
有名なKVMとQEMUを使った仮想化ではQEMUが非常にコードの大きな部分を占めていて、これを減らすことができればTCBも減らすことができます。
FirecrackerではこのQEMUを置き換えるというものになっています。

Firecrackの構造

Firecrackerの設計方針として、既存のモジュールを再実装するのは基本的に避け、できる限りLinux内のコンポーネントを利用するというものがあります。
これは実装コストを下げるというのと、サービスを運用する際、Linuxの知識がそのまま使えるというものがあります。

FirecrackerはKVMのインフラに乗っかりつつ、QEMUに変わるVMMとして実装し、その上で小さな仮想マシン(MicroVM)を動かすという設計になっています。
VMMはChrome OSのVMMであるcrossvmをベースにコードを削ったりリファクタリングして、現在は完全に別物として実装されています。

Firecrackerはデバイスとして、ネットワークやディスクなどのブロックデバイス、シリアルポートとi8042(PS/2キーボードコントローラ)のみをサポートしています。
このうち、ネットワークドライバとブロックデバイスドライバはvirtioをそのまま使うことでコスト削減に貢献しています

Firecrackerのプロセスを操作するインターフェースとしてREST APIを提供しています。これなら様々な言語から操作することが用意で、それこそcurlなどのコマンドラインツールでも操作可能になるからです。

各VMの独立性を保つためには、プロセスごとのレートリミットをつける必要があります。Firecrackerでは1秒ごとのオペレーション数をAPIから設定することができます。

セキュリティのためのJailerというものも実装されています。これはFirecrackerそのものが使えるインターフェースを制限し、ゲストがVMMの脆弱性をつくことを難しくするためのものです。

評価

大量のVMを走らせるという実験を、QEMUと最近Intelが発表したRust製VMMであるCloud Hypervisorとの比較をおこなっています。

まず、起動時間です。QEMUよりかはパフォーマンスがいいのですが、Cloud Hypervisorには若干劣ります。一方で、メモリのオーバーヘッドはFirecrackerが3MB程度なのに対して、Cloud Hypervisorが13MBなので、こちらはFirecrackerに軍配が上がります。
次にIO性能ですが、実装がいろいろ足りていないため、QEMUにも負けている部分がいろいろあるようです。

さて、はじめに掲げた目標は達成できているでしょうか?

  • 独立性:仮想化を用い、サイドチャネルの対策もした
  • オーバーヘッドと密度:大量のVMを低いオーバーヘッドで動かせることを確認した
  • パフォーマンス:改善の余地はあるが、十分なパフォーマンスを達成
  • コンパチビリティ:変更していないLinuxカーネルを動かせた
  • 高速な切り替え:起動時間が十分に短い
  • ソフトアロケーション:20倍のオーバーサブスクリプションをテストしたが問題なし

ということで、全部満たしていそうです。

感想

仮想化フレームワークとしてUnikernelを以前紹介したが、こちらはよりコンパチビリティを意識したアプローチになっていている一方、きちんとVMの密度を上げられているというのは面白いと思いました。
KVMのフレームワークに詳しくなくVMMという単語の使い方に困惑しましたが、調べてみると結構こういう意味で使っている場合が多いようでややこしいですね…っg