查看原文
其他

黑客松Demo之二: 降低沙箱内存开销

Kata Kat KataContainers 2020-02-28

摘要: 在12月15-16日的第十届中国开源黑客松上,蚂蚁金服、阿里巴巴和Intel的开发者们一起做了一个Demo,来展示未来的 Kata 2.0 中可以用哪些技术来降低沙箱的内存开销。尽管由于会引入一些协议上的不兼容,所以这些技术无法全面地在 Kata 1.x 中引入,但是对负担较小的 2.0 新开发周期来说,这些尝试是非常有启发性的,并且这其中引入的相应组件都已经开源,甚至部分地集成到了 Kata 1.x 中。

关键词: Rust, ttRPC, Cloud-hypervisor

全链路内存开销分解

Kata Containers 的 slogan 里的一句就是"the speed of containers",性能与开销当然是 Kata 最关心的话题,不过,在消灭虚拟化引入的开销问题上,至今仍是“革命尚未成功,同志仍需努力”。虽然我们已经尽力减少了 Qemu 的内存占用(Qemu-lite, Nemu),避免了不必要的内核模块,用 kata-shim-v2 单一进程替换了批量的 containerd-shim + kata-shim + kata-proxy 的组合(参见这篇《Kata Containers: 两年而立》),但是,全链路的内存开销仍然不可忽视,及时不对照 runC,对比 gVisor 也是开销更多。

要想节约内存,首先需要了解如何内存是如何用掉的

每个 Kata Pod 沙箱占用的内存主要是由一个 shim-v2 进程和一个虚拟机监视器(以下缩写 VMM,最著名的 VMM 就是 Qemu)进程构成的,它们都会消耗内存,但是这之中,只有 VMM 内部的内存对用户来说是有影响(可见)的,而这之中,沙箱里的内核和 agent 是直接分享了应用内存但并不是应用的一部分,也就是说,这一部分是用户可见的开销。而 VMM 本身在宿主机上的开销以及 shim-v2 占用的内存,虽然用户应用不可见,但同样是 Kata 带来的开销,影响基础设施的资源效率。

这些内存开销里,还包括了可共享开销和不可共享开销。所有宿主这边的代码段内存(只读内存),可以共享 page cache,所以是共享的,而在沙箱里的代码(只读)内存,在使用 DAX 或模版的情况下,也可以共享同一份。所以,可以共享的内存开销在节点全局范围内是唯一一份,所以在有多个Pod的情况下,这部分的常数开销相对而言是不太重要的,相反的,不可共享开销,尤其是堆内存开销,会随着 Pod 的增长而增长,的换句话说,堆内存(匿名页)是最需要被重视的开销。

综上,第一位需要被遏制的开销是沙箱内的用户可见的不可共享开销,尤其是 Agent 的开销,而 VMM 和 shim 的匿名页开销次之。

目前可用的技术

Kata 诞生以来,第一位的努力目标就是确保和 Kubernetes 生态兼容,从付出的努力看,大概紧随其后的就是内存开销,这些工作分成两部分:一是正视开销,让调度和分配认识到这些开销的存在,比如在配置中预留分配给管理平面的资源、给 RuntimeClass 进行扩展,以使 Kubernetes 调度能感知到沙箱带来的开销等;另一部分就是千方百计从各个方面节约内存开销。

Rust vs Go

首先来看内存开销的重点——Kata Agent。Kata 1.x 的 agent 可以认为是 runV 的 hyperstart 的继承者,它使用了 libcontainer,从而保证了和 runC 的最大兼容性,同时 kata-agent 使用内存安全的 Go 编写,相对于用 C 写成的 hyperstart,先天地避免了很多内存风险。然而,在收获这些收益的同时,也带来了不小的内存开销,据观测,启动一个单容器的 Pod,kata-agent 会使用大概 11MB 的匿名内存页。

于是,在2019年5月的丹佛峰会上,Arch Committee 的 Eric 和王旭在讨论路线图的时候就不约而同地提出了能否用 Rust 改写 kata-agent。近几年,Rust作为一种无开销的内存安全语言,在系统领域备受瞩目,相对于 Go 来说,Rust 没有 runtime 带来的额外开销,因此是一个很被看好的方案。而且,由于有 kata-agent 作为对照组,可以通过 kata-agent 的集成测试来验证 rust-agent 的兼容性。

在本次黑客松之前,rust-agent 的测试版本已经可以工作,同样情况下的内存开销大概可以压缩到1.1MB,也就是 Go 版本 Agent 的1/10,在本次黑客松上,几位开发者希望可以把它和其他几个组件/变化集成起来使用。

Rust-VMM

