参考资料
- WebAssembly 在云原生中的实践指南,https://cloud.tencent.com/developer/article/2324065
作为一种通用字节码技术,wasm的初衷是在浏览器中的程序实现原生应用性能。高级语言将wasm作为目标语言进行编译并运行在wasm解释器中。和nodejs类似的发展轨迹,2019年Mozilla推出的wasi标准将wasm应用的范围扩展到了OS中,实现了跨平台。
wasm在多个层面都能够对标oci容器运行时,可以将其理解为实现了OCI标准的轻量级JVM,兼顾了轻量性能和跨平台,可以作为新一代容器运行时使用。
关于wasm核心规范(不包括wasi),字节码和解释器的更多内容可以参考,https://segmentfault.com/a/1190000040737725
本文的主要内容如下
- 在eks节点中安装wasm运行时
- 构建wasm镜像并部署
大多数wasm运行时的资料都集中在ubuntu发行版(但是中国区并没有提供ubuntu的eks ami)
- wasm在eks上的支持目前还在roadmap中,https://github.com/aws/containers-roadmap/issues/1997
- runc支持wasm目前还在roadmap中
由于OS本身在这里并不重要,因此为了避免重复劳动,将global eks ami拷贝到中国区,具体步骤省略。
在拷贝之前,需要在实例上完成以下步骤
安装wasmedge,关于不同wasm运行时的比较,可以参考https://zhuanlan.zhihu.com/p/562593932
curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash
source $HOME/.wasmedge/env
安装必要的编译和依赖环境
apt update
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
安装crun,因为crun能够支持wasm运行时,eks默认的runc目前还不支持
git clone https://github.com/containers/crun
cd crun
./autogen.sh
./configure --with-wasmedge
make
make install
crun是一个低等级的容器运行时,关于crun,containerd的docker的关系,可以从high-level和low-level容器运行时的角度区分,大体逻辑如下图
- containerd 使用 crun, youki 这两种支持wasm的不同的低级容器运行时来管理 Wasm 模块,同时也可以运行普通的linux容器,本次在eks的配置与此类似
- containerd 通过 containerd-wasm-shim 直接通过 Wasm 运行时来管理 Wasm 模块。
安装完毕后查看是否生效
root@ip-192-168-10-99:~/crun# crun -v
crun version 1.14.4.0.0.0.23-a32cc
commit: a32cc45fb3944fd34866e25af5ef70dc02207b0d
rundir: /run/crun
spec: 1.0.0
+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +WASM:wasmedge +YAJL
修改containerd的配置文件/usr/local/share/eks/containerd-config.toml
,末尾添加如下
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun]
runtime_type = "io.containerd.runc.v2"
pod_annotations = ["module.wasm.image/variant"]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun.options]
BinaryName = "crun"
配置完毕后生成ami并拷贝中国区,直接启动实例(配置网络权限等,此处不赘述),在实例中运行启动脚本
观察节点加入集群情况
构建wasm镜像,此处以rust语言为例,先参考https://rsproxy.cn/#getStarted配置rust工具链
export RUSTUP_DIST_SERVER="https://rsproxy.cn"
export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup"
curl --proto '=https' --tlsv1.2 -sSf https://rsproxy.cn/rustup-init.sh | sh
编写主要逻辑如下
use warp::Filter;
#[tokio::main(flavor = "current_thread")]
async fn main() {
let hello = warp::get()
.and(warp::path::end())
.map(|| "Hello, World!");
warp::serve(hello).run(([0, 0, 0, 0], 8080)).await;
}
修改依赖文件
[dependencies]
tokio_wasi = { version = "1", features = ["rt", "macros", "net", "time", "io-util"]}
warp_wasi = "0.3"
添加wasm编译目标并编译
rustup target add wasm32-wasi
cargo build --target wasm32-wasi --release
使用如下dockerfile构建镜像wasm-demo-app
FROM scratch
COPY target/wasm32-wasi/release/http-server.wasm /
CMD ["/http-server.wasm"]
查看镜像只有0.87MB
创建以下runtimeclass和pod,直接部署
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: crun
handler: crun
---
apiVersion: v1
kind: Pod
metadata:
name: wasm-demo-app
annotations:
module.wasm.image/variant: compat
spec:
runtimeClassName: crun
containers:
- name: wasm-demo-app
image: xxxxxxxx.dkr.ecr.cn-north-1.amazonaws.com.cn/wasm-demo-app:latest
启动后contaainerd使用crun运行容器,但是调用wasmedge时出现如下报错,参考https://github.com/containers/crun/issues/1046解决,即将wasmedge的动态链接加入lddconfig路径
could not load `libwasmedge.so.0
容器正常运行
尝试请求,成功相应
$ curl 192.168.9.206:8080
Hello, World!