编者按:目前的安全容器软件栈 — 包括 host 操作系统中的 cgroup、guest 操作系统和用于函数工作负载的容器 rootfs,都会导致低部署密度和在低并发能力。为此,RunD 作为一种轻量级安全容器运行时,提出了 host-to-guest 的全栈优化方案来解决上述问题。
摘要
在轻量级虚拟机(MicroVM)中托管单个容器的安全容器现在已经广泛应用于无服务器计算。由于其中的用户函数大多为细粒度抽象,因此为了提高资源利用率和用户体验,Serverless 需要支持高密度的容器部署和高并发的容器启动。我们的调查显示,目前的安全容器软件栈 — 包括 host 操作系统中的 cgroup、guest 操作系统和用于函数工作负载的容器 rootfs,都会导致低部署密度和在低并发能力。为此,RunD 作为一种轻量级安全容器运行时,提出了 host-to-guest 的全栈优化方案来解决上述问题。使用 RunD 运行时,可以做到在一秒钟内启动超过 200 个安全容器,并且可以在一个 384GB 内存的节点上部署超过 2500 个安全容器。
一、介绍
函数计算作为无服务器计算(或者服务器无感知计算,Serverless)中的主要实现,通过隔离开发人员提供的细粒度函数并弹性管理使用资源,做到了更精细化的按量付费和更高的数据中心资源利用率。随着云原生技术的发展和微服务架构的流行,应用被越来越多的拆分成更细粒度的函数并部署为 Serverless 模式。
但基于传统容器技术隔离的函数计算由于其较低的隔离性和安全性,已经逐步被替换成结合 MicroVM 和容器的安全容器技术为应用提供强隔离性和低延迟响应。安全容器通常会在一个普通的容器外额外嵌套一层轻量级的 microVM 中,如下图1 (a)所示。通过这种方式,用户可以基于现有的容器基础设施和生态系统构建 Serverless 服务。安全容器能够确保与 MicroVM 中的容器运行时兼容。Kata Containers 和 FireCracker 都提供了实现这种安全容器的实践经验。
(图1/目前主流的安全容器模型,以及对应的软件栈架构)
在 Serverless 场景下,函数的轻量级和短期运行的特性使得高密度容器部署和高并发容器启动对于无服务器计算至关重要。例如,47% 的 Lambdas 在 AWS 上运行的最小内存规格是 128MB,在 Microsoft Azure 中,大约 90% 的应用程序的内存消耗从未超过 400MB。由于一个物理节点通常有很大的内存空间(如 384GB),它按理应该能够部署大量的容器设计。同时,大量的函数调用可能会在短时间内到达。但是,安全容器的额外开销大大降低了函数的部署密度和启动容器的并发性。
图1(b)显示了安全容器的软件栈层次结构。一般情况下,MicroVM 中的 guest 操作系统(GuestOS)和 host 上的资源调度都被转交给云提供商负责。rootfs 是一个文件系统,充当用户代码的执行环境。它是由 host 创建的,并传递给 microVM 中的容器运行时。在 host 端,cgroup 用于为安全容器分配资源,CPU 调度器负责管理资源分配。由此可见,安全容器的复杂层次结构必定会带来了复杂、高额的额外开销。
本文以 SOTA 的开源安全容器技术 Kata-containers 为出发点,通过深入分析从 host-to-guest 架构栈中的瓶颈点,提出了函数计算场景下安全容器高密高部署的 3 个关键观察和挑战:
- 容器的文件系统可以根据用户镜像只读和不需要持久化的特点进行定制;
- 客户机中的操作系统基础映像等可以在多个安全容器间共享和按需压缩以降低内存开销;
- 高并发创建 cgroup 会导致高同步时延,尤其在高密场景下带来的高调度开销。
为此我们提出了 RunD — 超轻量级安全容器运行时,通过全栈的 host-to-guest 解决方案以提供高密度部署和高并发能力的支持。RunD 通过引入读写分离的高效文件系统、预补丁和精简的 guest 内核以及一个全局可供维护的 lightweight cgroup 池以解决上述的三个高密高并发挑战。
根据我们的评估,RunD 启动到应用程序代码只需 88ms,并且每秒可以在一个节点上启动 200 个安全容器。在一个拥有 384GB 内存的节点上,可以使用 RunD 部署超过 2500 个安全容器。目前 RunD 已经作为 Alibaba 的 Serverless 容器运行时,服务超过 100 万个函数,每天调用近 40 亿次。在线统计数据表明,RunD 使得每个节点的最大部署密度已经超过 2000 个容器,并支持超过 200 个容器创建的快速端到端响应。
二、背景
通过以上介绍,我们了解了 RunD 。那么在本节中,我们将首先讨论当前安全容器的设计,以及为何需要引入 RunD 的需求。
2.1 安全容器模型
根据不同级别的安全/隔离需求,目前 Serverless 的生产环境中通常有两类主流的安全容器模型。图2(a)显示了”单虚拟机多容器“的安全容器模型。在该模型中,一个虚拟机(VM)承载着相同函数调用的容器,同一虚拟机中的容器共享虚拟机的 guest 操作系统。在这种情况下,对不同函数采用 VM 级别的隔离,但对同一函数的不同调用为 container 级别隔离。因为每个函数所创建和所需要的容器数量不同,该模型会导致潜在的内存碎片。虽然我们可以在运行时回收内存碎片,但这可能会严重影响函数性能,甚至在虚拟机内存热拔失败时导致程序崩溃。
(图2/两种主流的安全容器模型隔离)
图2(b)显示了隔离每个函数调用的“单虚拟机单容器”的安全容器模型。目前的无服务器计算提供商主要使用这种安全容器模型。在此模型中,每个调用都