关于webassembly:使用OCI注册中心分发WebAssembly模块

4次阅读

共计 3110 个字符,预计需要花费 8 分钟才能阅读完成。

WebAssembly(WASM)是基于堆栈的虚拟机的二进制指令格局。用相熟的术语来说,WASM 是各种编程语言(例如 C,C ++,Rust 或 Golang)的编译指标,生成具备已知格局的紧凑二进制文件。Mozilla 开发人员称 WebAssembly 对 Web 平台具备微小的意义 – 它提供了一种以近乎本机的速度在 Web 上运行以多种语言编写的代码的形式。

这里的最大含意是可能以靠近本机的速度在 Web 上执行模块。过来应用 JavaScript 编写时性能低下的工作能够用高性能编程语言(例如 C ++ 或 Rust)来重写。

然而 WebAssembly 不仅实用于 Web。WebAssembly 零碎接口我的项目(WASI)旨在通过提供操作系统工作的形象来标准化 WebAssembly 以在 Web 内部运行。这带来了两个次要长处:可移植性和安全性。明天,您能够应用 wasmtime 之类的运行时,在具备对文件系统和网络的细粒度拜访的沙盒环境中,在各种操作系统(Linux,macOS,Windows)上执行 WASM 模块。

咱们认真想想,这些劣势不正是现在如日中天的容器具备的劣势吗?

WASI 能够为容器生态系统提供一个十分乏味的代替办法 - 然而对于本文,咱们仅探讨如何散发 WebAssembly 模块。

应用 OCI 注册核心散发 WebAssembly 模块

目前,有两种调配 WebAssembly 模块的办法 – wasm-pack(应用 NPM 来存储模块)或 WAPM(独立于编程语言和工具链,但仍是一个十分晚期的工具,尚未在其内部宽泛采纳)。然而,如果咱们认为 WebAssembly 是 Linux 容器的潜在跨平台替代品,那么咱们还须要一种独立于编程语言和工具链的散发形式。为何不齐全应用 OCI 注册核心散发容器镜像的办法呢?

此外,OCI 最近发表了 OCI Artifacts 我的项目,该我的项目旨在扩大 OCI 注册管理机构标准并存储其余云原生工件(思考 Helm 图表或 CNAB 捆绑软件)。具备间接的长处 – 一种统一的形式来调配多个工件类型,应用曾经存在的注册表服务或重用和扩大以后的平安模型(例如 TUF)。

ORAS(OCI 注册表存储)是 OCI Artifacts 我的项目的拟议施行,可显著简化 OCI 注册表中任意内容的存储。因而,咱们能够应用 ORAS 客户端库来构建一个非常简单的工具,以将 WebAssembly 模块推入和推到 OCI 注册表中。

然而请留神,以后,大多数注册表服务都回绝未知的工件类型 –ORAS 已通过开源 Docker Distribution 我的项目和 Azure Container Registry 进行了测试。

第一步是定义要与 WebAssembly 模块关联的媒体类型 – 这有助于辨认工件类型,能够在配置注册表以显式容许或不容许存储它们时应用。

ConfigMediaType       = "application/vnd.wasm.config.v1+json"
ContentLayerMediaType = "application/vnd.wasm.content.layer.v1+wasm"

为了推送,咱们读取了模块的内容,将它们作为单个层增加到 OCI 描述符中,而后应用oras.Push

contents, err := ioutil.ReadFile(module)

desc := store.Add(module, ContentLayerMediaType, contents)
layers := []ocispec.Descriptor{desc}

pushOpts := []oras.PushOpt{oras.WithConfigMediaType(ConfigMediaType),
    oras.WithNameValidation(nil),
}

manifest, err := oras.Push(ctx, resolver, ref, store, layers, pushOpts...)

拉取同样简单明了 – 咱们应用 oras.Pull 来获取 OCI 清单和理论模块,而后将其写入文件中:

pullOpts := []oras.PullOpt{oras.WithAllowedMediaType(ContentLayerMediaType),
    oras.WithPullEmptyNameAllowed(),}

_, layers, err := oras.Pull(ctx, resolver, ref, store, pullOpts...)
manifest, contents, _ := store.Get(layers[0])
ioutil.WriteFile(outFile, contents, 0755)

能够在 GitHub 上找到 Go 软件包和一个 wasm-to-oci 实用程序。

应用 OCI 注册表进行测试

咱们有一个本地模块(能够在 repo 的 testdata目录中找到),并且咱们应用 wasm-to-oci 推送到咱们以后登录的 Azure 容器注册表存储库(应用 Docker CLI):

$ ls
.rwxr-xr-x 1.6M radu  hello.wasm

$ wasm-to-oci push hello.wasm <oci-registry>.azurecr.io/wasm-to-oci:v1
Pushed: <oci-registry>.azurecr.io/wasm-to-oci:v1
Size: 1624962
Digest: sha256:4c7915b4c1f9b0c13f962998e4199ceb00db39a4a7fa4554f40ae0bed83d9510

此时,咱们能够应用雷同的实用程序从刚刚推送的存储库中提取信息,而后应用抉择的 WebAssembly 运行时执行模块:

$ wasm-to-oci pull <oci-registry>.azurecr.io/wasm-to-oci:v1 --out test.wasm

Pulled: <oci-registry>.azurecr.io/wasm-to-oci:v1
Size: 1624962
Digest: sha256:4c7915b4c1f9b0c13f962998e4199ceb00db39a4a7fa4554f40ae0bed83d9510

$ wasmtime test.wasm
Hello from WebAssembly!

$ wasmer run test.wasm
Hello from WebAssembly!

咱们能够查看生成的 OCI 清单,并查看咱们之前设置的媒体类型,以及清单和理论模块的摘要和大小:

{
  "schemaVersion": 2,
  "config": {
    "mediaType": "application/vnd.wasm.config.v1+json",
    "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
    "size": 2
  },
  "layers": [
    {
      "mediaType": "application/vnd.wasm.content.layer.v1+wasm",
      "digest": "sha256:4c7915b4c1f9b0c13f962998e4199ceb00db39a4a7fa4554f40ae0bed83d9510",
      "size": 1624962
    }
  ]
}

论断

这是将 WASM 存储在 OCI 注册核心的乏味概念证实。如果您当初正在 Web 上应用 WebAssembly,则很可能不须要它,然而在 WASI 的状况下,它很有用,尤其是思考到 WebAssembly 的 container shim 程序。

PS: 本文属于翻译,原文

正文完
 0