HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

WebAssembly 与 Kubernetes 双剑合璧:机遇与挑战

  • 2020-03-07
  • 本文字数:7772 字

    阅读完需:约 25 分钟

WebAssembly 与 Kubernetes双剑合璧:机遇与挑战

无处不在的 WebAssembly

如果评选 2019 年编程技术的“网红”,无论是前端圈还是后端圈 WebAssembly (WASM) 都绝对能够高票入选。然而,如果评选最被“低估”的技术,我觉得 WebAssembly 也可以轻松入围。借用伏尔泰曾评价神圣罗马帝国的句式 “既不神圣,也不罗马,更非帝国”,我们也可以说 WebAssembly “既不限于 Web,更不是 Assembly(汇编语言)”。


在 2019 年 12 月,万维网联盟 (World Wide Web Consortium - W3C) 宣布WebAssembly核心规范正式成为Web标准, 这使得 WebAssembly 成为互联网上与 HTML, CSS, and JavaScript 并列的第四种官方语言,可以原生的运行在浏览器上。而更加重要的是,WebAssembly 作为一个安全的、可移植、高效率的虚拟机沙箱,可以在 Internet 的任何地方、任何平台(不同操作系统,不同 CPU 体系架构下)安全运行应用。WebAssembly 已得到了所有主流浏览器厂商的广泛支持(Google Chrome, Microsoft Edge, Apple Safari, Mozilla Firefox 等),然而它的影响已经远超 Web。


WebAssembly 的设计初衷之一是为了解决 JavaScript 的性能问题,使得 Web 网页应用有接近本机原生应用的性能。作为一个通用、开放、高效的底层虚拟机抽象,众多编程语言(如 C/C++, Rust, 等)可以将现有应用编译成为 WASM 的目标代码,运行在浏览器中 。这让应用开发技术与运行时技术解耦,极大促进了代码复用。


Mozilla 在 2019 年 3 月推出了 WebAssembly System Interface(WASI),来标准化 WebAssembly 应用与系统资源的交互抽象,比如文件系统访问,内存管理,网络连接等,类似 POSIX 这样的标准 API。WASI 规范大大拓展了 WASM 应用的场景,可以让其可以超越浏览器环境,作为一个独立的虚拟机运行各种类型的应用。同时,平台开发商可以针对具体的操作系统和运行环境提供 WASI 接口不同的实现,可以在不同设备和操作系统上运行跨平台的 WebAssembly 应用。这可以让应用执行与具体平台环境实现解耦。这一切使得“Build Once, Run Anywhere”的理想逐渐形成现实。WASI 的示意图如下所示。2019 年月,为了进一步推动模块化 WebAssembly 生态系统,Mozilla、Fastly、英特尔和红帽公司携手成立了字节码联盟(Bytecode Alliance),共同领导 WASI 标准、 WebAssembly 运行时、语言工具等工作。



原图:https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/

WASM 与容器相爱相杀

WebAssembly 是否会取代容器?

正因为 WebAssembly 所具备的的安全、可移植、高效率,轻量化的特点,非常适于应用安全沙箱场景。WASM 得到了容器、函数计算、IoT/边缘计算等社区的广泛关注。Docker 创始人 Solomon Hykes 在 WASI 发布之际的一句 Twitter,更是成为了去年容器和 WebAssembly 社区引用频率最高的一句话之一。



Fastly, Cloudflare 等 CDN 厂商基于 WebAssembly 技术实现了更加轻量化的应用安全沙箱,可以在一个进程内部运行多个独立的用户应用。阿里云 CDN 团队 EdgeRoutine 也实现了类似技术。与容器技术相比,WASM 可以实现毫秒级冷启动时间和极低的资源消耗。



原图:https://blog.cloudflare.com/cloud-computing-without-containers/


当然,世界上没有完美的技术。任何沙箱技术不可能同时满足执行效率、安全隔离性和通用性这三个维度的要求。WASM 在安全隔离和通用性等方面与 Docker Container 等存在差距。虽然如此,我们还是看到了 WebAssembly 技术巨大的潜力。

