この文書は?
WebAssembly(Wasm)という名前を様々なところで目にしますが、まだあまり良く理解していないinajobが、プラグインシステムとしてWasmを利用することの利点について調査したものです。
プラグインとしてのWasm
Wasmの発祥はブラウザでの高速なロジックの実行だったが、今ではその範疇を超えて様々な利用方法が生まれています。
この調査では、そんなWasmの利用例の一つであるプラグイン実行エンジンとしてのWasmに着目しました。
調査の手法
プラグイン実行エンジンとしてWasmを採用している著名なプロジェクトを列挙し、どのような背景でWasmをプラグイン実行エンジンとして導入したかを調べ、それらを俯瞰することで、Wasmのプラグイン実行エンジンとしての特徴をまとめます。
事例一覧
- Envoy
- kube-scheduler
- OPA
EnvoyにおけるWasmプラグイン
- 参考: Wasmで広がるEnvoyとIstioの世界
- 設定にWASMバイナリのパスを書くことでプラグインとして組み込むことができる
- network filter
- https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/network_filters/wasm_filter.html
name: envoy.filters.network.wasm typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm config: config: name: "my_plugin" vm_config: code: local: filename: "/etc/envoy_filter_http_wasm_example.wasm" allow_precompiled: true
- network filter
- このプラグインの仕様はProxy Wasmとして標準化されている
- https://github.com/proxy-wasm/spec
- 他のWebサーバでも利用しやすくなっている
- istio Proxy, ATS...
- Envoyには他にもプラグインの機構がある
- Pre built filters
- Envoyが予め備えているフィルタ
- C/C++で記述
- ロジックを変更した際は再ビルドが必要
- https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/http_filters
- Envoyが予め備えているフィルタ
- ext_proc
- 外部のプロセスとGRPCで連携する
- 他の手法より遅い
- 通信のオーバーヘッド
- 通信のためにデータをシリアライズするオーバーヘッド
- 他の手法より遅い
- https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/ext_proc_filter
- わかりやすい説明の図
- 外部のプロセスとGRPCで連携する
- Lua
- Luaスクリプトでロジックを設定ファイルに記述する
- 非ネイティブなのでそこまで早くない
- この書き方からわかるように複雑なロジックを実装するものではない
-
https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/lua_filter
name: envoy.filters.http.lua typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua default_source_code: inline_string: | -- Called on the request path. function envoy_on_request(request_handle) -- Do something. end -- Called on the response path. function envoy_on_response(response_handle) -- Do something. end
- Luaスクリプトでロジックを設定ファイルに記述する
- Pre built filters
と、ここまで見たところで次の例に移ります
kube-schedulerにおけるWasmプラグイン
- 参考
- kube-schedulerの拡張方法はいくつかある
- Extender
- Webhook
- リモートへの通信があるため遅い
- Plugin
- Goで実装、kube-schedulerの再コンパイルが必要
- WebAssembly(WIP) ←これ
- Extender
- パフォーマンスの比較(小さいほど早い)
- 1: Plugin
- 2: Wasm
- 10: Extender
- WasmはWebhookより早く、ネイティブのプラグインより手軽に利用できる特徴がありそうです
OPAにおけるWasm build
- 参考: https://www.openpolicyagent.org/docs/latest/wasm/
- Regoのポリシーを実行可能なWasmのモジュールにコンパイルする
-
opa build
でregoからwasmを出力できる
-
- この仕組みを使うと様々な言語にOPA(というかRego)のポリシーエンジンを注入できる
- 公式にはJavaScript SDKがある
- コミュニティベースで様々な環境用のSDKが整備されている
- OPAの組み込み方の比較
-
https://www.openpolicyagent.org/docs/latest/integration/#comparison
- REST API
- Go Lib
- Wasm
- 現実装で一番パフォーマンスが良いのはWasm
-
https://www.openpolicyagent.org/docs/latest/integration/#comparison
- Wasmにビルドする、とは?
- 以下をくっつけたもの
- C/C++で書かれたOPAのbuiltin functionsの実装をWasmにコンパイルしたもの
- Regoから生成したロジックをWasmにコンパイルしたもの
- 以下をくっつけたもの
3つの例から見えてきたプラグイン実行エンジンとしてのWasmの特徴
プラグインとは
あらためて、プラグインとはとは以下のような特徴を持つ仕組みです
- 利用者が簡単に拡張できる
- 本体アプリとの連携が可能
- 本体アプリの機能を呼び出す
- 本体アプリのイベントをプラグイン側Listenできる
- など
プラグインの様々な実現手法
ここまで見てきた例や、その他の世の中の例を踏まえると以下のような実現手法があります。
- 実行環境を組み込む
- Lua
- JVM
- (多分C# (
.NET
)とかもできる) - WASM
- DLL
- 外部サービスとの通信(RPC)
- GRPC
- REST API
プラグインに求められる要件
上で挙げた実現手法の中でわかりやすいものを✅,❌で記載しています
- (ホスト,プラグインともに)様々な言語で実装できる
- ❌Lua
- △ JVM (JVM言語もあるにはありますが・・)
- ✅Wasm
- プラットフォーム非依存
- ❌DLL
- ✅Wasm
- ネイティブ並みの速度で動作
- ❌Lua (Lua JITを使えば結構早くなるらしいですが)
- ✅DLL
- (そこそこ)Wasm
- 大容量のデータを高速で受け渡す
- ❌RPC
- ✅Wasm
- プラグインを安全に実行したい
- ❌DLL
- ✅Wasm
→ これらを いい感じ に満たすのがWasm
まとめ
Wasmをプラグインの仕組みとして利用している事例について、なぜWasmを採用したのかを調べました。
プラグインに求められる要件をいい感じにサポートしているということがわかった。
雰囲気としては、なにか100点満点の特徴が突出しているというよりは、どの教科も80点程度の優等生的な特徴を持っている手法なのかなと感じました。