近日,CNCF(Cloud Native Computing Foundation)官方网站发表了由谐云边缘计算研发实习生晋晨和来自 Second State 的Vivian Hu共同撰写的文章—《使用 OpenYurt 管理 WasmEdge|轻量级边缘计算方案》。
文章介绍了边缘计算框架OpenYurt 在边端如何使用轻量级runtime WasmEdge。其中,谐云边缘计算研发实习生晋晨主要负责实验操作部分,包括实验记录工作。实际场景中,docker在边缘资源受限场景下作为runtime过重,在本实验中,改用containerd作为high level runtime,修改对应的containerd配置,使得containerd默认的low level runtime 由runc转crun,最后在OpenYurt集群上成功运行基于WebAssembly的demo app。最终,通过OpenYurt和WasmEdge的集成,拓宽在边缘计算边端资源受限场景下的使用。晋晨表示:“本文只是双方合作的一次前期尝试,后续将对于具体的场景开发更多合作的可能。”
谐云边缘计算解决方案,通过EdgeStack智能边缘计算平台保障稳定性,EdgeBox边缘一体机确保边缘安全。其中,EdgeStack®智能边缘计算平台基于轻量级容器编排框架云边端协同技术,打造“云+边缘+端”的云边端协同架构,将容器云计算能力下沉至边缘节点,可支撑百万级边缘节点和设备接入。智能边缘计算平台同时支持KubeEdge和OpenYurt,通过轻量级边缘组件与云端协同完成海量数据边缘处理;支持边缘应用和模型从云端的自动下发、更新和运维,大幅降低边缘侧应用和数据运维管理的压力。
HC-EdgeStack® 边缘计算平台架构图
使用 OpenYurt 管理 WasmEdge | 轻量级边缘计算方案
作者:晋晨(OpenYurt)Vivian Hu(WasmEdge)边缘计算[1] 是一种分布式应用架构,将计算资源(例如 CPU 和存储)放置在靠近数据源的位置。通过这种方式,为各种应用程序提供了低延迟、高性能和强大的安全性。然而,与数据中心的云计算类似,边缘计算也面临着跨异构设备和网络的工作负载分发、管理和编排等挑战。为了应对以上云计算中的这些挑战,很多开发者会选择基于容器的解决方案。因此,开发者们现在正在将 Kubernetes (K8s) 和容器等解决方案引入边缘计算。然而遗憾的是,K8s 和 Linux 容器都不是为边缘计算而设计的。边缘上标准 K8s 的潜在问题包括:
边缘设备的计算、存储和网络资源有限。在边缘设备上运行完整的 K8s 节点通常过于耗费资源。
K8s 只能管理具有公共 IP 地址的设备。然而,许多边缘设备不会暴露其公共 IP。
边缘设备经常离线,而标准的 K8s 要求其 pod 始终处于连接状态。
边缘设备通常通过非 TCP 网络连接,并且需要专门的网络接口与它们的 K8s 管理器进行通信。
因此,开发者为边缘计算创建了专门的 Kubernetes 发行版本。一个领先的为边缘优化的 K8s 发行版本是 OpenYurt[2]。OpenYurt 最初由阿里巴巴创建,现在是 CNCF 的沙箱项目。OpenYurt 是一个开放平台,囊括了上游 Kubernetes 强大的编排能力。因此,用户可以使用相同的上游 Kubernetes API 交付、管理和监控边缘工作负载。
即便使用像 OpenYurt 这样的为边缘优化了的 K8s 发行版,标准 Linux 容器仍然过于笨重,无法在小型设备上运行边缘工作负载。一个典型的 Linux 容器镜像占用的空间通常以 GB 为单位,并且启动一个完整的 CPU 需要几秒钟。考虑到典型的边缘应用程序通常较精简,Linux 容器在资源受限的设备上占用了过多的存储、CPU 和电池资源。此外,Linux 容器应用程序在边缘设备上不可跨平台,且不安全。对于边缘容器化应用程序而言,符合 OCI 标准的,且兼容 k8s 的[3]轻量级 WebAssembly runtime, 比如 WasmEdge[4] ,相较于 Linux 容器[5]是更好的替代选项。WasmEdge 提供基于能力的安全沙箱,对底层操作系统服务做很少的假设,同时在前端支持多种编程语言[6]。除了 Linux、 macOS、 Windows, WasmEdge 甚至可以在实时操作系统(RTOS)上运行,像 Linux 基金会的 seL4[7]。
OpenYurt[8] 和 WasmEdge[9] 团队一起展示如何使用 OpenYurt 在一个边缘集群中管理 WasmEdge 应用。OpenYurt 和 WasmEdge 将终于把云原生的容器化的应用带入边缘计算了!让我们开始吧!
准备工作
OpenYurt 使用中心化 Kubernetes 控制面板来管理云服务器中的多个边缘节点。此外,它将上游 Kubernetes 扩展到边缘。在这个演示中,我们将设置两台机器。一个模拟的云节点称为 Master,另一个模拟的边缘节点称为 Node。这两个节点构成了最简单的 OpenYurt 集群,OpenYurt 组件在其中运行。首先,关闭 swap 分区
sudo swapoff -a
free -m //验证
接下来,配置两个节点的文件 node/etc/hosts
然后,加载内核模块 br_netfilter,并调整内核参数。
//load the module
sudo modprobe br_netfilter
//verify
lsmod | grep br_netfilter
// create k8s.conf
cat < net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sudo sysctl --system 最后,设置 rp-filter 值,将文件 /etc/sysctl.d/10-network-security.conf 中两个参数的值由 2 改为 1,且将 /proc/sys/net/ipv4/ip_forward 设置为 1。 sudo vi /etc/sysctl.d/10-network-security.confecho 1 > /proc/sys/net/ipv4/ip_forward sudo sysctl --system 安装 Containerd 使用下面命令行在边缘节点上安装 containerd 。 export VERSION="1.5.7" echo -e "Version: $VERSION" echo -e "Installing libseccomp2 ..." sudo apt install -y libseccomp2 echo -e "Installing wget" sudo apt install -y wget wget https://github.com/containerd/containerd/releases/download/v${VERSION}/cri-containerd-cni-${VERSION}-linux-amd64.tar.gz wget https://github.com/containerd/containerd/releases/download/v${VERSION}/cri-containerd-cni-${VERSION}-linux-amd64.tar.gz.sha256sum sha256sum --check cri-containerd-cni-${VERSION}-linux-amd64.tar.gz.sha256sum sudo tar --no-overwrite-dir -C / -xzf cri-containerd-cni-${VERSION}-linux-amd64.tar.gz sudo systemctl daemon-reload 由于 crun 项目默认支持 WasmEdge,我们只需要为 runc 配置 containerd 配置即可。所以我们需要修改 /etc/containerd/config.toml 中的 runc 参数为 curn,添加 pod_annotation。 sudo mkdir -p /etc/containerd/ sudo bash -c "containerd config default > /etc/containerd/config.toml" wget https://raw.githubusercontent.com/second-state/wasmedge-containers-examples/main/containerd/containerd_config.diff sudo patch -d/ -p0 < containerd_config.diff 之后,重启 containerd 使配置生效。 systemctl start containerd 安装 WasmEdge 使用下面的安装脚本,在 edge 节点上安装 WasmEdge。 curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash 安装并构建 crun 我们需要在 edge node 上构建一个支持 WasmEdge 的 crun 二进制文件。目前,最直接的方法是你自己从源代码开始构建 crun。首先请确保你在 Ubuntu 20.04 已经安装了 crun 的依赖项。如果你使用的是其他版本的 Linux,请参考官方文档[10]。 sudo apt update sudo apt install -y make git gcc build-essential pkgconf libtool \ libsystemd-dev libprotobuf-c-dev libcap-dev libseccomp-dev libyajl-dev \ go-md2man libtool autoconf python3 automake 接下来,配置、构建、安装带有 WasmEdge 支持的 crun 二进制文件 sudo make install git clone https://github.com/containers/crun cd crun ./autogen.sh ./configure —with-wasmedge make sudo make install 安装 OpenYurt 现在,我们可以在 Edge 节点上安装 OpenYurt 来控制它下面的 containerd、crun 和 wasmedge 堆栈。构建 OpenYrut 集群最简单的方法是使用 OpenYurt 体验中心。你只需注册一个用于测试的帐户,然后就可以获得一个 OpenYurt 集群。接下来,你可以使用 yurtctl join 命令行来加入边缘节点。在此处[11]查看更多详细信息。目前,OpenYurt 体验中心提供的 OpenYurt 组件版本为 0.6.0(最新版),Kubernetes 版本为 1.20.11。 或者,你也可以根据下面的指南,从头开始构建 OpenYurt 集群。 设置一个 K8s 集群 这里我们使用 yurtctl convert 将 K8s 集群转换为 OpenYurt 集群,所以我们需要先搭建一个 K8s 集群。需要注意的一点,如果你使用 yurtctl init/join 来设置OpenYurt 集群并加入节点,你可以跳过这一步。 $ sudo apt-get update && sudo apt-get install -y ca-certificates curl software-properties-common apt-transport-https // add K8s source $ curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add - $ sudo tee /etc/apt/sources.list.d/kubernetes.list < $ deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main // install K8s components 1.18.9 $ sudo apt-get update && sudo apt-get install -y kubelet=1.18.9-00 kubeadm=1.18.9-00 kubectl=1.18.9-00 // Initialize the master node $ sudo kubeadm init --pod-network-cidr 172.16.0.0/16 \ --apiserver-advertise-address=192.168.3.167 \ --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers // join the work node $ kubeadm join 192.168.3.167:6443 --token 3zefbt.99e6denc1cxpk9fg \ --discovery-token-ca-cert-hash sha256:8077d4e7dd6eee64a999d56866ae4336073ed5ffc3f23281d757276b08b9b195 安装 yurtctl 工具 使用以下命令行安装 yurtctl 。yurtcli CLI 工具可以安装/卸载 OpenYurt 并将标准 Kubernetes 集群转换为 OpenYurt 集群。 git clone https://github.com/openyurtio/openyurt.git cd openyurt make build WHAT=cmd/yurtctl 安装 OpenYurt 各组件 yurtctl convert --deploy-yurttunnel --cloud-nodes oy-master --provider kubeadm\ --yurt-controller-manager-image="openyurt/yurt-controller-manager:v0.5.0"\ --yurt-tunnel-agent-image="openyurt/yurt-tunnel-agent:v0.5.0"\ --yurt-tunnel-server-image="openyurt/yurt-tunnel-server:v0.5.0"\ --node-servant-image="openyurt/node-servant:latest"\ --yurthub-image="openyurt/yurthub:v0.5.0" 注:需要将 -- yurtctl-servant-image="openyurt/yurtctl-servant:v0.5.0" 改成 --node-servant-image="openyurt/node-servant:latest" 运行一个简单的 WebAssembly app 接下来,让我们通过 Kubernetes 集群作为 pod 中的容器运行 WebAssembly 程序。本节将从 Docker hub 拉取基于 WebAssembly 的容器镜像开始。如果你想知道如何编译、打包 WebAssembly 程序并将其作为容器镜像发布到 Docker hub,请参阅 WasmEdge Book[12]。 从 master 节点的另一个终端窗口输入以下命令,然后开始使用集群。 root@master:~# kubectl cluster-info Kubernetes master is running at https://192.168.3.167:6443 KubeDNS is running at https://192.168.3.167:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy 因为 kubectl 1.18.9 没有 annotations 参数,所以我们在这里需要调整命令行。如果你使用的是 OpenYurt Experience Center,其默认版本为 OpenYurt 0.6.0 和 Kubernetes 1.20.11,请直接参阅 WasmEdge Book 中的 Kubernetes 部分[13]来运行 wasm 应用程序。 // kubectl 1.18.9 $ sudo kubectl run -it --rm --restart=Never wasi-demo --image=hydai/wasm-wasi-example:with-wasm-annotation --overrides='{"kind":"Pod","metadata":{"annotations":{"module.wasm.image/variant":"compat"}} , "apiVersion":"v1", "spec": {"hostNetwork": true}}' /wasi_example_main.wasm 50000000 // kubectl 1.20.11 $ sudo kubectl run -it --rm --restart=Never wasi-demo --image=hydai/wasm-wasi-example:with-wasm-annotation --annotations="module.wasm.image/variant=compat" --overrides='{"kind":"Pod", "apiVersion":"v1", "spec": {"hostNetwork": true}}' /wasi_example_main.wasm 50000000 容器化应用程序的输出被打印到控制台。所有 Kubernetes 版本都是一样的。 Random number: 1123434661 Random bytes: [25, 169, 202, 211, 22, 29, 128, 133, 168, 185, 114, 161, 48, 154, 56, 54, 99, 5, 229, 161, 225, 47, 85, 133, 90, 61, 156, 86, 3, 14, 10, 69, 185, 225, 226, 181, 141, 67, 44, 121, 157, 98, 247, 148, 201, 248, 236, 190, 217, 245, 131, 68, 124, 28, 193, 143, 215, 32, 184, 50, 71, 92, 148, 35, 180, 112, 125, 12, 152, 111, 32, 30, 86, 15, 107, 225, 39, 30, 178, 215, 182, 113, 216, 137, 98, 189, 72, 68, 107, 246, 108, 210, 148, 191, 28, 40, 233, 200, 222, 132, 247, 207, 239, 32, 79, 238, 18, 62, 67, 114, 186, 6, 212, 215, 31, 13, 53, 138, 97, 169, 28, 183, 235, 221, 218, 81, 84, 235] Printed from wasi: This is from a main function This is from a main function The env vars are as follows. The args are as follows. /wasi_example_main.wasm 50000000 File content is This is in a file pod "wasi-demo" deleted 现在,你可以通过 Kubernetes 命令行查看 pod 状态。 crictl ps -a 你可以在日志中看到从调度到运行 WebAssembly 工作负载的事件。 CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID 0c176ed65599a 0423b8eb71e31 8 seconds ago Exited wasi-demo 这样完成了。接下来,你可以尝试使用 OpenYurt 管理自己的 WasmEdge 应用。 未来可期 WasmEdge[14] 和 OpenYurt[15] 共同将 Kubernetes 的全部优势引入到了边缘计算。以上的 demo 演示了一个非常简单的使用场景,只是触及了其中巨大潜力和前景的一角。请在 GitHub 上关注这两个项目,以了解我们合作的最新信息。同时,如果你有从此技术路径中受益的应用,我们也很乐意聆听! WasmEdge GitHub repo: https://github.com/WasmEdge/WasmEdge[16] OpenYurt GitHub repo: https://github.com/openyurtio/openyurt[17] 参考资料 [1] 边缘计算: https://en.wikipedia.org/wiki/Edge_computing [2] OpenYurt: https://openyurt.io/ [3] OCI 标准的,且兼容 k8s 的: https://wasmedge.org/book/en/kubernetes.html [4] WasmEdge: https://wasmedge.org/ [5] 相较于 Linux 容器: https://wasmedge.org/wasm_linux_container/ [6] 多种编程语言: https://wasmedge.org/book/en/dev.html [7] seL4: https://wasmedge.org/book/en/os/sel4.html [8] OpenYurt: https://github.com/openyurtio/openyurt [9] WasmEdge: https://github.com/WasmEdge/WasmEdge [10] 官方文档: https://github.com/containers/crun#readme [11] 此处: https://openyurt.io/docs/installation/openyurt-experience-center/overview/ [12]WasmEdge Book: https://wasmedge.org/book/en/ kubernetes/demo/wasi.html [13]Kubernetes部分: https://wasmedge.org/book/en/ kubernetes/kubernetes.html [14] WasmEdge: https://github.com/WasmEdge/WasmEdge [15] OpenYurt: https://github.com/openyurtio/openyurt [16] https://github.com/WasmEdge/WasmEdge: https://github.com/WasmEdge/WasmEdge [17] https://github.com/openyurtio/openyurt: https://github.com/openyurtio/openyurt 关于 WasmEdge WasmEdge 是轻量级、安全、高性能、实时的软件容器与运行环境。目前是 CNCF 沙箱项目。WasmEdge 被应用在 SaaS、云原生,service mesh、边缘计算、汽车等领域。