WebAssembly 容器

我的理解是 WebAssmebly 可以成为一种容器类型,类似 Linux Container 或者 Windows Container 一样。成为一个跨平台的标准应用分发方式和运行时环境。

应用分发

Docker 容器的一个重要贡献是其标准化了容器化应用打包规范 Docker Image,而且它已经成为开放容器计划(Open Container Initiative - OCI)的镜像格式标准。Docker 镜像提供了自包含、自描述的镜像格式。它可以将应用以及其依赖的环境信息打包在一起,从而实现应用与运行环境解耦,让容器应用可以轻松运行在从本地开发环境到云端生产环境的不同场景中。并且社区围绕 Docker 镜像构建了繁荣的工具链生态,如 Docker Hub 可以进行应用分发和 CI/CD 协同,Nortary/TUF 项目可以保障应用可信地分发、交付。


对与 WebAssembly,目前社区提供了类似 NPM 的包管理实现 WAPM,可以较好地支持应用的分发。 为 WebAssembly 应用构建 Docker 镜像,可以实现双赢的局面。


  • WebAssembly 开发者可以完全复用 Docker/OCI 镜像规范和工具链,进一步简化应用分发和交付。比如,我们可以将 Nginx 的 WASM 镜像作为基础镜像,基于这个镜像可以构建包含不同 Web 内容的应用镜像;我们可以利用 tag 对应用版本进行追踪;利用 Docker Registry 进行应用分发;在这个过程我们还可以进一步利用数字签名来保障安全的软件供应链。

  • Docker 镜像规范支持Multi-Arch镜像,可以简化不同 CPU 体系架构(如 x86, ARM, RISC-V 等)的应用镜像的构建与分发。而 WebAssembly 天生具备可移植性,大大简化了跨平台 Docker 应用镜像的构建和分发。

  • 参考:利用Docker加速 ARM 容器应用开发和测试流程


我提供了一个技术原型示例项目,https://github.com/denverdino/wasm-container-samples,大家可以参考其中的例子来构建 WASM 容器镜像。由于 WebAssembly 应用采用紧凑的二进制格式,而且没有任何操作系统依赖,WASM 应用可以构建出非常小的容器镜像。大家可以自行感受一下:


$ sudo ctr image lsREF                                                           TYPE                                                 DIGEST                                                                  SIZE      PLATFORMS   LABELSdocker.io/denverdino/c-http-server-wasm:latest                application/vnd.docker.distribution.manifest.v2+json sha256:2efa759f46f901cda2e6a9b4228c423b17a960c06e957964e72c21dc5b42408f 29.2 KiB  linux/amd64 -docker.io/denverdino/hellowasm:latest                         application/vnd.docker.distribution.manifest.v2+json sha256:cadcc8b07eb82b18db2c8f500fa2b11e5ebf2e9054cfa687e4ffe44861860132 8.2 KiB   linux/amd64 -docker.io/denverdino/nginxwasm:latest                         application/vnd.docker.distribution.manifest.v2+json sha256:8735c82524a463b842b7c79f2c1be8094ee1c57cfd34154f68752fbe79c25998 582.7 KiB linux/amd64 -
复制代码

安全隔离

WebAssembly 的最初设计目标是让应用可以安全运行在浏览器中。WASM 虚拟机提供的的沙箱和内存隔离机制,可以有效减少安全攻击面。而当 WebAssembly 走出浏览器,面向更加通用的场景。WASM 也面对更加复杂的安全挑战。


WASI 提供了基于能力的安全模型。WASI 应用遵循最小权限原则,应用只能访问其执行所需的确切资源。传统上,如果应用需要打开文件,它会带路径名字符串调用系统操作 open。然后系统调用会检查应用是否具有访问该文件的相关权限,比如 Linux 实现了基于用户/组的权限模型。这样隐式的安全模型,依赖于正确的安全管理配置,比如一旦特权用户执行了一个恶意应用,它就可以访问系统中任意的资源。而对于 WASI 应用而言,如果它需要需要访问指定文件等系统资源,需要从外部显式传入加有权限的文件描述符引用,而不能访问任何其他未授权资源。这中依赖注入的方式可以避免传统安全模型的潜在风险。一个示意图如下



