プラグイン実行エンジンとしてのWasm

# この文書は？

WebAssembly(Wasm)という名前を様々なところで目にしますが、まだあまり良く理解していないinajobが、プラグインシステムとしてWasmを利用することの利点について調査したものです。

# プラグインとしてのWasm

Wasmの発祥はブラウザでの高速なロジックの実行だったが、今ではその範疇を超えて様々な利用方法が生まれています。

この調査では、そんなWasmの利用例の一つであるプラグイン実行エンジンとしてのWasmに着目しました。

# 調査の手法

プラグイン実行エンジンとしてWasmを採用している著名なプロジェクトを列挙し、どのような背景でWasmをプラグイン実行エンジンとして導入したかを調べ、それらを俯瞰することで、Wasmのプラグイン実行エンジンとしての特徴をまとめます。

# 事例一覧

- Envoy
- kube-scheduler
- OPA

# EnvoyにおけるWasmプラグイン

- 参考: [Wasmで広がるEnvoyとIstioの世界
](https://speakerdeck.com/mathetake/wasmdeguang-garuenvoytoistiofalseshi-jie?slide=18)
- 設定にWASMバイナリのパスを書くことでプラグインとして組み込むことができる
    - network filter
        - https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/network_filters/wasm_filter.html
        ```yaml
        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
        ```
- このプラグインの仕様は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
    - ext_proc
        - 外部のプロセスとGRPCで連携する
            - 他の手法より遅い
                - 通信のオーバーヘッド
                - 通信のためにデータをシリアライズするオーバーヘッド
        - https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/ext_proc_filter
        - [わかりやすい説明の図](https://himenon.github.io/docs/envoyproxy/what-is-envoyproxy-external-processing/)
        - ![](https://himenon.github.io/assets/images/envoyproyx-ext-proc-52da94c81dbf5c97ccec0fb5bb8a9eb6.png)
    - Lua
        - Luaスクリプトでロジックを設定ファイルに記述する
            - 非ネイティブなのでそこまで早くない
            - この書き方からわかるように複雑なロジックを実装するものではない
        - https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/lua_filter
            ```yaml
            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
            ```


と、ここまで見たところで次の例に移ります

# kube-schedulerにおけるWasmプラグイン

- 参考
    - https://github.com/kubernetes-sigs/kube-scheduler-wasm-extension
    - [初心者でもわかるKubernetes Scheduler拡張の全てとその最前線
](https://speakerdeck.com/196ikuchil/chu-xin-zhe-demowakarukubernetes-schedulerkuo-zhang-noquan-tetosonozui-qian-xian)
- kube-schedulerの拡張方法はいくつかある
    - Extender
        - Webhook
        - リモートへの通信があるため遅い
    - Plugin
        - Goで実装、kube-schedulerの再コンパイルが必要
    - WebAssembly(WIP) ←これ
- パフォーマンスの比較(小さいほど早い)
    - 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
- Wasmにビルドする、とは？
    - 以下をくっつけたもの
        - C/C++で書かれたOPAのbuiltin functionsの実装をWasmにコンパイルしたもの
            - https://github.com/open-policy-agent/opa/tree/main/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点程度の優等生的な特徴を持っている手法なのかなと感じました。