【云驻共创】多沙箱容器运行时Kuasar开发上手实践

【摘要】在云原生技术发蓬勃发展的时代,底层承载应用的容器很重要,然而,单一容器隔离技术已经无法满足各种场景的要求,不同的场景都需要不同的容器形态来承载,从而产生了不同的沙箱技术。本文结合沙箱容器发展的历程,介绍华为云多沙箱容器运行时 Kuasar 项目的优势,并为开发者演示 Kuasar 的安装运行方式,开启多沙箱容器运行时的上手实践体验!

前言

在一年一度的云原生开源领域顶级峰会KubeCon + CloudNativeCon Europe 2023上,由华为云、中国农业银行、openEuler 社区和 CNCF 项目 WasmEdge 等联合发起的云原生多沙箱容器运行时 Kuasar 正式宣布开源,受到云原生社区、Rust 社区和云厂商们的广泛关注和热烈讨论。

全新云原生开源项目Kuasar,其结合了华为云多年生产业务实践以及对沙箱技术发展的思考,基于业界新兴的沙箱接口实现。在保留传统容器运行时功能的基础上,Kuasar通过全面Rust化以及优化管理模型和框架等手段,进一步降低管理开销、简化调用链路,灵活扩展对业界主流沙箱技术的支持,实现云原生业务场景全覆盖。此外,通过支持多安全沙箱共节点部署,Kuasar可以充分利用节点资源、降本增效,为用户提供更安全高效的沙箱场景解决方案。


沙箱容器的发展

容器时代

image-20230703160021362.png

早在 2013 年,docker 横空出世,标志着容器时代到来。最初的容器技术,其实就是利用 Linux 内核提供的命名空间 Namespace 和控制组 Cgroup 功能,实现容器进程之间的资源隔离和限制。在容器时代,容器就是 docker 里唯一的一等公民。

image-20230703160041595.png

不久,2014年,容器编排领域诸侯争霸,随着 Kubernetes 最终成为主流的容器编排工具,Pod也成为容器编排领域的一等公民,为了兼容 Pod 这一概念,docker 引入了 pause 容器。

然而,pause 容器的引入常常让开发者感到困惑,因为 Pod 与 pause 容器之间存在着很多差异。在 kubernetes 中,Pod 是一组容器逻辑和物理资源的载体,而 pause 容器只是提供了容器间共享的 namespace 而已。此外,容器运行时里有很多冗余和复杂的判断逻辑用于区分 pause 容器和用户容器,使得代码阅读和开发变得困难。

2019年,containerd从 CNCF 毕业,目前已在 kubernetes中成为首选的容器运行时,同样 containerd 也需要借助 pause 容器来运行一个 Pod。

image-20230703175933767.png

由于runC容器与宿主机系统共享内核,一旦发生容器逃逸,尤其是在多租场景下,将带来巨大的安全隐患。


沙箱崛起

随着上述问题的出现,也陆续出现相关的解决方案。时间来到2018年,云原生领域飞速发展,许多沙箱(Sandbox)隔离技术都被应用到容器领域,沙箱容器如火如荼。沙箱容器将容器进程限制在一个封闭的沙箱环境中,防止其对系统和其他容器造成破坏,具有极高的安全性。沙箱天然符合 Pod 的定义,它为一组容器提供了一个隔离的环境,在沙箱环境中运行的容器,就是沙箱容器

根据沙箱隔离的边界可分为轻量虚拟机沙箱(MicroVM Sandbox)、用户态内核沙箱(Application Kernel Sandbox)和WebAssembly 沙箱(Wasm Sandbox)。它们都是为满足不同业务需求而孵化的产物,所以它们在不同的维度上有着各自的优势。

  • 轻量虚拟机沙箱(MicroVM Sandbox):在宿主机上模拟一套完整的虚拟机,容器运行在虚拟机内,具有非常高的安全隔离效果。

  • 用户态内核沙箱(Application Kernel Sandbox):通过一个运行在用户态的内核程序,拦截并实现容器的系统调用,从而保证容器间的安全隔离性。

  • WebAssembly 沙箱(Wasm Sandbox):将容器运行在 WebAssembly 的运行时中,依赖 WebAssembly 的能力提供进进程级别的隔离。

image-20230703163015164.png

每种沙箱在极速弹性、安全隔离和标准通用维度有各自的优势,目前云厂商都已在生产环境布局了沙箱容器产品,每个沙箱借助 containerd Shim v2均实现了一套管理面的程序,彼此之间不相兼容。

image-20230703163609606.png

