<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>rust | 伪架构师</title>
    <link>/tags/rust/</link>
      <atom:link href="/tags/rust/index.xml" rel="self" type="application/rss+xml" />
    <description>rust</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Tue, 14 Apr 2020 12:42:59 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>rust</title>
      <link>/tags/rust/</link>
    </image>
    
    <item>
      <title>在 Kubernetes 上用 Krustlet 调度 WASM</title>
      <link>/post/wasm-node-on-k8s/</link>
      <pubDate>Tue, 14 Apr 2020 12:42:59 +0800</pubDate>
      <guid>/post/wasm-node-on-k8s/</guid>
      <description>

&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;

&lt;p&gt;坊间有两个传言：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes 正在成长为一个统一调度器&lt;/li&gt;
&lt;li&gt;WASM 如果早点成气候，就没 Docker 什么事了&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/deislabs/krustlet&#34; target=&#34;_blank&#34;&gt;Krustlet&lt;/a&gt; 往前踏了一小步：他的官方描述是“Kubernetes Kubelet in Rust for running WASM”——使用 Rust 实现的 Kubelet，可以在 Kubernetes 中运行 WASM。&lt;/p&gt;

&lt;p&gt;Krustlet 是 Deis 实验室的产品，算是 Helm 的同门师兄弟。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;项目还非常初期，包括镜像拉取、Pod 生命周期等功能都没能完整实现，只能作为一个概念方面的尝试。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;部署&#34;&gt;部署&lt;/h2&gt;

&lt;p&gt;官方提供了 EKS、AKS 以及 Kind 的部署方案，这里我们使用 Kind 进行部署。使用如下配置文件定义一个三节点集群：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kind create cluster --config=config-3-node.yaml
Creating cluster &amp;quot;kind&amp;quot; ...
 ✓ Ensuring node image (kindest/node:v1.17.0) 🖼
 ✓ Preparing nodes 📦 📦 📦 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;集群启动之后，就可以安装 Krustlet 了。&lt;/p&gt;

&lt;p&gt;踩坑过程中，注意到 Krustlet 的几个依赖项目：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Openssl 1.1.x 支持，所以有些老系统可能需要升级；&lt;/li&gt;
&lt;li&gt;接入 Krustlet 时，需要满足接入新节点的 Kubernetes 权限要求；&lt;/li&gt;
&lt;li&gt;Krustlet 和 Kubelet 一样，也要使用 kubeconfig 文件进行认证。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在 &lt;a href=&#34;https://github.com/deislabs/krustlet/releases/&#34; target=&#34;_blank&#34;&gt;Release 页面&lt;/a&gt;可能找到压缩包下载，目前支持 Linux 和 MacOS 两个平台。&lt;/p&gt;

