zl程序教程

您现在的位置是:首页 >  Java

当前栏目

Harbor 2.6 支持 WebAssembly 镜像

2023-02-18 16:34:48 时间

题图摄于香港平顶山

WebAssembly,简称Wasm,是当前云原生领域的热门话题,作为一项起源于前端的技术,其使用范围已经从前端拓展到后端,在serverless、边缘计算等领域有着较吸引人的应用前景。Harbor 2.6 与时俱进,推出了Web Assembly的支持。本文介绍Harbor WebAssembly 功能。

(本文作者刘念系原 VMware 中国研发云原生实验室工程师,Harbor等云原生开源项目贡献者。)

WebAssembly 技术,最初的用途是为浏览器中 JavaScript 脚本扩展高级功能,在浏览器的 sandbox 中调用宿主机接口去运行某些特定的程序或代码段。

此外,Wasm 程序作为一种介于高级语言和机器语言中间的类汇编语言,能在宿主机上获得较好的执行速度,因此 Wasm 常常与 JavaScript 配合一起使用,负责并帮助 JavaScript 主程序处理算力要求较高的子任务,如 Google 地球网页版中渲染图层的任务都交由 Wasm 程序去完成。

在安全性方面,Wasm 遵循capability based security原则,按权分配,传递通过显式申请获得的权限,并提供了类似沙盒的虚拟运行环境,为宿主机的安全提供了不错的保障。

我们不难发现 Wasm 应用拥有着和 Docker 应用类似的特点,他们都可以映射为可移植的容器化应用程序,在目标宿主机上以隔离空间的形式启动和运行。他们各有所长,Docker 应用目前技术相对完善和成熟,容器的可交互性极高,在构建镜像时用户无需关注复杂的构建过程,通过编写指定的Dockerfile文件便可以交给成熟的工具去处理。

WebAssembly 技术目前仍处于发展的蓬勃期,很多必要的标准和统一化工具仍在依托社区进行着讨论,制定与构建中。Wasm 应用的编译对工具链要求极高,需要用户在编写程序后自行编译到 Wasm 格式的可执行文件。

尽管如此,WebAssembly 弥补了很多Docker 难以解决的痛点,Wasm 应用不论是冷启动速度,执行代价还是打包后镜像的开销都比 Docker 轻量数十倍以上。相比于Docker容器使用的 Linux 的 cgroups 隔离机制,Wasm 应用在沙盒 VM 中有着更好的隔离屏障。在一些 serverless 、边缘计算等场景中,使用 WebAssembly 都可以大展身手。

近年来随着应用云布局架构优势的凸显和高速发展,云原生应用以近乎爆炸趋势的在发布,更新和迭代,许多云原生制品仓库也相继出现,用户可以手动或者通过自动化工具拉取目标镜像文件并完成部署。

目前支持 WebAssembly 镜像管理的镜像仓库相对较少,局限了 Wasm 步入云原生领域的步伐。

Harbor 是由 VMware 中国研发中心原创的开源企业级的云原生制品仓库项目,是国内首个毕业于 CNCF 的开源项目。它包括权限管理 (RBAC)、日志审核、管理界面、镜像复制和中文支持等功能。Harbor 已经成为很多企业和个人提供了可靠的私有镜像仓库服务,云原生领域的朋友对 Harbor 应该不陌生。

在 Harbor 2.6中,Harbor 增加了对 WebAssembly 镜像的支持。用户可以将他们的 Wasm 镜像推送至 Harbor 仓库,Harbor 会识别出 Wasm 镜像进行存储,并提供拉取时的分发服务。目前,WebAssembly 主要有两种形式的镜像,这两种镜像都符合 OCI (Open Container Initiative) 规范中的容器镜像标准,但有着不同的构建方式。