2023年 3 月,containerd 在其 v1.7.0 版本中发布了 Sandbox API特性,该特性提供了一套管理沙箱的 API ,它的出现使得容器和沙箱的概念解耦,“容器归容器,沙箱归沙箱”,创建 Pod 就是创建沙箱,不再需要借助 pasue 容器。

image-20230703164309361.png

沙箱容器已成为云原生场景下的安全解决方案,我们希望借助Sandbox API 的力量,实现一种支持多种沙箱技术的容器运行时。


Kuasar 项目简介

项目简介

Sandbox API 的出现使得沙箱成为容器世界新的一等公民,我们需要一个支持多种主流沙箱技术的容器运行时,同时具有可扩展、可维护、可演进机制。因此,Kuasar 应运而生。

华为云于2023 年 4 月在荷兰阿姆斯特丹举办的KubeCon + CloudNativeCon Europe 2023云原生峰会上正式开源Kuasar 。新开源的多沙箱容器运行时 Kuasar 可以充分利用节点资源、降本增效,为用户提供更安全高效的沙箱场景解决方案。

Kuasar 是一个基于 Rust 语言开发,可以同时支持多种主流沙箱隔离技术的容器运行时,具有以下特点:

  • 对沙箱友好:基于 Sandbox API 接口开发,区别于当前的 Shim v2 接口,对沙箱的定义和生命周期管理有天然优势。
  • 多沙箱混部:集成多种主流沙箱技术,可以在单个节点上运行多种不同类型的沙箱容器。
  • 简化的模型:采用了 1:N 的容器进程管理模型,对比目前 Shim 进程 1:1 的做法,带来了 100% 启动速度提升和 99% 内存开销优化。

Github地址https://github.com/kuasar-io/kuasar

image-20230703170203846.png


项目官网https://kuasar.io

image-20230703170723726.png


Kuasar定位

Kuasar 是一个多沙箱容器运行时,那么什么是容器运行时?简单说容器运行时是一个负责拉起容器,管理容器运行状态的运行时组件,可以分为高阶容器运行时和低阶容器运行时两类:

  • 高阶容器运行时:负责 CRI 的实现,从高维度管理容器和镜像实例,containerd, CRI-O, docker 还有 iSulad 都是典型的高阶容器运行时。
  • 低阶容器运行时:负责 OCI 实现,真正操作容器。Kata-containers 和 runC 等都是低阶容器运行时。

image-20230703175846432.png

Kuasar 属于低阶容器运行时,和高阶容器运行 containerd 交互,Kuasar 主要由两个模块组成:

  • Kuasar-Sandboxer:实现了 Sandbox API,负责管理沙箱生命周期和资源分配。Sandboxer 以插件的形式和 containerd 交互。
  • Kuasar-Task:实现了 Task API,负责管理容器的生命周期和资源分配。

目前,在北向接口层面,Kuasar 正在与 containerd 联合构建最新的沙箱接口标准,sandboxer 插件已经加入 containerd v2.0 的版本路标;此外,OpenEuler 社区的轻量级容器引擎 iSulad 项目也已经完成与 Kuasar 项目的对接。而在南向沙箱层面,Kuasar 已经支持包括 Cloud Hypervisor(MicroVM 类)、WasmEdge(Wasm 类)、StratoVirt(MicroVM 类)、Quark(App Kernel类)在内的多类主流安全沙箱。并已在Roadmap中计划支持更多的沙箱,在未来可以适应更多的云原生场景。


MicroVM Sandboxer

在轻量级虚机场景,虚机进程提供了完整的虚拟化层和Linux 内核,此类的虚机包括 Cloud HypervisorStratoVirtFirecrackerQEMU。在 MicroVM Sandboxer 中, vmm-sandboxer 负责创建虚机和调用 API vmm-task 作为虚机里的 init 进程负责拉起容器进程,容器的 IO 流则可通过虚机的 vsock 或 uds 导出。

image-20230703180046968.png

目前仅支持 Cloud Hypervisor, QEMU 和 StratoVirt。


App Kernel Sandboxer

App Kernel Sandbox将 KVM 虚拟化层和 Guest 内核深度融合成一个用户态内核进程,通过拦截容器系统调用实现容器隔离。典型代表包括 gVisor 和 Quark 。

Quark 是一款App Kernel沙箱,使用自己的 QVisor hypervisor 和自定义内核 QKernel。QVisor 只负责KVM虚拟机的生命周期管理,并不模拟任何设备。Qkernel 拦截所有的 syscall,在需要的情况下,通过 VM_Exit 或者 eventfd 通知 QVisor 处理。通过将主机进程的内存空间映射到 VM 的物理内存空间中,实现 QVisor 和 QKernel 的内存共享。

