【云驻共创】多沙箱容器运行时Kuasar开发上手实践
前言
在一年一度的云原生开源领域顶级峰会KubeCon + CloudNativeCon Europe 2023
上,由华为云、中国农业银行、openEuler 社区和 CNCF 项目 WasmEdge 等联合发起的云原生多沙箱容器运行时 Kuasar 正式宣布开源,受到云原生社区、Rust 社区和云厂商们的广泛关注和热烈讨论。
全新云原生开源项目Kuasar,其结合了华为云多年生产业务实践以及对沙箱技术发展的思考,基于业界新兴的沙箱接口实现。在保留传统容器运行时功能的基础上,Kuasar通过全面Rust化以及优化管理模型和框架等手段,进一步降低管理开销、简化调用链路,灵活扩展对业界主流沙箱技术的支持,实现云原生业务场景全覆盖。此外,通过支持多安全沙箱共节点部署,Kuasar可以充分利用节点资源、降本增效,为用户提供更安全高效的沙箱场景解决方案。
沙箱容器的发展
容器时代
早在 2013 年,docker 横空出世,标志着容器时代到来。最初的容器技术,其实就是利用 Linux 内核提供的命名空间 Namespace 和控制组 Cgroup 功能,实现容器进程之间的资源隔离和限制。在容器时代,容器就是 docker 里唯一的一等公民。
不久,2014年,容器编排领域诸侯争霸,随着 Kubernetes 最终成为主流的容器编排工具,Pod也成为容器编排领域的一等公民,为了兼容 Pod 这一概念,docker 引入了 pause 容器。
然而,pause 容器的引入常常让开发者感到困惑,因为 Pod 与 pause 容器之间存在着很多差异。在 kubernetes 中,Pod 是一组容器逻辑和物理资源的载体,而 pause 容器只是提供了容器间共享的 namespace 而已。此外,容器运行时里有很多冗余和复杂的判断逻辑用于区分 pause 容器和用户容器,使得代码阅读和开发变得困难。
2019年,containerd从 CNCF 毕业,目前已在 kubernetes中成为首选的容器运行时,同样 containerd 也需要借助 pause 容器来运行一个 Pod。
由于runC容器与宿主机系统共享内核,一旦发生容器逃逸,尤其是在多租场景下,将带来巨大的安全隐患。
沙箱崛起
随着上述问题的出现,也陆续出现相关的解决方案。时间来到2018年,云原生领域飞速发展,许多沙箱(Sandbox)隔离技术都被应用到容器领域,沙箱容器如火如荼。沙箱容器将容器进程限制在一个封闭的沙箱环境中,防止其对系统和其他容器造成破坏,具有极高的安全性。沙箱天然符合 Pod 的定义,它为一组容器提供了一个隔离的环境,在沙箱环境中运行的容器,就是沙箱容器。
根据沙箱隔离的边界可分为轻量虚拟机沙箱(MicroVM Sandbox)、用户态内核沙箱(Application Kernel Sandbox)和WebAssembly 沙箱(Wasm Sandbox)。它们都是为满足不同业务需求而孵化的产物,所以它们在不同的维度上有着各自的优势。
轻量虚拟机沙箱(MicroVM Sandbox):在宿主机上模拟一套完整的虚拟机,容器运行在虚拟机内,具有非常高的安全隔离效果。
用户态内核沙箱(Application Kernel Sandbox):通过一个运行在用户态的内核程序,拦截并实现容器的系统调用,从而保证容器间的安全隔离性。
WebAssembly 沙箱(Wasm Sandbox):将容器运行在 WebAssembly 的运行时中,依赖 WebAssembly 的能力提供进进程级别的隔离。
每种沙箱在极速弹性、安全隔离和标准通用维度有各自的优势,目前云厂商都已在生产环境布局了沙箱容器产品,每个沙箱借助 containerd Shim v2
均实现了一套管理面的程序,彼此之间不相兼容。
2023年 3 月,containerd
在其 v1.7.0
版本中发布了 Sandbox API
特性,该特性提供了一套管理沙箱的 API ,它的出现使得容器和沙箱的概念解耦,“容器归容器,沙箱归沙箱”,创建 Pod 就是创建沙箱,不再需要借助 pasue 容器。
沙箱容器已成为云原生场景下的安全解决方案,我们希望借助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
项目官网:https://kuasar.io
Kuasar定位
Kuasar 是一个多沙箱容器运行时,那么什么是容器运行时?简单说容器运行时是一个负责拉起容器,管理容器运行状态的运行时组件,可以分为高阶容器运行时和低阶容器运行时两类:
- 高阶容器运行时:负责 CRI 的实现,从高维度管理容器和镜像实例,containerd, CRI-O, docker 还有 iSulad 都是典型的高阶容器运行时。
- 低阶容器运行时:负责 OCI 实现,真正操作容器。Kata-containers 和 runC 等都是低阶容器运行时。
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 Hypervisor、 StratoVirt、 Firecracker 和QEMU。在 MicroVM Sandboxer 中, vmm-sandboxer 负责创建虚机和调用 API vmm-task 作为虚机里的 init 进程负责拉起容器进程,容器的 IO 流则可通过虚机的 vsock 或 uds 导出。
目前仅支持 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 中的所有容器都将在同一个进程中运行。
目前仅支持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 资源。
目前仅支持 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. 这种模型可以大大减少常驻进程的数量,整个架构也因此变得更清晰简洁。
Kuasar改变当前的Shim V2 的管理模型,带来以下收益:
- sandbox管理逻辑清晰:sandbox 管理逻辑和 container 管理逻辑完全分开,开发友好,语义清晰。
- 简化 container 调用链:取消 Task API 到 Shim v2 API 的转化,直接调用,链路简化。
- 高效的 sandboxer 进程: Sandboxer 进程常驻减掉了冷启动 Shim 进程的耗时, 1:N 管理模型大幅减少了进程数量,Rust 程序内存安全,相比 Golang 开销小。
- pause 容器消失:创建 Pod 不再创建 pause 容器,不再需要准备 pause 容器镜像快照。
性能表现
那么 Kuasar 的性能表现究竟如何呢?选择大家最关心的“端到端容器启动时间”和“管理面组件内存消耗”作为衡量 Kuasar 性能的两个指标,具体定义如下:
- 端到端容器启动时间:在 containerd v1.7.0 的 CRI 实现中,摒弃了将沙箱伪装成容器的做法,改用 Sandbox API 新特性来创建沙箱和启动容器,因此我们需要以 CRI 为入口,实际测试端到端拉起一个容器进程所需要的时间。
- 管理面组件内存消耗:测量管理组件的内存消耗(不包括虚机),即对比Sandboxer 进程和所有 Shim v2 进程的 PSS 内存( Proportional Set Size )。PSS是单个进程运行时实际占用的物理内存,包含共享库按比例分配后占用的内存。
控制如下变量:
- VMM 、 Guest OS (除 init 进程)、 Guest Kernel 保持一致。
- 容器镜像相同,并直接使用本地镜像快照。
- 容器存储驱动均采用 Overlayfs。
- 容器网络为 HostNetwork 模式。
启动时间测试
启动时间测试分为两组,一组统计单个 Pod 的启动时间,另一组统计并行启动50个 Pod 的时间:
Kuasar 100% 的启动速度提升主要得益于两方面,一方面是 Sandbox API 的实现,使得创建容器不再单独创建 pause 容器,节省了准备pause容器镜像快照的时间;另一方面得益于1:N 的管理模型,Sandboxer 进程常驻,从而节省了冷启动 Shim 进程的时间,这使得容器的启动速度大大提升。
内存消耗测试
内存消耗测试共分三轮,每轮分别启动了1、5、10、20、30和50个Pod,查询Sandboxer 进程和所有 Shim 进程的 PSS 数值。
Kuasar 节省近99%的内存,原因也可分为两点:主要是 1:N 的管理模型使得 N 个进程减少为1个进程,带来的内存收益与 Pod 数成正比;其次,Kuasar 采用了 Rust 编程语言,相比于 Kata Shim 进程使用的 Golang 语言,语言本身也会带来一些内存收益。
Kuasar 安装部署
预准备
在安装配置前需要大家预准备以下内容:
其余具体构建需求可参考官网和Github地址:
官方地址:https://kuasar.io/docs/developer/build/
Github地址:https://github.com/kuasar-io/kuasar
安装部署
下载并源码编译
安装部署可参考Github地址:https://github.com/kuasar-io/kuasar
操作命令:
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
运行组件
启动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 才生效
运行容器
根据说明文档,我们可直接运行代码仓提供的脚本进行测试。
准备好所演示的镜像:
运行vmm沙箱
bash examples/run_example_container.sh vmm
测试容器的访问:
运行quark沙箱
bash examples/run_example_container.sh quark
测试容器的访问:
运行wasm沙箱
bash examples/run_example_wasm_container.sh
查看现有Pod和清空演示
总结
Kuasar作为新一代的容器运行时,不再采用通过 shim v2 接口来管理 Pod,取而代之的是 Kuasar 向容器引擎提供的新一代容器运行时 Pod 管理接口 Sandbox API。这套接口不仅逻辑更加清晰,而且可以支持多沙箱接入。每一种 Sandboxer 都使用了自己的容器隔离技术,用来管理同一类型的 Pod。而Kuasar 将发挥沙箱接口的优势,拥抱业界最新的 DRA(Dynamic Resource Allocation)、CDI(Container Device Interface) 等管理接口,为云原生场景带来更安全、高效、便捷的容器解决方案,为云原生应用提供更安全的保障。
Reference
Kuasar Github:https://github.com/kuasar-io
Kuasar官网:https://kuasar.io
本文参与华为云社区【内容共创】活动第22期。
【内容共创】活动第22期活动详情:https://bbs.huaweicloud.com/blogs/402312
- 点赞
- 收藏
- 关注作者
评论(0)