第一种方式,WebAssembly 镜像使用 wasm-to-oci (https://github.com/engineerd/wasm-to-oci) 工具将目标 Wasm文件转成符合 OCI 规范的镜像结构。随后使用ORAS (OCI注册表存储)工具,将构建的镜像推送到目标镜像仓库中。wasm-to-oci 遵循OCI 制品(https://github.com/opencontainers/artifacts)项目的提案,定义了一个与 WebAssembly 模块关联的媒体类型。如下是通过 wasm-to-oci 工具产生镜像生成的 OCI 清单(manifest):

wasm-to-oci 工具可以依赖于其他工具的与目标镜像仓库建立的 credential 登录证书,如 Docker。在不特别指明的情况下,推送和拉取镜像时 wasm-to-oci 默认会检索 ~/.docker/config.json 文件并读取所需的 credential。

我们使用 wasm-to-oci 工具将 Wasm 目标码转化为 OCI 镜像结构,并推送至Harbor仓库。假设 Harbor 仓库的地址是 wasm-harbor.com,使用命令:

$ wasm-to-oci push helloworld.wasm <wasm-harbor.com>/webassembly/helloworld:v1 --insecure

可以得到以下输出信息,镜像大小和摘要ID等。

进入 Harbor 管理页面可以查看此 Wasm 镜像的概览信息:

使用 wasm-to-oci 工具构建的镜像一般服务于 krustlet。krustlet 是用Rust语言编写的虚拟kubelet,旨在帮助 Kubernetes 支持部署和调度 WebAssembly 的工作流。在部署有 krustlet 的 Kubernetes 集群中,使用如下 yaml 文件即可部署刚才Wasm 程序。

在 Krustlet 中用 rust 实现的 client,在 Wasm 工作流部署时会自动从镜像仓库中拉取所需的镜像。当然,使用 wasm-to-oci 推送到 Harbor 仓库的镜像也可以被工具本身拉取,使用命令

$ wasm-to-oci pull wasm-harbor.com/wasm/helloworld:v1 -o pulled.wasm --insecure

会将原本 OCI 镜像结构的制品(artifact)拉取到本机并转化为原始Wasm字节码文件。

第二种 WebAssembly 镜像的构建方式与构建经典的 Docker 镜像的类似,使用Dockerfile 指明定制某个镜像的步骤和说明,每条指令构建一层镜像,最后标注默认的容器启动入口。但对于 WebAssembly 镜像,用户需要在构建时为此镜像附着一个特殊的annotation标记,”run.oci.handler=wasm”或者” module.wasm.image/variant=compat”。

这不仅是 Harbor 识别 Wasm 镜像的标志,也是部署镜像到 Kubernetes 时,下游CRI runtimes 决定是否调用 Wasm 容器运行时的依据。目前 Docker 工具并不支持在构建镜像时为镜像附着 annotation,因此构建此类 Wasm 镜像需要使用其他镜像构建工具,如 buildah。

以编译好的 helloworld.wasm 文件为例子,我们将这个字节码文件拷入新建的目录中,并编写 Dockerfile 文件。内容为:

使用buildah工具构建此镜像,

$ buildah build --annotation "run.oci.handler=wasm" -t helloworld:v2 .

得到输出:

随后将构建的Wasm镜像推送至Harbor仓库:

$ buildah push --cert-dir ~/certs.d/wasm-harbor.com/ helloworld:v2 docker://wasm-harbor.com/wasm/helloworld:v2

显示推送成功:

登入到 Harbor 仓库页面,可以查到此 Wasm 镜像,同时可以检查详细的镜像信息,如镜像的 Dockerfile 构建指令历史等。

这一类型的 WebAssembly 镜像一般服务于以 crun 为 CRI runtimes 的低级容器运行时.目前 crun 中已经支持集成了wasmedge,wasmtime 和 wasmer三种Wasm的runtimes,当收到上层 CRI runtimes 传递的以指定Wasm镜像启动容器的指令时,crun 会将容器交给集成的 Wasm 运行时去处理。

如果你在使用 Wasm 开发应用,可以运用 Harbor 的新功能来存储和分发 Wasm 镜像。对之前已经使用 Harbor 管理 Docker 镜像的用户,这将是一举两得的事情。