zoukankan      html  css  js  c++  java
  • 在kubernetes上运行WASM负载

    在kubernetes上运行WASM负载

    WASM一般用在前端业务中,但目前有扩展到后端服务的趋势。本文使用Krustlet 将WASM服务部署到kubernetes。

    简介

    Krustlet 是一个可以在kubernetes本地运行WebAssembly负载的工具。Krustlet作为kubernetes集群中的节点。当用户使用特定node tolerations来调度Pod时,kubernetes API会将该负载调度到一个Krustlet节点,Krustlet会拉取并运行模块。

    为了在Krustlet 节点上运行一个应用,首先必须将该应用编译为WebAssembly 格式,并推送到镜像仓库中。

    准备

    首先使用kind安装一个kubernetes集群(minikube要求使用virtualBox驱动)。

    安装Krustlet

    安装二进制文件

    首先从官网下载安装Krustlet,拷贝到一个系统可识别的路径即可(如/usr/local/bin)

    生成bootstrap文件

    Krustlet和kubelet的初始化流程类似,执行如下命令生成Krustlet的bootstrap.conf文件,默认路径为/root/.krustlet/config

    $ bash <(curl https://raw.githubusercontent.com/deislabs/krustlet/master/docs/howto/assets/bootstrap.sh)
    

    运行Krustlet

    找到kind使用的默认网关地址:

    # docker network ls
    NETWORK ID     NAME      DRIVER    SCOPE
    ...
    b48010373347   kind      bridge    local
    
    # docker network inspect b48010373347|grep "Gateway"
                        "Gateway": "172.18.0.1"
    

    运行Krustlet:

    $ export KUBECONFIG=~/.krustlet/config/kubeconfig
    $ krustlet-wasi --node-ip 172.18.0.1 --bootstrap-file=/root/.krustlet/config/bootstrap.conf
    

    运行界面如下,提示需要审批CSR:

    # krustlet-wasi --node-ip 172.18.0.1 --bootstrap-file=~/.krustlet/config/bootstrap.conf
    BOOTSTRAP: TLS certificate requires manual approval. Run kubectl certificate approve ubuntu-tls
    

    审批CSR

    $ kubectl certificate approve <hostname>-tls
    

    校验

    运行kubectl get nodes -o wide,可以看到新增了一个节点ubuntu,在该节点上可以运行WebAssembly负载:

    # kubectl get node -owide
    NAME                 STATUS   ROLES    AGE     VERSION   INTERNAL-IP   EXTERNAL-IP  
    kind-control-plane   Ready    master   16m     v1.19.1   172.18.0.2    <none>       
    ubuntu               Ready    <none>   8m37s   0.7.0     172.18.0.1    <none>       
    

    部署应用

    下面安装官方的一个例子/demos/wasi/simpleserver/。运行如下命令即可:

    # kubectl apply -f simpleserver.yaml
    

    该pod会启动一个伪服务,代码如下:

    use std::thread::sleep;
    use std::time::Duration;
    
    fn main() {
        loop {
            println!("Hello, World!");
            sleep(Duration::from_secs(5));
        }
    }
    

    需要注意的是,在k8s.yaml中镜像字段为webassembly.azurecr.io/simpleserver:v1.0.0,但它并不是一个标准的容器镜像,而是WASM的module,默认会放到/root/.krustlet/.oci/modules目录下。在/root/.krustlet/.oci/modules/webassembly.azurecr.io/simpleserver/v1.0.0目录下查看拉取到的module

    # ll
    -rw-r--r-- 1 root root      71 May  6 22:34 digest.txt
    -rw-r--r-- 1 root root 1998989 May  6 22:34 module.wasm
    

    可以看到module.wasm的大小只有约2M,是一个支持跨平台运行的二进制文件,由此可以看出WASM和容器的区别:容器是需要基础镜像的,而WASM则不需要,它是一个可以跨平台运行的二进制文件,且需要特定的runtime工具运行。

    # file module.wasm
    module.wasm: WebAssembly (wasm) binary module version 0x1 (MVP)
    

    可以使用wasmtime运行.wasm文件,wasmtime的下载方式如下:

    curl https://wasmtime.dev/install.sh -sSf | bash
    

    运行如下:

    # wasmtime module.wasm
    Hello, World!
    Hello, World!
    Hello, World!
    ...
    

    WASM POD分析

    查看该Pod,可以看到它就是一个正常运行的pod

    # kubectl get pod
    NAME           READY   STATUS    RESTARTS   AGE
    simpleserver   1/1     Running   0          7m59s
    

    运行kubectl describe pod simpleserver查看该pod信息

    apiVersion: v1
    kind: Pod
    metadata:
      name: simpleserver
      labels:
        app: simpleserver
    spec:
      containers:
        - image: webassembly.azurecr.io/simpleserver:v1.0.0
          imagePullPolicy: Always
          name: simpleserver
      tolerations:
        - key: "node.kubernetes.io/network-unavailable"
          operator: "Exists"
          effect: "NoSchedule"
        - key: "kubernetes.io/arch"
          operator: "Equal"
          value: "wasm32-wasi"
          effect: "NoExecute"
        - key: "kubernetes.io/arch"
          operator: "Equal"
          value: "wasm32-wasi"
          effect: "NoSchedule"
    

    源代码编译运行

    编译

    由于上例的代码是rust编写的,因此需要安装rust套件:

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    

    在rust工具链中添加wasm:

    $ rustup target add wasm32-wasi
    

    生成可执行文件:

    $ cargo build --target wasm32-wasi --release
    

    推送module

    由于生成的二进制并不是标准的镜像,因此无法直接推送到OCI仓库中,可以使用wasm-to-oci将module推送到OCI 仓库。

    但需要注意的是,并不是所有的镜像仓库都支持推送WASM module,目前支持的镜像仓库为:

    PS: 我使用了harbor镜像库,但无论使用http(报token无法解析)还是https(ca issuer无法识别),krustlet-wasi都无法成功拉取镜像。因此,建议有条件的话使用Azure或Google的镜像仓库

    参考这篇文章搭建harbor镜像仓库(使用https方式)。搭建成功后,登录仓库,并执行如下命令,将WASM module推送到仓库中:

    # wasm-to-oci push simpleserver.wasm registry.harbor.com/library/wasm-hello-world:v1 --use-http
    

    在harbor仓库中可以看到刚上传的module。

    image

    运行自己的module

    将k8s.yml中的image修改为自己的module地址:

    image: registry.harbor.com/library/simpleserver:v1
    

    总结

    WASM本身支持多种语言,因此可以方便地将市面上已有的服务转换为WASM格式。后续WebAssemble有可能成为一种新的容器类型,类似Linux容器或Windows容器。
    WASM由WASM虚拟机实现隔离性,但目前的隔离程度有限(如CPU、mem、network、共享存储等),且WASM虚拟机实现各异。这里给出了一系列WebAssembly Runtimes。

    可以参考一下这篇文章Using WebAssembly and Kubernetes in Combination,里面详细讲解了WASM的现状。WASM目前还处于早期,WASI标准后续也需要进行迭代更新。但由于其本身具有的轻量级以及可移植的优点,相信前途会一片光明。

    PS:对服务端的WASM支持最多最好的语言是RUST,是否是时候捡起来了?

    TIPS:

  • 相关阅读:
    GitHub 更新fork的代码
    robotframework出现错误:Keyword 'AppiumLibrary.Open Application' expected 1 to 2 non-keyword arguments,got 5.
    adb命令积累
    appium测试android环境搭建(win7)
    小明的自留地
    转载:appium踩过的坑
    junit3和junit4的使用区别如下
    Python线程指南
    实现ie低版本支持input type="number"
    LODOP打印开发
  • 原文地址:https://www.cnblogs.com/charlieroro/p/14737418.html
Copyright © 2011-2022 走看看