Virtualization.framework

鈴ヶ嶺聡哲氏(以下、鈴ヶ嶺):ここまではmacOSの仮想化技術の変遷でしたが、ここから新しくVirtualization.frameworkが登場します。これは先ほども言いましたが、macOS 11 Big Surから追加された、VM作成の高レベルのAPIです。

Linux専用のAPIになっていて、kernelやinitrdを指定することで起動できます。これはHypervisor.frameworkとは違い、Intel MacとApple Siliconベースの両方のMac対応の抽象化されたAPIになっているので、簡単にLinux VMを作成可能です。

このようにConfigで保存できるものが、CPUやメモリ、あとはネットワークのドライバやソケットなどが対応しています。ネットワークに関しては、NATやV2 Networkが現状は対応可能です。

Docker Desktop for M1

2020年12月16日に発表されたプレビュー版のDocker、Docker Desktop for M1についてです。Apple Siliconでは、従来Intel Macで使われたhyperkitから、Virtualization.frameworkに移行しています。

Intel Macでも移行を検討しているような発言が、Dockerのロードマップのイシューのところにあがっています。今後hyperkitのサポートがどうなるのか、個人的にすごく気になります。

virtualization-rsの作成背景と中身

Rustのbindingで私が作成したvirtualization-rsの説明をします。Virtualization.frameworkのRust bindingを今回作成しました。Rustの特徴としては、モダンな型システムや、型推論、メモリ安全性、高速実行などいろいろあります。

Linux VMを作成する今回のようなシステムソフトウェアを書く言語として、非常に適しているのではないか、ということで作成しました。

中身の実装がどうなっているのか説明します。objcと呼ばれる、Objective-Cのオブジェクトが操作可能なRustのパッケージがあります。

Objective-Cはカッコでメッセージを飛ばすと思いますが、Rustでもマクロを使い、msgSendでメッセージを送る、Objective-CライクなAPIになっています。有名どころだと、Mac版ではservoもこのパッケージを使用して対応しています。

内部的な実装は、Objective-CのRuntimeという、dynamic libraryのC APIが存在しているので、このようにクラスがstructで定義されていたり、メッセージを飛ばすものが関数として用意されています。これをRustからCのAPIを叩いて、Objective-Cのobjectを操作するような内部実装になっています。

デモの概要

ここからデモに移ります。どのようにLinux VMを作成するか説明します。

cloud-initと呼ばれる、もともとAWSのEC2上で開発されていたインスタンスを、初期化するための標準仕様があります。このようにmeta-dataにhostnameやinstance-idを設定したり、user-dataにuserやpassword、sshするためのkeyなどを設定すると、それが初期化されたインスタンスが立ち上がる仕様があります。

その仕様の中に、ネットワークサービスを実行することなく初期化設定を可能とする、NoCloudがあって。meta-dataやuser-dataをisoに固めて、filesystemを介して渡すことでその設定が可能になります。今回はそれを使用していきたいと思います。

Linuxのイメージは、UbuntuのCloud imageと呼ばれる、常に最新のアップデートが適用されているLinuxのイメージを使ってやります。クラウドのインスタンスやDockerなどは、UbuntuのCloud imageが使われています。

NoCloudのisoの作成例です。chpasswdとすると、ここではrootのパスワードを変更したり、Ubuntuのパスワードをubuntuにする変更になっています。

meta-dataに関しては、このようにインスタンスのidをfoober0に設定したり、hostnameをfooberに設定して、isoに固めるようなコマンドを実行することで、NoCloudのisoが作成可能になります。

デモ動画

次にデモ動画に移りたいと思います。

(動画再生開始)

このようにGitHub上にあげたvirtualization-rsをダウンロードして、そこからwgetでCloud imageを落としていきます。

Cloud imageは、UbuntuのCloud imageなどと検索するとトップに出てきます。これをクリックすると、バージョンごとのUbuntuのCloud imageが出てくるので、20.04のものを選択します。currentを選択すると、それぞれのアーキテクチャごとのイメージがあります。