2018年末,AWS 在 re:Invent 开源的 Firecracker 备受瞩目,这是一种低内存开销、无模拟设备模型的 VMM,正好是云计算领域期待的方向,当然,更重要的意义不在于代码本身,而是向业界传递了一种久违的对新 VMM 的信心——之前我们尝试过很多改造 qemu 以降低开销的方案,却没有迈出重写这一步,原因并不全是技术因素,也是没有用户勇敢地表态过愿意尝试,如今,AWS的实践给了大家这个信心,一时间应者云集,Kata 也迅速地支持了以 firecracker 作为 VMM 的方案。

当然,Firecracker 也并不是从零开始的工作,它是源于 crosvm 的,后者是 Google 开发的项目,用于桌面的 Chrome OS,这样,就有两个同源的 Rust 编写的 VMM 了。不过,虽然这两个项目都开放源代码并且乐于共享他们的设计元素,却不太希望社区贡献者扰乱他们各自的开发节奏。于是,Kata 的开发者们号召大家组成了一个称为 rust-vmm 的合作社区,将一些 firecracker, crosvm 共用的模块作为独立的包,放出来,有兴趣开发适合自己的 VMM 的人就可以用这些验证过的包作为基础了。除了 AWS 和 Google 外,其他的开发者,比如 Intel 和阿里巴巴,也对这个项目有积极的贡献。

然而,仅仅是一些组件并不能直接开箱即用,这对 Kata 来说是远远不够的,而且这也让 firecracker 和 crosvm 之外的开发者贡献的 rust-vmm 社区的包的测试变得很困难。在2019年5月,Denver 峰会上,Kata Arch Committee 的王旭和 Samuel 讨论之后,Intel 在会后不久将自己集成的 Rust VMM 项目 cloud-hypervisor 开源出来,并在不久之前把它放到了中立的 GitHub Organization 里。目前,cloud-hypervisor 的 Kata 集成工作正在进行之中。

gRPC vs ttRPC

Kata 0.x-1.x 的 shim 和 agent 通信使用的是在虚拟串口或 vsock 上的 gRPC 协议,后者是 Google 开发的,以 Protocol buffer 为跨语言、跨平台序列化格式的高性能 RPC协议和服务器,有原生的 Go 和 C++ 语言实现。在实现 rust-agent 的时候,为了保持兼容性同样需要支持 Rust 语言的 gRPC 服务器,最终,蚂蚁金服的朱辉修改了 PingCAP 的 grpc-rs 和上游的 gRPC C++ 库,使之可以在 vsock 上工作。

当然,在可靠的本机的 vsock 上工作,并且只需要传递控制面信息、没有大并发压力的时候,gRPC 听起来有点牛刀杀鸡了,其中包含的强大的 HTTP/2 服务器似乎有点过剩了——containerd 的开发者面对 unix socket 的时候曾经也是这么想的,于是,他们做了低配版的 ttRPC——低配更轻小。那么,rust-agent 能不能也用上 ttRPC 呢?

不过,用 ttRPC 替换 gRPC 做通信协议虽然技术上看起来可行,但是,破坏了跨版本兼容性,所以在 Kata 1.x 里是无法实现的,我们将这个替换瞄准了 Kata 2.0。为此,朱辉老师再接再厉,利用了 PingCAP 的 grpc-rs 的协议翻译代码,实现了一份 ttRPC 的 rust 版本,这个工作正在推进回 ttRPC 上游。

ttRPC 不仅轻小,而且,因为是原生实现,无需再链接 C++ 的 gRPC 库,替换之后的代码在测试中,大约可以从 gRPC 版本的 1.1MB 减少到 800KB 左右,跌至1MB以下。当然,对于目前的 firecracker/cloud-hypervisor 的实现,这个 ttRPC 库的工作并不完美,在黑客松开始前几天的准备中,蚂蚁金服的几个开发者也努力调查并给 firecracker/cloud-hypervisor 提出了改进方案。

Demo的方案和效果

综上,在这次黑客松中,蚂蚁金服、阿里巴巴和 Intel 的几位开发者努力解决剩余问题,来 Demo Kata 2.0 的内存节约候选方案—— rust-agent + ttRPC + cloud-hypervisor。

截止到黑客松结束,这三者已经可以联动工作了,Agent 侧的匿名内存页开销(不可共享开销)从 11MB 直降到 500-800KB,而沙箱 VMM 这边,在相同资源的 Pod 下,Pod启动后内存占用降低到 Qemu 的大约1/7,更多和更可靠的数据还需要进一步完善测试和测量。

不过,直到最后,仍有一个 cloud-hypervisor 独有的 DAX 性能问题尚未解决,留待未来解决。

未来的工作

在未来的开发中,首先要解决 cloud-hypervisor 的剩余性能问题,并完善测试数据,此外还要为面向云原生的虚拟化目标加入更多的弹性能力。这方面的工作将是 Kata 2.0 最受期待的工作之一,Kata Containers 社区欢迎你。


Modified on

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存