&lt;p&gt;解压之后，创建 &lt;code&gt;~/.krustlet/lib&lt;/code&gt; 目录，将压缩包中的 &lt;code&gt;*.so&lt;/code&gt; 和 &lt;code&gt;*.dylib&lt;/code&gt; 复制到 &lt;code&gt;~/.krustlet/lib&lt;/code&gt; 之中，可执行文件复制到 &lt;code&gt;/usr/local/bin&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;接下来为 krustlet 准备用于加入 Kubernetes 的证书：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/sh
mkdir -p ~/.krustlet/config
cd ~/.krustlet/config
openssl req -new -sha256 -newkey rsa:2048 -keyout krustlet.key -out krustlet.csr -days 365 -nodes -subj &amp;quot;/C=US/ST=./L=./O=./OU=./CN=krustlet&amp;quot;
cat &amp;lt;&amp;lt;EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: krustlet
spec:
  request: $(cat krustlet.csr | base64 | tr -d &#39;\n&#39;)
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF
kubectl certificate approve krustlet
kubectl get csr krustlet -o jsonpath=&#39;{.status.certificate}&#39; | base64 --decode &amp;gt; krustlet.crt
openssl pkcs12 -export -out certificate.pfx -inkey krustlet.key -in krustlet.crt -password &amp;quot;pass:password&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;启动&#34;&gt;启动&lt;/h2&gt;

&lt;p&gt;启动过程很简单：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ krustlet-wasi  --pfx-password password --node-ip 10.89.81.61
[2020-04-14T06:16:34Z ERROR kubelet::kubelet] Error handling event: error decoding response body: missing field `access_token` at line 1 column 501
[2020-04-14T06:18:04Z ERROR kubelet::kubelet] Error handling event: error decoding response body: missing field `detail` at line 1 column 119
[2020-04-14T06:28:37Z ERROR kubelet::kubelet] Error handling event: error decoding response body: missing field `detail` at line 1 column 119
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;其中的 &lt;code&gt;--node-ip&lt;/code&gt; 参数是可选的，在 Docker for OS X 中，需要用 &lt;code&gt;ifconfig en0&lt;/code&gt; 确定一下适配器 IP，如果是在物理机/虚拟机环境中，这个参数可以省略或者根据实际情况做出调整。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;是的你没看错，启动就出了点小问题。接下来看看节点情况：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get nodes
NAME                 STATUS   ROLES    AGE    VERSION
kind-control-plane   Ready    master   136m   v1.17.0
kind-worker          Ready    &amp;lt;none&amp;gt;   136m   v1.17.0
kind-worker2         Ready    &amp;lt;none&amp;gt;   136m   v1.17.0
kind-worker3         Ready    &amp;lt;none&amp;gt;   136m   v1.17.0
abcd-mb0       Ready    agent    111m   v1.17.0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;看看节点的情况：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl describe nodes abcd-mb0
...
Taints:             krustlet/arch=wasm32-wasi:NoExecute
...
System Info:
  Machine ID:
  System UUID:
  Boot ID:
  Kernel Version:
  OS Image:
  Operating System:           linux
  Architecture:               wasm-wasi
  Container Runtime Version:  mvp
  Kubelet Version:            v1.17.0
  Kube-Proxy Version:         v1.17.0
...
  Operating System:           linux
  Architecture:               wasm-wasi
  Container Runtime Version:  mvp
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到有很多信息是缺失的，说明项目的确很早期。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Taints&lt;/code&gt; 字段的定义，要求特定 Pod 才能调度到该节点上。&lt;/p&gt;

&lt;p&gt;最后其架构显示的是 wasm-wasi。&lt;/p&gt;

&lt;h2 id=&#34;运行一个-pod&#34;&gt;运行一个 Pod&lt;/h2&gt;

&lt;p&gt;编写一个 YAML 文件：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Pod
metadata:
  name: krustlet-tutorial
spec:
  containers:
    - name: krustlet-tutorial
      image: webassembly.azurecr.io/hello-world-wasi-rust:v0.1.0
      imagePullPolicy: Always
  tolerations:
    - key: &amp;quot;node.kubernetes.io/network-unavailable&amp;quot;
      operator: &amp;quot;Exists&amp;quot;
      effect: &amp;quot;NoSchedule&amp;quot;
    - key: &amp;quot;krustlet/arch&amp;quot;
      operator: &amp;quot;Equal&amp;quot;
      value: &amp;quot;wasm32-wasi&amp;quot;
      effect: &amp;quot;NoExecute&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;镜像名好像很普通，Pull 一下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ docker pull webassembly.azurecr.io/hello-world-wasi-rust:v0.1.0
v0.1.0: Pulling from hello-world-wasi-rust
670adc713612: Pulling fs layer
invalid rootfs in image configuration
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;看来这个镜像并不普通。。后面会讲一下。&lt;/p&gt;

&lt;p&gt;Pod 定义中声明了 &lt;code&gt;tolerations&lt;/code&gt;，让该 Pod 可以在新节点上运行。提交 yaml 之后，可以看到 Pod 运行：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get pods -w
NAME                READY   STATUS    RESTARTS   AGE
krustlet-tutorial   0/1     Pending   0          6s
krustlet-tutorial   0/1     Running   0          8s
krustlet-tutorial   1/1     Running   0       8s
krustlet-tutorial   0/1     ExitCode:0   0          8s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;看到这个 Pod 飞快的完成了运行并成功退出，查看他的日志：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;hello from stdout!
hello from stderr!
Args are: []
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;镜像&#34;&gt;镜像&lt;/h2&gt;

&lt;p&gt;前面使用 &lt;code&gt;docker pull&lt;/code&gt; 未能成功下载，这是因为这个镜像其实是一个封装为 OCI 的 WASM，可以使用 &lt;a href=&#34;https://github.com/engineerd/wasm-to-oci&#34; target=&#34;_blank&#34;&gt;was-to-oci&lt;/a&gt; 工具下载，并使用 &lt;a href=&#34;https://github.com/bytecodealliance/wasmtime&#34; target=&#34;_blank&#34;&gt;wasmtime&lt;/a&gt; 尝试运行：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ wasm-to-oci pull registry.microservice.rocks/module-wasm:v1
INFO[0007] Pulled: registry.microservice.rocks/module-wasm:v1
INFO[0007] Size: 1964621
INFO[0007] Digest: sha256:670adc7136128af3a2848d86c18013b1009e7dedb8a686ecacda175094aa083c
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;完成后可以看到当前目录出现了一个 &lt;code&gt;module.wasm&lt;/code&gt; 文件，运行一下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ wasmtime module.wasm
hello from stdout!
hello from stderr!
Args are: [&amp;quot;module.wasm&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;反过来，也可以使用这个工具把 WASM 文件推送到镜像库中。例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$  wasm-to-oci push module.wasm registry.microservice.rocks/module-wasm:v1
INFO[0001] Pushed: registry.microservice.rocks/module-wasm:v1
INFO[0001] Size: 1964621
INFO[0001] Digest: sha256:54b09224f004231ffb37d14ac478a101d94c58aac93b8da7b67ed84147763d09
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;玩后感&#34;&gt;玩后感&lt;/h2&gt;

&lt;p&gt;目前 Krustlet 对 Docker Registry 的支持似乎是有问题的，因此无法运行我们自己用 &lt;code&gt;wasm-to-oci&lt;/code&gt; 推送到私库的 WASM。网络通信等内容也就无法测试了。好在目前版本只是 0.1.0，还有很多值得一等。&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
