Firecrackerの実装を眺めた感想

はじめに

f:id:ryotaway:20181220162340j:plain

こんにちは。 id:ryotaway です。プログラマをしています。

この記事は Misoca+弥生+ALTOA Advent Calendar 2018 - Qiita20日目の記事です。 昨日は naoki_hayashi さんの「AWS ECS+EFSでwordpressサイト構築 - 弥生開発者ブログ」でした。

昨日の記事でもAWSが登場していますが、AWSのサービスって便利ですよね! 仕事でも大変お世話になっています。

この記事ではAWSで作られたFirecrackerについて書きます。

Firecrackerとはなにか

Firecrackerとは、2018/11/27に AWS re:Invent 2018で発表されたOSSで、LambdaやFargateの基盤として開発されたマイクロ仮想マシンだそうです。詳細については、 FirecrackerGitHub - firecracker-microvm/firecracker: Secure and fast microVMs for serverless computing. などをご覧ください。

Firecrackerとは爆竹という意味ですが、束になってるやつではなく爆竹1つをイメージしているのかなと思います。 仮想マシンの起動からユーザーコードの実行、仮想マシン終了までのライフサイクルを短時間でパッと実行するイメージを表しているのかなと思ったので、なるほどずいぶんと格好いい名前だなぁという印象を持ちました。

実装について

FirecrackerはRustで書かれてます。Rustは新しめなシステムプログラミング言語で、所有権や借用などの概念も盛り込んだプログラミング言語です。詳細は Rust programming language などをどうぞ。

Rustのコードや仮想マシンの実装に馴染みのない人がFirecrackerの実装を読むのは大変だとは思うのですが、せっかくOSSになっているのですから、プログラマはみんな読んだらいいんじゃないかなと思ってます。得るものがあるのではないかな。

この記事では仮装マシンの実装に慣れていない人のために、Firecrackerの実装を説明していきます。

と意気込んだものの

コード量はそれほど多くないのですが、説明をブログに書くとなるとかなり長く読みにくい記事になってしまい、「余白が足りない」といいたくなる気持ちが湧いてきます。なので、この記事ではざっくりとディレクトリごとにどんな機能が入っているのかをくらいの軽い説明にとどめようと思います。

すでにFirecrackerの実装を読んだ人や仮想マシンの実装に慣れた人には「ディレクトリやファイルの名前を見ればわかるよ!」程度のことしか書きませんが、ご了承くださいませ。

なお、調査対象は Firecracker release v0.12.0 のコードとしています。 (この記事を書いている時点での最新版です)

GitHub - firecracker-microvm/firecracker: Secure and fast microVMs for serverless computing.