原图:https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/


我们可以看到 WASI 的安全模型与传统操作系统安全模型非常不同,而且还在持续演进中。比如字节码联盟提出了 nanoprocess 来解决应用模块间的安全协同和信任传递。


WebAssembly/WASI 的安全模型依然存在不足,比如


  • 资源隔离:

  • 对于内存资源,WebAssembly 实现了线性内存模型。WebAssembly 应用只能利用索引访问传入的一段逻辑线性内存。而 WASM 虚拟机负责确定内存的实际物理地址,WASM 应用无法获知内存的真实地址,也无法通过越界访问等方式发动攻击。所以理论上,可以对 WASM 应用进行资源容量限制。但是目前部分 WASM 虚拟机还无法对内存进行精确的隔离限制

  • 对于 CPU 资源,部分的 WASM 虚拟机实现可以对应用使用的 CPU 资源进行计量,但是大多无法实现精确的配额限制、优先级和抢占式调度。

  • I/O 资源,比如 IOPS 等,WASM 目前完全没有相关的隔离能力。

  • 网络安全:

  • WASI 的 Capability 模型对于文件系统访问相对比较容易保护。但是这个静态的安全模型无法适用于动态的网络应用场景。在微服务架构中,应用经常通过 Service Registry 进行服务发现,为服务的调用者和提供者实现动态的调用绑定。这个语义是无法用静态的 capability 模型描述和注入的。这也导致了 WASI 的网络部分 API 还处于讨论之中。现有的WASI网络安全模型,以及相关讨论


Linux 操作系统和容器技术已经提供了非常完备的资源隔离和安全隔离实现。与 WebAssembly 结合在一起可以应对不同场景对不同隔离级别的需求。


  • 共享进程资源 - 多个 WASM 应用模块运行在一个 WASM 虚拟机进程内部,依赖 WASM 运行时进行隔离。隔离级别低,控制粒度比较粗,资源开销极小。可以以较小代价保障系统安全。适合受限问题域的应用安全隔离。

  • 独立进程资源 - 不同 WASM 应用模块运行在不同的 WASM 虚拟机进程中,可以复用操作系统的进程级隔离能力,比如 CGroup。此外,还可以利用类似 Kubernetes 中的 Network Policy (网络策略),或者服务网格(如 Istio)等技术,对进程的网络访问进行细粒度的控制,甚至实现零信任网络。隔离级别比较高,控制粒度比较细,资源开销适中。可以应用于更加通用的场景。


注:当然利用安全沙箱如虚拟化等技术,结合 WebAssembly,可以进一步最小化安全攻击面,但是 ROI 不高。

调度与编排

在云时代,Kubernetes 已经成为分布式环境下资源调度和应用编排的事实标准。Kubernetes 可以屏蔽底层设施的差异性。可以在同一个 K8s 集群中包含 x86、ARM 等不同体系架构的节点,可以支持 Linux,Windows 等不同的操作系统。Kubernetes 和 WebAssembly 相结合可以进一步提升应用的可移植性。


微软的 Deis Labs 年初发布了一个实验项目, https://github.com/deislabs/krustlet 来利用 Virtual Kubelet 类似的架构调度 WebAssembly 应用。但是这个方式有很多局限,无法借助容器方式进行应用分发,也无法利用 K8s 的语义进行资源编排。


难得有一个春节假期可以宅在家里间,我基于 Derek McGowan 去年的一个实验性项目https://github.com/dmcgowan/containerd-wasm,完善了 containerd 的 WASM shim 实现。可以让 containerd 支持 WASM container,并且可以利用 Kubernetes 集群管理和调度 WASM container。


项目的代码实现: https://github.com/denverdino/containerd-wasm


注:这个项目更多是概念验证,进程管理、资源限制,性能优化等的细节并没未完整实现。


