技术深度|简单
Wasm简介
WebAssembly(简称 Wasm)是一种为栈式虚拟机设计的二进制指令集。Wasm 被设计为可供类似C/C++/Rust等高级语言的平台编译目标,最初设计目的是解决 JavaScript 的性能问题。Wasm 是由 W3C 牵头正在推进的 Web 标准,并得到了谷歌、微软和 Mozilla 等浏览器厂商的支持。当然,WebAssembly 不仅可以运行在浏览器上,也可以运行在非web环境下。
Wasm 具有运行高效、内存安全、无未定义行为和平台独立等特点,经过了编译器和标准化团队多年耕耘,目前已经有了成熟的社区。对于 Wasmtime、Wamr、Wasm3、WasmEdge 和 Wasmer 等采用 Wasm 格式的非浏览器运行时,其一方面展示了 Wasm 规范的灵活性,比如把 Wasm3 当成解释器来执行;另一方面则能支持 JIT 和 AOT 编译,外加各种缓存及优化功能。
WASM虚拟机
WASMTIME
WASMTIME是字节码联盟主推的一个WASM虚拟机,既可以作为一个CLI,也可以被嵌入到其他应用系统中,如IoT或者云原生WAMR
同样是字节码联盟旗下的,更偏向于芯片场景的虚拟机,如它的名字所示,体积非常小,起步速度只要100微秒,内存耗费最低只需100KBWASMER
这是独立于字节码联盟,并努力构建自己生态的社区推出的产品,特点是支持在更多的编程语言运行WASM实例,并有自己的包管理平台WapmSSVM
这是一个相对小众的运行时,对云、AI 以及区块链有针对性的优化WasmEdge
WasmEdge是一个轻量级高性能虚拟机,应用于 severless 云函数、SaaS、区块链智能合约、物联网、汽车实时软件应用等多种场景
WASM虚拟机的优势
1. 快速、高效、可移植:通过利用常见的硬件能力,WASM代码在不同平台上能够以接近本地速度运行。
2. 可读、可调试:WASM是低阶语言,但允许通过人工来写代码、看代码以及调试代码。
3. 保持安全:WASM被限制运行在一个安全的沙箱执行环境中。像其他网络代码一样,它遵循浏览器的同源策略和授权策略。
4. 不破坏网络:WASM的设计原则是与其他网络技术和谐共处并保持向后兼容。
虽然 Wasm 在浏览器中高度依赖于 JavaScript 和 Wasm 运行时之间的桥梁,但非营利性组织字节码联盟(Cosmonic、Fermyon 和 Suborbital 等都是其成员)一起参与研发,希望为 Wasm 引入系统绑定。Wasm 系统接口(WASI)就是典型案例,其添加了能够与文件系统、环境变量、时钟和随机数生成器等系统资源进行交互的标准化支持。
WASI
WASI是一个新的API体系, 由Wasmtime项目设计, 目的是为WASM设计一套引擎无关(engine-indepent),面向非Web系统(non-Web system-oriented)的API标准. 目前, WASI核心API(WASI Core)在做覆盖文件,网络等等模块的API, 离实用还是有很长路要走.
WASM与Runtime
WebAssembly和WASI都是相当新的东西,因此在容器生态系统上运行Wasm工作负载的标准还没有确定。本文只介绍一种解决方案,当然还有其他可行的方案,例如将Linux容器运行时与Wasm兼容的组件替换。比如,使用Krustlet替代原生的kubelet,这种方法的局限性在于,用户必须在Linux容器运行时和Wasm运行时之间进行选择;另一种解决方案是使用带有Wasm运行时的镜像并调用编译后的二进制文件,但这种方法会使容器镜像随着运行时而膨胀,如果在低容器运行时上调用Wasm运行时,就不一定需要这种方法。
本文将介绍如何通过配置,让OCI运行时运行Linux容器和wasi兼容的工作负载。
低级运行时Crun
通过现有的低级别OCI运行时实现调用Linux容器和Wasm容器,就可以很容易地解决上面讨论的一些问题。这避免了诸如依赖容器镜像来承载Wasm运行时或向仅支持Wasm容器的基础设施引入新层等问题。
其中一个可以处理该任务的容器运行时:Crun
Crun速度快,占用内存少,是一个完全符合oci标准的容器运行时,可以作为现有容器运行时的替代品。最初编写Crun是为了运行Linux容器,但它也提供了以host方式在容器沙盒中运行任意扩展的程序的能力。
下面是用Crun替换现有运行时的一种不正规的方式,其只是为了展示Crun可以替换现有的OCI运行时。
$ mv /path/to/exisiting-runtime /path/to/existing-runtime.backup
cp /path/to/crun /path/to/existing-runtime
其中一个处理程序是crun-wasm-handler,将配置的容器镜像(Wasm 兼容镜像)集成到crun sandbox从而成为现有的Wasm运行系统的一部分。通过这种方式,终端用户不需要自己维护Wasm运行时。
crun与wasmedge、wasmtime和wasmer进行了集成,以支持开箱即用的功能。crun可以通过检测镜像是否包含Wasm/WASI工作负载,以动态调用这些运行时。
有关使用Wasm/WASI支持构建crun的详细信息,请参见GitHub上的crun库。
用户可以在Podman和Kubernetes上使用crun作为底层的OCI运行时来创建和运行与平台无关的Wasm镜像。
Buildah构建镜像
Wasm/WASI兼容的映像是特殊的。它们包含一个注释(annotation),可以帮助像crun这样的OCI运行时区分linux一般镜像还是具有Wasm/WASI工作负载的镜像。然后,按需调用处理程序。
可以使用任何容器镜像构建工具,以创建Wasm镜像,但在本文中,使用Buildah。
1. 编译.wasm模块。
2.用.wasm模块准备一个Dockerfile。
FROM scratch
COPY hello.wasm /
CMD ["/hello.wasm"]
3. 使用Buildah构建Wasm镜像,并打上module.wasm.image/varian=compat的annotation
"module.wasm.image/variant=compat" -t mywasm-image buildah build --annotation
构建完镜像并将容器引擎配置为crun,crun将自动执行所需的工作并运行由配置的Wasm处理程序提供的工作负载。
Podman运行WASM
Crun是Podman的默认OCI运行时。Podman可以利用大多数crun特性,包括crun Wasm处理程序。一旦构建了Wasm 兼容镜像,Podman就可以像使用其他容器镜像一样使用它们:
podman run mywasm-image:latest
Podman使用crun的Wasm处理程序运行mywasm-image:latest,并返回执行的输出。
hello world from the webassembly module !!!!
WASM与CRI
下面是如何配置两个常用的容器运行时:
CRI-O
cri-o是一个轻量级的CRI运行时,它支持OCI,并提供镜像的管理、容器进程管理、监控日志及资源隔离等工作。
cri-o的通信地址默认是在/var/run/crio/crio.sock。
配置
1. 通过编辑/etc/crio/crio.conf的配置,配置crio使用crun而不是runc。Red Hat OpenShift文档包含关于配置crio的更多细节。
2. 用sudo systemctl Restart crio重新启动crio。
3.CRI-O自动将pod注释传播到容器spec。
Containerd
containerd应该是目前最流行的CRI运行时。它以插件的方式实现CRI,默认是启用的。它默认在unix套接字上监听消息。
从1.2版本开始,它通过 runtime handler来支持多种低级运行时。运行时处理程序是通过CRI中的字段传递,根据该运行时处理程序,containerd运行shim的应用程序来启动容器。这可以用来运行 runc及其他的低级运行时的容器,如 gVisor、Kata Containers等。在Kubernetes API中通过RuntimeClass进行运行时配置。
配置
1. Containerd支持通过在/etc/containerd/config.toml中定义的自定义配置切换容器运行时。
2. 通过确保运行时二进制文件指向crun,将containd配置为使用crun。更多细节可在包含的文档中找到。
3. 配置containd允许列出Wasm注释,这样它们就可以通过在配置中设置pod_annotations来传播到OCI规范:pod_annotations = ["module.wasm.image/ variable .*"]。
4. 使用sudo systemctl start containerd重新启动容器。
5. 现在,containd应该将wasmpod注释传播到容器。
下面是一个Kubernetes pod规范的例子,可以同时使用crio和containerd:
apiVersion: v1
kind: Pod
metadata:
name: pod-with-wasm-workload
namespace: mynamespace
annotations:
module.wasm.image/variant: compat
spec:
containers:
- name: wasm-container
image: myrepo/mywasmimage:latest
相关问题
CRI在Kubernetes 1.5中引入,作为kubelet和容器运行时之间的桥梁。社区希望Kubernetes集成的高级容器运行时实现CRI。该运行时处理镜像的管理,支持Kubernetes pods,并管理容器,因此根据高级运行时的定义,支持CRI的运行时必须是一个高级运行时。低级别的运行时并不具备上述功能。
在许多情况下,Pod带有sidecar。这意味着,当部署包含sidecar且sidecar容器不包含Wasm entry point时,crun的Wasm集成是没有用的,例如使用服务网格(如Linkerd、Gloo和Istio)的基础设施或网络代理(如Envoy)。
当然我们可以通过为Wasm处理程序添加两个annotation来解决这个问题:compat-smart和was-smart。这些注释充当选择开关,只在容器需要时切换Wasm运行时。因此,当使用sidecars运行部署时,只有包含有效Wasm工作负载的容器才由Wasm处理程序执行。常规容器被视为常规容器,并委托给主机Linux容器运行时。
因此,在构建容器镜像时,需要使用的annotation是module.wasm.image/variant=compat-smart而不是module.wasm.image/variant=compat
。
由于笔者时间、视野、认知有限,本文难免出现错误、疏漏等问题,期待各位读者朋友、业界专家指正交流。
参考文献
1.https://www.528btc.com/college/58442.html
真诚推荐你关注