Rust製のKubelet，Krustletを触ってみる

# はじめに
[Microsoftから](https://cloudblogs.microsoft.com/opensource/2020/04/07/announcing-krustlet-kubernetes-rust-kubelet-webassembly-wasm/)KubeletをRustで実装した[Krustlet](https://github.com/deislabs/krustlet)が発表されました．
このKrustletは，コンテナではなく，WebAssemblyのランタイム機能を備えており，ネイティブでWebAsseblyのワークロードを実行することが可能です．
今回はこのKrustletを実際に手元で動かしてみようと思います．

# Krustletを動かす
## 環境
- macOS 10.15.4
- docker 19.4.0
- kind 0.8.1
- kubernetes 1.18.2
- Krustlet 0.1.0

## Krustletの準備
今回Kubernetesクラスタの構築には[kind](https://github.com/kubernetes-sigs/kind)を用います．

```
$ kind create cluster --name krustlet-demo
```

### 証明書
Krustlet，APIサーバ間の通信に必要な証明書を用意します．
まずは証明書署名要求(CSR)を発行します．

```bash
$ mkdir -p ~/.krustlet/config
$ cd ~/.krustlet/config
$ openssl req -new -sha256 -newkey rsa:2048 -keyout krustlet.key -out krustlet.csr -nodes -subj "/C=JP/ST=./L=./O=./OU=./CN=krustlet"
```

次に署名リクエストをapiサーバに投げます．

```bash
$ cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: krustlet
spec:
  request: $(cat krustlet.csr | base64 | tr -d '\n')
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF
```

署名リクエストを承認します．

```bash
$ kubectl certificate approve krustlet

# CONDITIONがApprovedになっていればOK
$ kubectl get csr
NAME        AGE    SIGNERNAME                                    REQUESTOR                                 CONDITION
csr-n42ts   48m    kubernetes.io/kube-apiserver-client-kubelet   system:node:krustlet-demo-control-plane   Approved,Issued
krustlet    3m7s   kubernetes.io/legacy-unknown                  kubernetes-admin                          Approved,Issued
```

証明書を取得しPFXファイルを生成します．

```bash
$ kubectl get csr krustlet -o jsonpath='{.status.certificate}' | base64 --decode > krustlet.crt
$ openssl pkcs12 -export -out certificate.pfx -inkey krustlet.key -in krustlet.crt -password "pass:<YourPassword>"
```

## Krustletをインストールする
[リリースページ](https://github.com/deislabs/krustlet/releases)から任意のファイルをダウンロードします．
解凍後，実行ファイルをパスの通った適当な場所に配置します．
なお0.1.0では`krustlet-wascc`使用時に必要なファイルを予め，`~/.krustlet/lib/`に配置する必要があります（この操作は0.2以降で必要なくなる予定です）．

```bash
$ mv krustlet-* /usr/local/bin/
$ mv lib/*.{so,dylib} $HOME/.krustlet/lib/
```

## Krustletを実行
今回，KrustletはホストOSで実行するため，`--node-ip`オプションを用いて`docker0`のIPを伝えます（`ip addr show docker0`で確認可能）．
なお，Docker Desktop for Macでは`docker0`は隠蔽されており，`en0`がコンテナからアクセス可能なため，このオプションは省略可能です．

```
$ krustlet-wasi --pfx-password <YourPassword>
```

Krustletが実行されたことを確認します．
`kubectl describe no <node_name>`で詳細を確認して通常のノードとの違いを見てみるのも面白いです

```bash
$ kubectl get no
NAME                          STATUS   ROLES    AGE   VERSION
krustlet-demo-control-plane   Ready    master   72m   v1.18.2
shanpu-mbp.local              Ready    agent    12s   v1.17.0

$ kubectl describe no shanpu-mbp.local
...<省略>
```

### デモ
最後に簡単なWebAssemblyワークロードを実行します．
デモの前にKrustletのリポジトリを手元にクローンしておいてください．

```bash
$ cd WHERE_TO_KRUSTLET_REPO
$ kubectl apply -f ./demos/wasi/greet/greet-wasi.yaml 

# 実行完了を確認後ログを見てみる
$  kubectl logs greet
Hello, world!
```

## 合わせて読みたい
- https://deislabs.io/posts/introducing-krustlet/

# 結び
今回はRust製KubeletのKrustletを触ってみました．
WebAssemblyをKubernetes上でネイティブで実行できる点，そしてGo以外の言語でKubernetesのコンポーネントを構築できることを証明してくれた点で，Krustletは非常に魅力的なソフトウェアだと感じています．
今現在はまだバージョンは0.1.0で，実用段階ではありませんが，今後の発展に注目したいです．

なおこちらは[あくあたん工房GWアドベントカレンダー7日目](https://gw-advent.9wick.com/calendars/2020/86)の記事でした．
よければ他の記事も見てみてください．


# 参考
- https://github.com/deislabs/krustlet/blob/master/docs/intro/README.md