整个系统的架构设计如下,“container-shim-wasm-v1”做为 Containerd 的扩展,利用 wasmer 作为 WASM 应用运行时环境,可以实现与 runc 容器一致的用户体验。



我们还会将其注册为 K8s 的一个RuntimeClass ,允许用户利用 K8s 来交付和运维 WASM 应用。


注:RuntimeClass 是 Kubernetes v1.12 引入的新概念,可以让 Kubernetes 支持多种不同的容器运行时,比如 runc 容器、或者 Kata Containers,gVisor 等安全沙箱容器。更多细节可以参考,containerd与安全沙箱的Kubernetes初体验

Talk is Cheap, 放码过来

首先,我们将利用 Minikube 创建一个 K8s 测试环境,并将 Containerd 作为 Kubernetes 集群的容器运行时。

创建虚拟机测试环境

创建 Minikube K8s 集群,并将 Containerd 作为 Kubernetes 集群容器运行时


minikube start --image-mirror-country cn \    --iso-url=https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/iso/minikube-v1.6.0.iso \    --registry-mirror=https://tgtsuwdg.mirror.aliyuncs.com \    --container-runtime=containerd
复制代码


进入 Minikube 虚拟机


$ minikube ssh                         _             _            _         _ ( )           ( )  ___ ___  (_)  ___  (_)| |/')  _   _ | |_      __/' _ ` _ `\| |/' _ `\| || , <  ( ) ( )| '_`\  /'__`\| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )(  ___/(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)
复制代码


配置环境所需依赖


  • wasmer 0.13

  • minikube 缺省安装了 container 1.2.x,需要升级 containerd 1.3.x

  • 我提供了一个预编译的 containerd-wasm-shim-v1,也可自己编译一个版本。


cd ~
# Install Wasmer 0.13.1curl -L -O https://github.com/wasmerio/wasmer/releases/download/0.13.1/wasmer-linux-amd64.tar.gzgunzip wasmer-linux-amd64.tar.gztar xvf wasmer-linux-amd64.tarsudo cp bin/* /usr/bin/
# Upgrade containerd to v1.3.2curl -L -O https://github.com/containerd/containerd/releases/download/v1.3.2/containerd-1.3.2.linux-amd64.tar.gzgunzip containerd-1.3.2.linux-amd64.tar.gztar xvf containerd-1.3.2.linux-amd64.tarsudo systemctl stop containerdsudo cp bin/* /usr/bin/sudo systemctl restart containerd
# Install containerd-wasm-shimwget http://kubernetes.oss-cn-hangzhou.aliyuncs.com/containerd-wasm/containerd-shim-wasm-v1chmod +x containerd-shim-wasm-v1sudo mv containerd-shim-wasm-v1 /usr/bin/
复制代码

配置 containerd 支持 WASM shim

在 containerd 配置文件中添加 wasm shim 相关配置,并重启 containerd。


$ cat <<EOF | sudo tee -a /etc/containerd/config.tomldisabled_plugins = ["restart"][plugins.cri.containerd.runtimes.wasm]  runtime_type = "io.containerd.wasm.v1"EOF
$ sudo systemctl restart containerd
复制代码


测试 Hello World WASM 容器应用


$ sudo ctr image pull docker.io/denverdino/hellowasm:latestdocker.io/denverdino/hellowasm:latest:                                            resolved       |++++++++++++++++++++++++++++++++++++++|manifest-sha256:cadcc8b07eb82b18db2c8f500fa2b11e5ebf2e9054cfa687e4ffe44861860132: done           |++++++++++++++++++++++++++++++++++++++|layer-sha256:ecda28441283ecf01d35bca0361f2c1ef26a203454a06789ee5ce71ba1e32ca3:    done           |++++++++++++++++++++++++++++++++++++++|config-sha256:57974480d640c8d60d254a8b0fa4606b2c7107fe169bc3ddd455091277c3a5e4:   done           |++++++++++++++++++++++++++++++++++++++|elapsed: 3.0 s                                                                    total:   0.0 B (0.0 B/s)unpacking linux/amd64 sha256:cadcc8b07eb82b18db2c8f500fa2b11e5ebf2e9054cfa687e4ffe44861860132...done$ sudo ctr run --rm --runtime io.containerd.wasm.v1 docker.io/denverdino/hellowasm:latest test1Hello world
复制代码


测试 Nginx 的 WASM 容器应用


$ sudo ctr image pull docker.io/denverdino/nginxwasm:latestdocker.io/denverdino/nginxwasm:latest:                                            resolved       |++++++++++++++++++++++++++++++++++++++|manifest-sha256:8735c82524a463b842b7c79f2c1be8094ee1c57cfd34154f68752fbe79c25998: exists         |++++++++++++++++++++++++++++++++++++++|layer-sha256:27f4d8ad067fbb709d18ea5acd7a5ddfb85851e5d9f030636e9da3d16cc4bd07:    done           |++++++++++++++++++++++++++++++++++++++|config-sha256:a55bd3bdb9d00fdac5ee2f64bfc1856e58e8bb90587943969ad3d8115f4ced70:   done           |++++++++++++++++++++++++++++++++++++++|elapsed: 3.0 s                                                                    total:   0.0 B (0.0 B/s)unpacking linux/amd64 sha256:8735c82524a463b842b7c79f2c1be8094ee1c57cfd34154f68752fbe79c25998...done$ sudo ctr run --rm --runtime io.containerd.wasm.v1 docker.io/denverdino/nginxwasm:latest test22020/02/01 07:01:21 [notice] 30672#0: using the "select" event method2020/02/01 07:01:21 [notice] 30672#0: nginx/1.15.32020/02/01 07:01:21 [notice] 30672#0: built by clang 6.0.1  (emscripten 1.38.11 : 1.38.11)2020/02/01 07:01:21 [notice] 30672#0: OS: Linux 4.19.812020/02/01 07:01:21 [notice] 30672#0: getrlimit(RLIMIT_NOFILE): 1024:1024
复制代码


在 Minikube 外部,可以用如下方式获得 nginx 应用的访问地址


$ echo http://$(minikube ip):8080http://192.168.64.13:8080
复制代码


利用浏览器打开上述地址,显示如下


创建 WASM 容器的 RuntimeClass CRD

为了将 WASM 容器可以被 Kubernetes 所调度,我们需要创建一个 RuntimeClass CRD


下载示例文件


$ git clone https://github.com/denverdino/wasm-container-samples$ cd wasm-container-samples
复制代码


注册 RuntimeClass “wasm”,这个值


$ cat wasm-runtimeclass.yamlapiVersion: node.k8s.io/v1beta1kind: RuntimeClassmetadata:  name: wasmhandler: wasm
$ kubectl apply -f wasm-runtimeclass.yamlruntimeclass.node.k8s.io/wasm created
$ kubectl get runtimeclasskubectl get runtimeclassNAME CREATED ATwasm 2020-02-01T06:24:12Z
复制代码

在 K8s 中运行 WASM 容器应用

在 K8s 应用的 yaml manifest 中,我们可以在 Pod Spec 上指明所需 runtimeClassName。下面我们就用 K8s 来部署一个 nginx 的 WASM 容器。


$ cat nginx-wasm.yamlapiVersion: v1kind: Podmetadata: name: nginx-wasmspec: runtimeClassName: wasm containers: - name: nginx   image: denverdino/nginxwasm   ports:     - containerPort: 8080
$ kubectl apply -f nginx-wasm.yamlpod/nginx-wasm created
$ kubectl get podNAME READY STATUS RESTARTS AGEnginx-wasm 1/1 Running 0 9s
复制代码

新机遇、新希望

目前为止,WebAssembly 技术仍处于初期阶段,WASI 也有很多局限性。但是社区的进展非常快,SIMD 指令支持,多线程处理等规范也正在快速演进中。WebAssembly 已经打破次元壁,将高性能的计算能力带领到 Web 浏览器端,越来越多的计算密集型的游戏、AI 模型预测、和数据处理应用被移植到浏览器端,可以为应用提供更加优化的用户体验。


WebAssembly 更广阔的空间在云计算领域、区块链等分布式计算领域。WebAssembly 轻量、敏捷、安全的特性,可以有效降低 Serverless 应用启动速度和资源消耗。同时 WebAssembly 的可移植,可以让应用一致运行在从云端服务器到边缘 IoT 设备等不同平台环境中,让计算无处不在。


利用 containerd 的扩展机制,可以为 WebAssembly 应用提供与其他容器应用一致的、抽象的、应用分发、交付和运维模型,可以在 Kubernetes 集群中进行统一调度和管理。希望通过类似的探索可以简化基于 WebAssembly 的分布式应用管理和运维。

后记

本文写在 2020 年的春节期间,这个春节注定将会被所有人铭记。众志成城,抗击疫情!天佑中华,武汉加油!


原文链接


https://developer.aliyun.com/article/744310


2020-03-07 10:236442

评论 1 条评论

发布
暂无评论
发现更多内容

【云原生 | 最佳实践】一个实践驱动的云原生项目集—KubeWharf

计算机魔术师

字节跳动 云原生

CentOS 7.8编译安装python 3.7教程。

百度搜索:蓝易云

Python Linux centos 运维 云服务器

助力企业上云降本增效,华为云这款产品有妙招

轶天下事

体育数据API接口:观看足球篮球比赛直播视频,获取即时比分数据

软件开发-梦幻运营部

性能卓越,部署无忧,华为云这款产品值得信赖

平平无奇爱好科技

华为云耀云服务器L实例:企业建站与小程序开发的绝佳选择

轶天下事

华为云耀云服务器L实例:专为中小企业量身打造的高性能云服务器

轶天下事

责任等同于背锅?

BY林子

Nacos配置中心脱敏

姚秋实(Nacol)

安全 nacos 架构设计 jasypt 配置中心

3D模型材质编辑

3D建模设计

3D纹理 3D材质 模型渲染

MATLAB实战 | S函数的设计与应用

TiAmo

matlab

【高效视频处理】一窥火山引擎多媒体处理框架-BMF

计算机魔术师

数字化转型新篇章:华为云耀云服务器L实例引领初创与成长型企业向前

平平无奇爱好科技

淘宝API接口与用户体验分析

联讯数据

数字化浪潮下云计算如何服务?华为云这款服务器用实力说话

平平无奇爱好科技

探索未来云计算,华为云耀云服务器L实例引领行业新动力

平平无奇爱好科技

高防服务器一般价格多少钱一台?

Geek_f19a80

服务器

CentOS7如何使用fail2ban防范SSH暴力破解攻击?

百度搜索:蓝易云

Linux centos SSH 云服务器 Fail2ban

传输黑科技下的全景之旅—浅谈开源项目E3PO的思路与功能

计算机魔术师

AI 与自然语言

天黑黑

大模型 LLM 提示词

回顾2023,展望2024——小工程师的执着

工程师日月

#技术人的2023总结

解锁中小企业上云智选,华为云这款服务器你值得拥有

平平无奇爱好科技

企业数字化创新发展,华为云这款服务器助力一键飞跃数字化巅峰

轶天下事

2023-12-02:用go语言,如何求模立方根? x^3=a mod p, p是大于等于3的大质数, a是1到p-1范围的整数常数, x也是1到p-1范围的整数,求x。 p过大,x不能从1到p-1遍

福大大架构师每日一题

福大大架构师每日一题

CSS技巧:从高度0过渡到自动高度

南城FE

CSS 前端 动画

数字化时代的利器:华为云服务器L实例助力初创企业稳健成长

平平无奇爱好科技

华为云耀云服务器L实例:智能、高性能、低成本的数字化助手

轶天下事

ZooKeeper应用场景综述

极客罗杰

WebAssembly 与 Kubernetes双剑合璧:机遇与挑战_大前端_阿里云容器平台_InfoQ精选文章