App Kernel Sandboxer 的 quark-sandboxer 拉起 Qvisor 和 Qkernel,每当 containerd 需要在沙箱中启动一个容器时,QVisor 中的 quark-task 将调用 Qkernel 来启动一个新的容器。同一 Pod 中的所有容器都将在同一个进程中运行。

image-20230703180754844.png

目前仅支持Quark。


Wasm Sandboxer

如果说 App Kernel 沙箱是在虚拟化和内核层面实现了一套隔离沙箱技术,那么WebAssembly 沙箱则是定义了一套新的体系结构,包含一套指令集和虚拟机。所有程序必须编译成 WebAssembly 指令集才能在 WebAssembly 虚拟机中运行。因此对应用程序有很高的要求,常见的 Wasm 沙箱有 WasmEdge 和 Wasmtime 。

wasm-sandboxer 和 wasm-task 在 WebAssembly 沙箱内启动容器。当 containerd 需要在沙箱中启动容器时,wasm-task 将 fork 一个新进程,启动一个新的 WasmEdge runtime,并在其中运行 Wasm 代码。同一 Pod 内的所有容器都将与 wasm-task 进程共享相同的 Namespace 和 Cgroup 资源。

image-20230703181104620.png

目前仅支持 WasmEdge。受到某些技术限制(主要是标准输入输出无法重定向),wasm-task 使用 fork 的方式新启动一个 runtime。后续演进可能会选择直接在进程内启动 runtime ,实现更快速地启动和更低的内存占用。


Kuasar管理模型的变化

在目前容器运行时的 Shim v2 模型中,containerd 每创建一个 Pod,就要创建一个对应的 Shim 进程用于 Pod 的管理,Shim 进程再去创建虚机和容器,在这种场景下,管理面 Shim 进程和 Pod 的数量关系为1:1。

但在 Kuasar 中,只需要运行一个 Kuasar-Sandboxer 进程,containerd 对 Pod 的管理都是调用 Sandboxer 对外暴露的接口,不再需要为每个 Pod 都拉起一个管理进程,因此,管理面 Sandboxer 进程和 Pod 的数量关系为 1:N. 这种模型可以大大减少常驻进程的数量,整个架构也因此变得更清晰简洁。

image-20230703181807237.png

Kuasar改变当前的Shim V2 的管理模型,带来以下收益:

  1. sandbox管理逻辑清晰:sandbox 管理逻辑和 container 管理逻辑完全分开,开发友好,语义清晰。
  2. 简化 container 调用链:取消 Task API 到 Shim v2 API 的转化,直接调用,链路简化。
  3. 高效的 sandboxer 进程: Sandboxer 进程常驻减掉了冷启动 Shim 进程的耗时, 1:N 管理模型大幅减少了进程数量,Rust 程序内存安全,相比 Golang 开销小。
  4. pause 容器消失:创建 Pod 不再创建 pause 容器,不再需要准备 pause 容器镜像快照。

性能表现

那么 Kuasar 的性能表现究竟如何呢?选择大家最关心的“端到端容器启动时间”和“管理面组件内存消耗”作为衡量 Kuasar 性能的两个指标,具体定义如下:

  • 端到端容器启动时间:在 containerd v1.7.0 的 CRI 实现中,摒弃了将沙箱伪装成容器的做法,改用 Sandbox API 新特性来创建沙箱和启动容器,因此我们需要以 CRI 为入口,实际测试端到端拉起一个容器进程所需要的时间。
  • 管理面组件内存消耗:测量管理组件的内存消耗(不包括虚机),即对比Sandboxer 进程和所有 Shim v2 进程的 PSS 内存( Proportional Set Size )。PSS是单个进程运行时实际占用的物理内存,包含共享库按比例分配后占用的内存。

image-20230703182912215.png

控制如下变量:

  • VMM 、 Guest OS (除 init 进程)、 Guest Kernel 保持一致。
  • 容器镜像相同,并直接使用本地镜像快照。
  • 容器存储驱动均采用 Overlayfs。
  • 容器网络为 HostNetwork 模式。

启动时间测试

image-20230703183433601.png

启动时间测试分为两组,一组统计单个 Pod 的启动时间,另一组统计并行启动50个 Pod 的时间:

Kuasar 100% 的启动速度提升主要得益于两方面,一方面是 Sandbox API 的实现,使得创建容器不再单独创建 pause 容器,节省了准备pause容器镜像快照的时间;另一方面得益于1:N 的管理模型,Sandboxer 进程常驻,从而节省了冷启动 Shim 进程的时间,这使得容器的启动速度大大提升。