ここのファイルシステムイメージを落として、次にカーネルとinitrdを落とします。これらのパッケージはデイリーで常にビルドされているので、最新のものがすぐ手に入るようになっています。

このように、wgetで3つとも落とします。そして、tarでイメージを解凍します。もともとのサイズがちょっと小さいので、qemuのresizeを使ってイメージを11Gくらいに増やします。

次にuser-dataを作成して、ここではUbuntuのパスワードをubuntuに変更するような初期化をしたいと思います。meta-dataで、hostnameをfoobarに設定する設定をします。isoを作成します。

そしてパッケージをビルドします。重要なこととして、macOSはVirtualization.frameworkなどを使うときにentaitlementをバイナリに付与しないといけません。そのため、このようにxmlでentaitlementを作成して、コードサインでentaitlementを先ほど作ったバイナリに付与して、カーネルやディスクを指定して起動させます。そうするとLinux VMが立ち上がります。

しばらく経つと、cloud-initが起動して、ユーザーのパスワードが変更されます。この例だと標準出力をそのままシリアルでつないでいるので、パスワードが丸見えですが、ubuntuでログインできるようなデモになっています。

(動画再生終わり)

仮想化技術のベンチマーク計測

各種仮想化技術のベンチマークを最後にちょっと計測して終わりたいと思います。sysbenchを用いて素数を計算するCPUのベンチマークを、それぞれUbuntuの環境で、今回作成したvirtualization-rsと内部的にはhyperkitのものであるDockerと、内部的にはbinary translationのvirtualboxを比較しました。左側からvirtualization-rs、Docker、virtualboxになります。

同じような仮想化技術を使っているvirtualization-rsとDockerについては同等の結果が得られて、binary translationはそれより少し下がる結果が得られました。

以上をまとめると、macOS Big SurからLinux VMが作成可能な、高レベルAPIのVirtualization.frameworkが登場して、そのRust bindingsを今回作成しました。sysbenchなどによる検証結果から、従来のhyperkitなどと同程度の性能であることがわかりました。以上です。ありがとうございました。

質疑応答

司会者:鈴ヶ嶺さん、発表ありがとうございました。今回はRustでVirtualization.frameworkの呼べるものを作りましたが、苦労したところとかあります?

鈴ヶ嶺:最初、Objective-Cをどうやって呼ぶのかはちょっと苦労しました。すぐ叩けたりするのかなとかは、調べないといけなかった。それはちょっと苦労しましたね。

司会者:objcの使い方とか?

鈴ヶ嶺:そうですね。objcは内部的にどうなっているのか、まったくわからなかったので。調べていくうちに「あ、こういうふうに呼んでいるんだ」ってわかって、おもしろかったですね。

司会者:質問が来ています。「M1 Macでも動きますか?」と。

鈴ヶ嶺:僕はIntel Macしか持っていませんが、API的には共通なので、おそらく動くと思います。誰か確かめてみてください(笑)。

司会者:私、M1 Macなので、あとでちょっと試してみます。

鈴ヶ嶺:ありがとうございます(笑)。

司会者:Readmeにちゃんと書いてあるよね?

鈴ヶ嶺:すみません、書いていないです(笑)。

司会者:まじか(笑)。資料はこのあとアップロードすると聞いているので、もしほかにM1Macで試したい方は、資料を見て試せばいいと思っています。もし動かない場合は、プルリクのチャンスです。みなさんのプルリクをたぶん待っています。

鈴ヶ嶺:お願いします。ありがとうございます。

司会者:hyperkitはどうなるんだろうね?

鈴ヶ嶺:個人的にはどうなるのか、非常に気になるところですね。サポートしてくれなかったら、そのままHypervisor.frameworkなどをいじらなきゃいけなくなるので、ちょっと厳しい。なんとかなってほしいですね(笑)。

司会者:それでは鈴ヶ嶺さん、発表ありがとうございました。

鈴ヶ嶺:ありがとうございました。