はやし雑記

はやしです

wasm (Rust) で素数の判定&計算するAPIサーバーを書いて、kubernetesのkrustletノード(wascc) で動かす

wasmシリーズ第二弾です

前回の続き

blog.hayashikun.com

今回はwasccのほうのruntimeを使う

wasiとwasccの違いはこちらに

krustlet/providers.md at master · deislabs/krustlet · GitHub

今回は、Rustとwasccで素数の判定&計算するAPIサーバーを書いて、k8sのkrustlet (wascc)のノードで動かすのを試した

結構大変でした

ソースコードはここ

github.com

Prime APIの実装

Rustで書いた

httpリクエストを受ける

  • /is_prime?<number>
  • /prime_less_than?<number>

の2種類のエンドポイントを用意する

クエリ文字列に指定した数が素数かどうか判別するものと、指定した数より小さい素数を返すものの2種類

krustlet-example/lib.rs at master · hayashikun/krustlet-example · GitHub

素数の判定はエラトステネスの篩でやった

targetはwasm32-unknown-unknownに設定する

krustlet-example/config at master · hayashikun/krustlet-example · GitHub

ただし、テストはtargetがwasmだと動かないので、別途指定する macなので、こんな感じ

$ cargo test --package prime-api --lib tests --target x86_64-apple-darwin

ビルドするとprime_api.wasmができる

$ cargo build --release
$ ls target/wasm32-unknown-unknown/release/
build/          deps/           examples/       incremental/    prime_api.d     prime_api.wasm

Container Registryにimageをpush

wasmをk8sからpullして動かすたためには、.wasmに署名して、コンテナイメージに変換し、AzureかGCPかどこかのRegistryにそのイメージをpushする必要がある

demoではjustfileに書いてやってるけど、今回はぽちぽちコマンドを打ってやっていく

署名はwascapnkeysを使う

GitHub - wasmCloud/wascap: Embed, extract, and validate capability claims in JWTs for WebAssembly modules

GitHub - wasmCloud/nkeys: Rust implementation of the NATS nkeys library

$ cargo install wascap --features "cli"
$ cargo install nkeys --features "cli"
$ mkdir .key
$ nk gen account > .key/account.txt && awk '/Seed/{ print $2 }' .key/account.txt > .key/account.nk
$ nk gen module > .key/module.txt && awk '/Seed/{ print $2 }' .key/module.txt > .key/module.nk
$ wascap sign target/wasm32-unknown-unknown/release/prime_api.wasm target/wasm32-unknown-unknown/release/prime_api_signed.wasm -i .key/account.nk -u .key/module.nk -s -f -l -n prime_api

署名したら、OCIへの変換とregistryへのpushはwasm-to-ociがやってくれる

wasm-to-ociのインストールはreleaseからダウンロードしてPATHの通ったところに置くだけ

github.com

今回はGCPのContainer Registryを使った

ずっとAWSのECRを使っていたが、どうもAWSはこのタイプのイメージはpushできないぽい?

AWSばっかりでGCPを使ったことが全然無かったので、google-clould-sdkの導入などからやった

wasm-to-ociでpushするためには、スタンドアロン認証情報ヘルパーを設定する必要がある

Authentication methods  |  Container Registry documentation

設定できたらpushする

$ wasm-to-oci push target/wasm32-unknown-unknown/release/prime_api_signed.wasm asia.gcr.io/<project_id>/krustlet-example/prime-api:v1
INFO[0012] Pushed: asia.gcr.io/<project_id>/krustlet-example/prime-api:v1 
INFO[0012] Size: 1739890                                
INFO[0012] Digest: sha256:076ca5272e98b95bb7d97027ae04f5ee84815aaa1cf4b7063fe716030ac19c31

hostはasia.gcr.ioにした <project_id>はProject IDを入れる

k8sで動かしてみる

$ kubectl apply -f prime-api-pod.yaml
$ kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
prime-api   0/1     Running   0          4s

8080で受けられるようにしているのでlocalhostにリクエストを投げれば

$ curl "localhost:8080/is_prime?2021"
{"is_prime":false}
$ curl "localhost:8080/is_prime?2017"
{"is_prime":true}
$ curl "localhost:8080/prime_less_than?100"
{"prime":[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]}

とJSONが返ってくる

わーい

イメージはpublicですがめちゃめちゃpullしたりしないでくださいね><

imagePullSecretsでprivateをpullするのはまだ無理ぽい?

最初はimageをprivateにしていたので、pullするためにsecretを作成してやってみた

まずjsonキーを作って

Authentication methods  |  Container Registry documentation

$ kubectl create secret docker-registry gcr-reg \
    --docker-server=asia.gcr.io \
    --docker-username=_json_key \
    --docker-email=<email> \
    --docker-password=$(cat path/to/key.json)

gcr-regという名前でsecretを追加

<email>にはService accountのemail

specに以下を追加

  imagePullSecrets:
    - name: gcr-reg

としてapplyしてみたけど、なんかうまくいかない

error decoding response body: missing field `detail` at line 1 column 159
    
    Caused by:
        missing field `detail` at line 1 column 159

みたいなエラーが出る

もうちょっと後で調べる