内存消耗测试

image-20230703183528578.png

内存消耗测试共分三轮,每轮分别启动了1、5、10、20、30和50个Pod,查询Sandboxer 进程和所有 Shim 进程的 PSS 数值。

Kuasar 节省近99%的内存,原因也可分为两点:主要是 1:N 的管理模型使得 N 个进程减少为1个进程,带来的内存收益与 Pod 数成正比;其次,Kuasar 采用了 Rust 编程语言,相比于 Kata Shim 进程使用的 Golang 语言,语言本身也会带来一些内存收益。


Kuasar 安装部署

预准备

在安装配置前需要大家预准备以下内容:

image-20230704141422102.png

其余具体构建需求可参考官网和Github地址:
官方地址:https://kuasar.io/docs/developer/build/
Github地址:https://github.com/kuasar-io/kuasar

image-20230707095618287.png


安装部署

下载并源码编译

安装部署可参考Github地址:https://github.com/kuasar-io/kuasar

image-20230707095708348.png

操作命令:

git clone https://github.com/kuasar-io/kuasar.git
cd kuasar
make all
make install

注:Guest OS 镜像需在容器里编译,故需要启动 containerd 或其他容器运行时。


配置 cotainerd

containerd的配置文件 /etc/containerd/config.toml 中需要新增三个 runtime,分别是vmm、quark、wasm:

[proxy_plugins.vmm ]
  type = "sandbox"
  address = "/run/vmm-sandboxer.sock"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.vmm]
  runtime_type = "io.containerd.kuasar.v1"
  sandboxer = "vmm"
  io_type = "hvsock"
[proxy_plugins.quark ]
  type = "sandbox"
  address = "/run/quark-sandboxer.sock"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.quark]
  runtime_type = "io.containerd.quark.v1"
  sandboxer = "quark"
[proxy_plugins.wasm ]
  type = "sandbox"
  address = "/run/wasm-sandboxer.sock"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.wasm]
  runtime_type = "io.containerd.wasm.v1"
  sandboxer = "wasm"

不支持AppArmor特性,因此还需要配置 disable_apparmor = true

image-20230707112123151.png


运行组件

启动kuasar

使用以下命令启动kuasar:

对于vmm: nohup vmm-sandboxer --listen /run/vmm-sandboxer.sock --dir /run/kuasar-vmm &
对于quark: nohup quark-sandboxer --listen /run/quark-sandboxer.sock --dir /var/lib/kuasar-quark &
对于wasm: nohup wasm-sandboxer --listen /run/wasm-sandboxer.sock --dir /run/kuasar-wasm &

配置containerd环境变量

ENABLE_CRI_SANDBOXES=1 containerd ,Sandbox API 必须设置环境变量 ENABLE_CRI_SANDBOXES=1 才生效

image-20230707142513839.png


运行容器

根据说明文档,我们可直接运行代码仓提供的脚本进行测试。

image-20230707143418833.png

准备好所演示的镜像:

image-20230707144250934.png


运行vmm沙箱

bash examples/run_example_container.sh vmm

image-20230707144612228.png


测试容器的访问:

image-20230707145248796.png


运行quark沙箱

bash examples/run_example_container.sh quark

image-20230707145603676.png

测试容器的访问:

image-20230707145724035.png


运行wasm沙箱

bash examples/run_example_wasm_container.sh

image-20230707152043414.png

查看现有Pod和清空演示

image-20230707152511018.png


总结

Kuasar作为新一代的容器运行时,不再采用通过 shim v2 接口来管理 Pod,取而代之的是 Kuasar 向容器引擎提供的新一代容器运行时 Pod 管理接口 Sandbox API。这套接口不仅逻辑更加清晰,而且可以支持多沙箱接入。每一种 Sandboxer 都使用了自己的容器隔离技术,用来管理同一类型的 Pod。而Kuasar 将发挥沙箱接口的优势,拥抱业界最新的 DRA(Dynamic Resource Allocation)、CDI(Container Device Interface) 等管理接口,为云原生场景带来更安全、高效、便捷的容器解决方案,为云原生应用提供更安全的保障。


Reference

Kuasar Githubhttps://github.com/kuasar-io

Kuasar官网https://kuasar.io


本文参与华为云社区【内容共创】活动第22期。

【内容共创】活动第22期活动详情:https://bbs.huaweicloud.com/blogs/402312

任务19.[DTSE Tech Talk 技术直播 NO.28 多沙箱容器运行时Kuasar开发上手实践]

猜你喜欢

转载自blog.csdn.net/qq_41765918/article/details/131768187