前言
随着 Serverless 概念的进一步普及,越来越多的企业用户开始将业务迁移到 Serverless 平台。通过 Serverless,用户可以聚焦业务实现。无需关注运维与基础设施,按需使用资源和付费 ,其中用户最大的收益体现在两个方面:
- "零"运维成本,将底层基础设施的运维工作交由平台提供方(云厂商)去完成;
- “零”资源浪费,无需常备资源,仅在需要运行业务的时候启动实例,在处理完逻辑之后释放资源,按使用量付费,降低云资源的使用成本。
Serverless 给云用户带来巨大收益的同时,也给云厂商带来了极大的挑战。首先云厂商需要提供稳定、强大的基础设施,帮用户维护好海量的实例;其次,按量付费,资源按需启动运行则要求云厂商提供足够强大的弹性能力,能够在短时间内为用户启动足够多的实例,让用户可以在业务高峰到来的时候迅速准备好服务予以应对,这样用户才会放心地将核心业务托管在 Serverless 产品上。
在今年的云栖大会上,阿里云的 Serverless 产品大放异彩,函数计算产品宣布支持 2 万函数实例 /min 的并发交付能力,而 ECI(弹性容器实例)的技术专家陈晓宇更是进行了现场演示,在 6 秒钟的时间内拉起了 3000 个弹性容器实例,向客户展示了阿里云强大的 Severless 弹性能力。
在演示过程中,晓宇介绍了 ECI 在管控调度上的优化方案,同时也介绍了支撑 ECI 的底层方案--袋鼠系统。本文将详细展开介绍袋鼠系统在阿里云强大基础设施上所做的优化,揭秘支持阿里云云原生 Serverless 快速弹性背后的底层技术。
云原生容器运行时
对于云厂商来说,Serverless 型产品需要有一个合适的运行时,提供以下基础的能力:
- 云原生生态兼容:Severless 是云原生的典型业务,对于云原生生态(k8s 体系)有很强的依赖,因此需要运行时能够无缝地与云原生生态无缝对接
- 具备强隔离能力:云厂商会服务众多不同的客户,因此一般单一物理机上需要运行多个不同客户的实例,特别是在 Serverless 场景下,实例的规格普遍偏小,物理机上服务的客户数量会更多。因此需要由运行时实现实例之间的绝对隔离,保障不同租户之间的数据安全和稳定性。
基于以上的诉求,kata containers 进入了我们的视线。kata containers 架构引入了沙箱容器的概念,通过硬件虚拟化技术和独立内核,提供了与 VM 同等级的多租隔离,另外通过 kata-shim-v2 接口,直接对接 contained 和 k8s,减少了重复构建、部署容器组件的开销,也能够较好地与开源的 k8s 生态(监控、metric、安全等)组件进行对接。
早在 2019 年,阿里云就基于 kata containers 架构进行 Serverless 服务的探索,将其用到了生产中去,即阿里云袋鼠沙箱容器 1.0 架构。在生产实践过程中,我们也发现了原生 kata containers 的一些不足:
- 首先是启动速度:由于硬件虚拟化和分离内核的存在,相比于普通容器,kata 容器需要额外增加虚拟化环境的建立时间、guest 内核启动时间、guest OS 内系统组件启动时间等,这些时间累加起来会极大的影响容器的扩容速度。虽然袋鼠沙箱 1.0 做了很多针对性的优化,将容器实例整体拉起时间(从containerd发起创建容器到 pause 容器 running)时间优化到了 800ms,但是相比普通容器还是有比较大的差距。
- 其次是资源开销:在 kata 容器默认推荐配置中,会预留 2G 的内存资源给 guest 内的管控资源或 guest kernel 使用。在实际应用过程中,即便袋鼠沙箱进行了大量的优化,最终整体的 guest 内开销还有 200M左 右,host 上也有接近 100M 左右的内存开销。
- 最后是稳定性:这是一个表征不明显但是影响极大的问题。相比于普通容器,kata containers 引入了更多的组件,包含 kata-shim,hypervisor、guest kernel、kata-agent 等等,众多组件极容易出现衔接异常引发的问题,主要体现在实例的创建、销毁等过程中。对此 kata-shim-v2 在一定程度上缓解了这个问题,但是在线上还是遇到过一些由于 shim-v2 和 hypervisor 之间的通信或者状态同步导致的稳定性问题。
以上的问题在 Serverless 场景下会被放大,比如文章开头的时候提到的极速并发能力,就需要运行时能够快速的启动实例,进而能够在短时间内尽量多地将容器准备好投入服务,而 800ms 的启动时间使得单机的并发能力受到了极大的限制;而 Severless 有大量的极小规格实例,像 ECI 就推出了 512M 内存的规格,在函数计算场景更是有 128M 的实例,如果运行时本身就有 200M 的开销,对于客户来说成本是不可接受的。同时,Serverless 实例的普遍运行时间很短,每日新增的实例创建是海量的,如果在创建、销毁过程中会出现大量问题的话,那是不具备稳定生产条件的。
基于以上遇到的问题,阿里云的袋鼠团队与蚂蚁的可信原生技术团队以 kata containers 为基础框架,推出了阿里云袋鼠沙箱容器 2.0:
- 用基于硬件虚拟化的轻量级沙箱替换传统的 vm,同时使用精简设备模型,并优化裁剪配置 Alibaba Cloud Linux kenrel,将整体软件栈各个组件打薄;
- 创新性地将 shim-v2 组件和沙箱管理单元融合到一个进程中,推出了全新的容器引擎 runD,将 shim 以及沙箱管理的通信从 gRPC 换成了 function call 以及 IPC;
- 打通基于 ebpf 的管控通道,实现shim对于沙箱内运行时的 upcall 机制;
- 使用阿里云全新推出的 LifSeaOS(ContainerOS)作为 guestOS;
- 采用 rust 语言全新开发,并集成kata rust agent,实现沙箱管控链路的rust改造。
架构优化带来的收益也是明显的。
通过管控链路的缩短以及组件的精简,并辅以对沙箱内存分配流程、host cgroup 管理流程和 IO 链路的优化,runD 实例的端到端启动时间(从 containerd 下发创建指令到 pause 容器拉起)缩短到了 300ms,并发能力达到了 200/s。进入 2021 年,袋鼠沙箱容器更是引入了沙箱实例复制技术,在实验室环境下将单实例端到端启动缩短到了 110ms,并发能力提升到了惊人的 360/s。在生产环境下,即便包含业务管控耗时,ECI 的实例启动时间也在1秒左右,单机并发达到了 50/s,支撑起了集群 3000/6s,5000/15s 的极速并发能力。
除了启动时间的收益,资源开销也有了显著的缩小,当前袋鼠沙箱容器内的资源 overhead 已经减少到 30M 左右,在产品上通过少量的资源“补偿”,即可实现用户的“零”overhead,所买即所得;同时 runD 在 host 上的资源开销缩减到了 2M 左右,实现了在单一物理机上的 2000 实例的高密服务能力。
除了性能、开销指标上的收益,新架构的使用也获得了组件能力的升级。首先 runD 实现了针对沙箱容器的全链路热升级能力,为产品的稳定性提供了兜底保障;同时使能了实例内资源热插、热拔的能力,可以实现针对单一实例的无损 VPA 能力。
袋鼠沙箱容器目前已经在阿里云上服务了数十款 Serverless 云产品,每日承接了上百万实例的创建、销毁流量,为用户提供了稳定、高效的运行时服务。而 runD 引擎也即将开源,我们期望通过社区化的运作,让更多的云原生场景能够通过开源的技术获得收益,敬请大家期待。
云原生底层系统
以上着重介绍了阿里云袋鼠沙箱容器 2.0 运行时,但是 Serverless 产品是整体的优秀表现,单靠一个运行时是不够的,需要有一套完整的系统方案进行支撑,袋鼠团队正是在致力于在打造这样一套包含运行时、单机存储、单机网络方案的阿里云云原生底层系统。
袋鼠沙箱容器运行在阿里云神龙平台上,享受神龙平台强大的 I 层能力。同时我们与 Alibaba Cloud Linux 的内核团队针对云原生 Serverless 场景进行了 Linux 内核深层次的优化,利用沙箱内 guest->runD->host kernel->神龙平台全栈优化,充分发挥阿里云强大的软、硬件基础设施结合能力带来的红利。
在针对 Serverless 业务进行特征分析和画像的过程中,我们详细刻画了 Serverless 带给云基础设施的压力。统计数据发现,绝大部分实例的运行时长都很短,以分钟甚至毫秒级为单位。再结合上文提到的大量 Serverless 用户会在云上使用小规格或者极小规格实例,以及瞬间并发的使用特征,如果给每一个 Severless 实例都分配一个传统的 VPC 网卡或者云盘,那么频繁的实例创建、销毁会对整体的网络、存储后端带来一系列严重的串扰。因此袋鼠团队构建了一套单机系统,能够覆盖单一物理机节点上的网络、存储,叠加于阿里云的基础网络和存储之上,以单机为粒度吸收 Serverless 带来的实例频繁创建、销毁的压力。
网络
针对 Severless 大量用户使用网络仅需要进行单向访问的特点(即容器不需要对外提供访问端口或者服务,仅需要访问 VPC 内的云服务或者 ECS),袋鼠团队设计研发了 ANSM(Alibaba Network Service Mesh)方案,将单物理机上 ENI 的创建频率直接降低为零。
基于 ANSM 网络方案,实例的网络建立时间由秒级下降到了 200ms,并且单售卖节点上的实例数量、服务用户的数量摆脱了 ENI 数量的限制,可以在一台物理机上调度任意用户的任意数量的 POD,在生产上最大 POD 数量可达 2000 以上。
存储
在存储上,袋鼠提供了基于 Devicemapper 的存储分割方案,利用该方案,一台售卖节点仅需要创建一次高规格的 ESSD 云盘,然后便可以利用 Devicemapper 的能力进行切割对外提供服务,这个方案将不同实例存储的建立时间由秒级优化到了毫秒级,同时使用块设备的形态提供给不同的用户,保障了用户之间数据的安全性。
镜像
在生产实践中,我们发现拉取容器镜像、解压容器镜像耗时很长,占据了实例整体端到端启动的大部分时间,因此 ECI 提供了 image cache 镜像缓存方案,将用户镜像缓存在快照之中,直接将这这部分时间清零。同时我们也在探索是否有可以让用户无感进行镜像拉取加速的方式,我们将关注点放到了 2016 年 Tyler Harter 在 FAST 会议上发表的题为《 Slacker: Fast Distribution with Lazy Docker Containers 》的演讲,在其演讲中阐述了他们的一个观测结果:容器启动阶段仅需要使用镜像中不到 7% 的数据。因此我们提出一种设想,是否可以有一种按需加载的镜像拉取手段,仅将必要的数据拉取到本地,减少不必要的数据传输,在提升实例启动性能的基础上,同步减少并发场景下对于镜像仓库的传输带宽的压力。
在 2021 年,阿里云袋鼠沙箱容器正式将 Nydus 方案用在了 Serverless 产品之上。Nydus 是一种新型容器镜像格式,基于 Nydus 镜像加速方案,可以实现:
- 容器镜像按需加载
- Chunk 级别的镜像数据去重
- 去除镜像分层,减少不同镜像层之间的重复数据
使用 Nydus 镜像加速方案之后,ECI 拉取 423M 大小的镜像(解压后 1.1G)时间由 20s 下降到了 0.8s,极大提升了实例启动性能。当前 Nydus 已经在 CNCF 开源,并且正在与社区一起推进下一代镜像格式,更多 Nydus 细节查看:https://github.com/dragonflyoss/image-service
小结
随着云服务厂商服务边界的逐步上移,Serverless 服务正在通过给用户提供更好的弹性、性能和成本能力帮助客户快捷的完成业务的部署、运维和扩缩容,而袋鼠作为阿里云 Serverless 运行时产品的软件系统底座,也在不断地探索以更快的启动时间、更高的并发能力和更强的运行时性能构建更强的 Servless 产品,为用户带来更多的价值。在此欢迎有识之士加入我们,一起构建硬核的云原生底层系统。
联系邮箱:shaokang.hwd@alibaba-inc.com
加入龙蜥社群
加入微信群:添加社区助理-龙蜥社区小龙(微信:openanolis_assis),备注【龙蜥】拉你入群;加入钉钉群:扫描下方钉钉群二维码。欢迎开发者/用户加入龙蜥社区(OpenAnolis)交流,共同推进龙蜥社区的发展,一起打造一个活跃的、健康的开源操作系统生态!
关于龙蜥社区
龙蜥社区(OpenAnolis)是由企事业单位、高等院校、科研单位、非营利性组织、个人等按照自愿、平等、开源、协作的基础上组成的非盈利性开源社区。龙蜥社区成立于 2020 年 9 月,旨在构建一个开源、中立、开放的Linux上游发行版社区及创新平台。
短期目标是开发龙蜥操作系统(Anolis OS)作为 CentOS 替代版,重新构建一个兼容国际 Linux 主流厂商发行版。中长期目标是探索打造一个面向未来的操作系统,建立统一的开源操作系统生态,孵化创新开源项目,繁荣开源生态。
龙蜥OS 8.4已发布,支持 x86_64 、ARM64、LoongArch 架构,完善适配 Intel、飞腾、海光、兆芯、鲲鹏、龙芯等芯片,并提供全栈国密支持。
欢迎下载:https://openanolis.cn/download
加入我们,一起打造面向未来的开源操作系统!