以下から説明開始です。

  • api_server
  • cpuid
    • 仮想CPUの情報があります
      • brand_string.rs とかを眺めると、 fn from_host_cpuid() が定義されていたりして、なるほどなぁって思えます
      • c3_template.rst2_template.rs というファイル名をみると、AWSだなぁという気持ちになれますね
        • 実装のほうはCPUのcpuid命令を知らないと何もわからないと思うので、検索してから実装を読むのがよいかと思います
  • devices
    • legacyとvirtioのサブディレクトリがあります
    • legacyはキーボードとシリアルポートの実装が入ってまして、なんとなく実装を眺めればわかるんじゃないかと思います
      • 仕様を知らない人は調べましょう
      • 全然たいしたことないことがわかるはずです
    • virtioはblockデバイス、メモリマップトIO、ネットなどがありますが、guest osとhost osの間でやりとりするときにvirtioを使う仮装デバイスの実装がここに置かれているようです
  • docs
    • 資料が入っているディレクトリなので説明は省略します
  • dumbo
    • ネットワーク系の実装が置かれています
      • pdu (protocol data unit)のディレクトリには、arpethernetipv4などの実装が置かれています
        • 見ればわかると思いますが、ipv6はありません
      • tcpディレクトリには、connectionなどがあり、ファイル名をみるだけで「ふーん」って思うこと請け合いです
  • fc_util
    • 時間関係のユーティリティが入ってます
      • 実装がすごく小さいので説明は省略します
  • jailer
    • jailerは非常に重要な立ち位置にいるアプリで、単独でdocs内に説明のmarkdownファイルが置かれています
    • ここの図 でわかるように、chrootやcgroupなど、コンテナ型の仮想化をおこなっています
    • プロダクション環境ではjailerからfirecrackerを呼ぶ事で、上記設計にあるような2重バリアを作ってるんですね
  • kernel
    • firecrackerは起動後、ネットワークを介してvmlinux.binの場所やパラメータを指定します
    • ここの実装では、受け取ったカーネルのイメージをメモリに展開したり、パラメータをvalidationしたりしているようです
    • 実装をちょっと眺めただけで深掘りしていないので間違ってたらごめんなさい
  • kvm
    • KVMで定義されている定数を、enumに再定義しているだけの実装があります
    • firecrackerはKVMを使ってます
    • だからコンテナではなくて仮想マシンなんですよね
  • kvm_gen
    • 自動生成されている実装のようですが、生成器を見た方が良さそうなので読んでません
  • logger
    • みたまんまロガーなので説明は省略します
  • memory_model
    • 実装がすごい簡素なので読んだらわかります
    • ゲストOSのアドレスをいじる実装が入ってます
  • micro_http
    • 名前のとおり、ちっちゃいhttpの実装がはいってます
      • common下にheaderの実装が入っていて、ここではContent-Typeとかのhttp headerを処理しています
      • このあたりはhttpのプロトコルがわかっていればスルッと理解できるはず
      • 知らない人はマスタリングTCP/IPとか読めばいいんじゃないですかね
  • mmds
    • コメントにThe Mmds is the Microvm Metadata Service represented as an untyped json. って説明があります
      • ここに限らず、コメントが結構書かれているので理解の手助けになりますね
    • 小さなデータストアです
    • 実装自体は100行くらいの小さいものなので読めばわかります
  • net_gen
    • 自動生成されている実装のようなので生成器の側を読みたい
    • なのでここは読んでません
  • net_util
    • macアドレスやtapを使って通信するための処理があります
    • 小さいユーティリティで読みやすいかなと思います
  • rate_limiter
    • token bucketを使って処理をブロックしたり解除したりすることでリミッタをかけるんだそうです(コメント読んだだけ)
    • へー、って感じです
    • ファイルを眺めた感じだと、コメントに振る舞いがいっぱい書いてあるので読んで理解するのはそんなに大変じゃなさそうです
    • コメントに ## limitation ってあるのが面白いですね
  • resources
    • microvm-kernel-configというファイルがあります
    • 単に自動生成されたコンフィグファイルですね
  • seccomp
    • システムコールを制限するためのフィルターを提供しています
    • seccompはたくさん情報がインターネット上にあがっているので、理解するにはそれらを先に読むのがいいかなと思います
  • src
    • main.rsがあります
    • ご存知?のとおり、一番上のレベルのメソッドなので、シーケンスを上から追いたい人はここから読むのがいいのかもしれません
  • sys_util
    • OS寄りな処理がはいってます
      • シグナルとかTTYとかioctlとかいろいろな実装が入ってますが、個々の要素はたいしたことない(と思う)ので、概念を知ってから読めばいいだけかなって思います。
      • 実装を眺めていたらpthreadがでてきたので、へー、って思いました
        • 今回の記事とは関係ないですが、macのHypervisor.FrameworkのAPIのドキュメントを読んでいた時もpthreadがでてきたので、ここでもかー、まぁそうだよなーって思っただけです
  • tests
    • テスト
  • tools
    • devtoolとか入ってるところです
    • devtoolはシェルスクリプトでした(最初はてっきりバイナリだと思ってました)
  • vhost_backend
    • なんですかね、これ
    • vsockがらみっぽいので、vsockと通信するためにhost側に用意するもの?うーん
  • vhost_gen
    • 省略
  • virtio_gen
    • 省略
  • vmm
    • microvmの本体! 間違い。vmmだからvirtual machine monitorでした
      • device_managerは、上で書いたlegacyやmmioのデバイスを管理するためのモジュールのようです
      • vmm_configには、いろいろな設定を処理するモジュールが入ってます
        • microvmの状態やエラーなんかの定義もここにはいってますね
      • 他にもシグナルのハンドラがあったりと、microvmを表現するためのモジュールの塊という印象でした
  • x86_64
    • 仮装CPUのレジスタの保存・復元や、ページテーブルの設定・読み書きなど、CPU周りの処理が入ってます
    • CPUの仕様を参照しながら読むのが良さそうです(けっして全ての仕様を理解してから実装を読もうとしないでください)
      • 本当にツライので

だいぶ駆け足になりました。 説明を書こうとしたら感想文になってしまったのですが、別の機会にちゃんとした説明を書こうと思いますのでご容赦を。

おわりに

f:id:ryotaway:20181220162336j:plain

Firecrackerの実装のさわりの説明というか、さっと眺めた感想を書きました。 なんか、簡単そうだな、という印象を受けてもらえると嬉しいなと思ってますがいかがでしたでしょうか。

この記事は Misoca+弥生+ALTOA Advent Calendar 2018 - Qiita20日目の記事でした。 明日は ucho_yayoi さんが「UWSCでデスクトップアプリの自動テスト」について書くそうです。自動テストいいですね。楽しみです。

それでは。