WebAssemblyを実行するユニカーネルの構築 – その1

Exploring the Intersection of Unikernels and WebAssembly with Rust

タグ:Unikernel、WebAssembly、Rust、Spiderlightning、RustyHermit

最近のHackweek 22では、SUSEの従業員は自由にハックすることができました。これはSUSEで働く際の特典の一つです😎。今回の個人プロジェクトは、WebAssemblyを実行するUnikernelを構築することでした。このブログ記事では、この旅の詳細をすべて含めるつもりでしたが、1つの記事では情報量が多すぎると気づきました。そのため、すべてを小さなチャンクに分割することにしました。すべての投稿を追跡するために、このセクションを更新します。その間、POCのコードはこちらで見つけることができます。

私がそれを行った理由はいくつかありますが、プロジェクトの説明の中で書いたことを繰り返したくないだけです。学習と楽しさの目標は別として、UnikernelとWebAssemblyを組み合わせることには実際に良い理由があると思います。

アプリケーション開発者の視点から見ると、アプリケーションをUnikernelに移植/書き込むことは簡単な作業ではありません。アプリケーションとそのすべての依存関係は、ターゲットのUnikernelをサポートする必要があります。すべてのアプリケーションスタック内でパッチを当てることで、動作させるために必要な場合があります。

Unikernelメンテナの視点から見ると、彼らはユーザーアプリケーションがどのようなシステムプリミティブを利用するかわからないため、どの種類のアプリケーションでもシームレスに実行できるようにするためにかなりのエネルギーを費やす必要があります。

一方、WebAssemblyプラットフォーム(SpinやSpiderlightningなど)をターゲットにする場合、アプリケーションにはWebAssemblyランタイムによって提供される明確な機能セットがあります。

Spiderlightningのシナリオを見ると、アプリケーションはランタイム時にKey/Valueストアの機能を必要とするかもしれません。ただし、これらの機能がホスト側でどのように実装されているかはアプリケーションには関係ありません。つまり、同じ.wasmモジュールは、Redisを使用してK/Vストアを実装するランタイムやAzure Cosmos DBを使用して実装するランタイムで実行できます。

それはエンドユーザーアプリケーションにとって完全に透明です。

私が言いたいことが分かるかもしれません…

WebAssemblyモジュールを実行し、一連のSpiderlightning APIをサポートするUnikernelアプリケーションを書く場合、同じSpiderlightningアプリケーションは通常のslightランタイムとこのUnikernelの両方で実行できます。

アプリケーション開発者は追加の作業を行う必要はありません。Wasmモジュール自体はそれに気づくことさえありません。

複雑さはUnikernel開発者にのみかかりますが、彼らは明確な機能セットを実装する必要があります(「あらゆる種類のアプリケーションを動作させようとしてみましょう」とは異なります)。

以前、RustyHermitプロジェクトに出くわしました。これはRustで書かれたUnikernelです。私はそれを私のUnikernelアプリケーションを書くための基盤として使用することにしました。

RustyHermitアプリケーションの構築は非常に簡単です。ドキュメントは少し散在していますが、例が非常に役立ちます。クールなことは、RustyHermitがRustのナイトリーの一部であることです。これにより、開発者のエクスペリエンスが向上します。通常のRustアプリケーションを書いているような感覚です。

もちろん、すべての種類のRustクレートがRustyHermitで動作することを期待することはできません。それがPOCの開発にどのように影響を与えたかを見てみましょう。

次のセクションでは、先週の間に直面した主な課題について説明します。今後のブログ記事の中で詳細を共有します(ページの上部にある免責事項セクションを参照)。

残念ながら、私のお気に入りのWebAssemblyランタイムであるWasmtimeはRustyHermitの上でビルドされません。その多くの依存関係はlibcやその他の低レベルのライブラリを必要とします。

同様のことはwasmerにも当てはまります。

WebAssembly Micro Runtime(WAMR)のようなものを使用することも考えましたが、Rustで書かれたものを使用して「完全なRustyHermit体験」をしてみたかったので、それを選びました。

いくつかの検索の結果、純粋なRustのWebAssemblyランタイムであるwasmiを見つけました。これはRustyHermitの上でうまく動作します。さらに、その設計はWasmtimeの設計に触発されているため、以前の知識の多くを再利用することができました。

Spiderlightningは、WebAssemblyゲストに機能を提供し、ホストがWebAssemblyゲストが提供する機能を消費できるようにするために、WebAssemblyコンポーネントモデルの提案を活用しています。

ホストとゲストの間の通信は、Wasm Interface Typeで定義された型を使用して行われます。

具体的な例を挙げると、私が実行するデモでは、WebAssemblyコンポーネントモデルを次のように活用しています。

いくつかのWITタイプが関与しています。それぞれのために、ゲスト内部(基本的にはSDK)とホスト内部(ゲストSDKを実装するコード)の両方が必要です。

この場合、私はUnikernel内部でこれらのインターフェースのホスト側を実装するだけでした。

wit-bindgenというcliツールによって、.witファイルから生成されるホスト/ゲストコードを作成することができます。

この場合、私はUnikernel内部でこれらのインターフェースのホスト側を実装するだけでした。

wit-bindgenによって生成されるコードは、WebAssemblyランタイムを使用して低レベルの操作を行っています。生成するコードは、プログラミング言語とホスト側で使用されるWebAssemblyランタイムに依存します。

wit-bindgenは明らかにwasmi WebAssemblyランタイムをサポートしていませんでしたので、それを処理するためにwit-bindgenを拡張する必要がありました。コードは、このフォークのwasmiブランチ内で見つけることができます。

これらの準備が整ったら、Key/Valueの機能のホスト側を作成し、ホストの特性の簡単な実装を行いました。ホストコードは単にデバッグ情報を出力するだけでした。

その後、Spiderlightningプロジェクトのバニラキーバリューデモを実行することができました。🥳

この長い投稿の最後までたどり着いたあなたに、賞を差し上げたいと思います!以下は、Spiderlightningのhttp-serverデモを実行しているUnikernelアプリケーションの録画です。

読んでいただいてありがとうございました。次の旅のパートをお楽しみに。それでは、Rust async、Redis、そしていくつかの奇妙なエラーについて説明します。

注意

  • この記事はAI(gpt-3.5-turbo)によって自動生成されたものです。
  • この記事はHackerNewsに掲載された下記の記事を元に作成されています。
    Building a unikernel that runs WebAssembly – part 1
  • 自動生成された記事の内容に問題があると思われる場合にはコメント欄にてご連絡ください。

コメントする