当前 Serverless 容器的行业趋势如何?有哪些应用价值?如果 Kubernetes 天生长在云上,它的架构应该如何设计?Serverless 容器需要哪些基础设施?阿里云容器服务产品负责人易立及阿里云 Serverless Kubernetes 产品 TL 张维将分享他们对 Serverless 容器架构和背后的关键思考。
从 Serverless 容器到 Serverless Kubernetes
Serverless(无服务器)容器是让用户无需购买和管理服务器直接部署容器应用的产品、技术形态。Serverless 容器可以极大提高容器应用部署的敏捷度和弹性能力,降低用户计算成本;让用户聚焦业务应用而非底层基础设施管理,极大地提高应用开发效率,降低运维成本。
目前 Kubernetes 已经成为业界容器编排系统的事实标准,基于 Kubernetes 的云原生应用生态(Helm, Istio, Knative, Kubeflow, Spark on K8s 等)更是让 Kubernetes 成为云操作系统。一方面通过 Serverless 方式根本性解决 K8s 自身的管理复杂性,让用户无需受困于 K8s 集群容量规划、安全维护、故障诊断;一方面进一步释放了云计算的能力,将安全、可用性、可伸缩性等需求由基础设施实现,这样可以形成差异化竞争力。
行业趋势
Gartner 预测到 2023 年,70% AI 任务会通过容器、Serverless 等计算模型构建。在 AWS 的调研中,在 2019 年 40% 的 ECS(AWS 弹性容器服务)新用户采用 ECS on Fargate 的 Serverless Container 形态。
Serverless 容器是现有 Container as a Service 的进化方向之一,可以和 fPaaS/FaaS (Function as a Service) 形成良好的互补。FaaS 提供了事件驱动的编程方式,用户只需实现函数的处理逻辑,比如当接收到用户上传的一个视频时,对视频进行转码和加水印。FaaS 方式开发效率很高,也可以将弹性发挥到极致,但需要用户改变现有的开发模式来进行适配。而 Serverless Container 应用的载体是容器镜像,灵活性很好,配合调度系统可以支持各种类型应用,比如无状态应用、有状态应用、计算任务类应用等等。用户大量现有的应用无需修改即可部署在 Serverless Container 环境中。
图源:https://blogs.gartner.com/tony-iams/containers-serverless-computing-pave-way-cloud-native-infrastructure/
Gartner 报告中也谈到 Serverless 容器业界标准未定,云厂商有很多空间通过技术创新提供独特的增值能力,其对云厂商的建议是:
- 扩展 Serverless 容器应用场景和组合,迁移更多普通容器 workload 到 Serverless 容器服务。
- 推进 Serverless 容器的标准化,减轻用户对云厂商锁定的担忧。
典型场景与应用价值
自阿里云 ASK/ECI 从 2018 年 5 月份正式公测以来,我们非常高兴的看到 Serverless 容器的价值逐渐被用户认可。典型应用场景包括:
在线业务弹性扩容
基于 ASK 支撑在线业务弹性扩容,在 30s 之内可以极速扩容 500 个应用实例,轻松应对预期和非预期突发流量。比如此次疫情时期多个在线教育平台使用 ASK/ECI 超强弹性能力轻松面对业务高峰。
免运维 Serverless AI 平台
基于 ASK 开发的智能、免运维的 AI 应用平台,可以让开发者创建自己的算法模型开发环境,而平台则会按需弹性伸缩,极大减少了系统维护和容量规划复杂性。
Serverless 大数据计算
基于 ASK 构建 Serverless 大数据计算平台。通过 Serverless 化的 Spark, Presto 等数据计算应用,灵活满足企业快速成长过程中不同业务部门的多种计算任务、高弹性、强隔离和免维护的需求。
Serverless 容器架构思考
不同于标准 K8s,Serverless K8s 与 IaaS 基础设施深度整合,其模式更利于公有云厂商通过技术创新,提升规模、效率和能力。在架构层面我们将 Serverless 容器分成容器编排和计算资源池两层,下面我们将对这两层进行深度剖析,分享我们对 Serverless 容器架构和背后的关键思考。
Kubernetes 的成功秘诀
Kubernetes 在容器编排的成功不止得益于 Google 的光环和 CNCF(云原生计算基金会)的努力运作。背后是其在 Google Borg 大规模分布式资源调度和自动化运维领域的沉淀和升华。
其中几个技术要点:
声明式 API
由于 Kubernetes 采用了声明式的 API。开发者可以关注于应用自身,而非系统执行细节。比如 Deployment, StatefulSet, Job 等不同资源类型,提供了对不同类型工作负载的抽象。对 Kubernetes 实现而言,基于声明式 API 的 “level-triggered” 实现比 “edge-triggered” 方式可以提供更加健壮的分布式系统实现。
可扩展性架构
所有 K8s 组件都是基于一致的、开放的 API 实现、交互。三方开发者也可通过 CRD(Custom Resource Definition)/Operator 等方法提供领域相关的扩展实现,极大提升了 K8s 的能力。
可移植性
K8s 通过一系列抽象如 Loadbalance Service, Ingress, CNI, CSI,帮助业务应用可以屏蔽底层基础设施的实现差异,灵活迁移。
Serverless Kubernetes 的设计原则
Serverless Kubernetes 必须要能兼容 Kubernetes 生态,提供 K8s 的核心价值,此外要能和云的能力深度整合。
- 用户可以直接使用 Kubernetes 的声明式 API,兼容 Kubernetes 的应用定义,Deployment, StatefulSet, Job, Service 等无需修改
- 全兼容 Kubernetes 的扩展机制,这个很重要,这样才能让 Serverless Kubernetes 支持更多的工作负载。此外 Serverless K8s 自身的组件也是严格遵守 K8s 的状态逼近的控制模式。
- Kubernetes 的能力尽可能充分利用云的能力来实现,比如资源的调度、负载均衡、服务发现等。根本性简化容器平台的设计,提升规模,降低用户运维复杂性。同时这些实现应该是对用户透明的,保障可移植性,让用户现有应用可以平滑部署在 Serverless K8s 之上,也应该允许用户应用混合部署在传统容器和 Serverless 容器之上。
从 Node Centric 到 Nodeless
传统的 Kubernetes 采用以节点为中心的架构设计:节点是 Pod 的运行载体,Kubernetes 调度器在工作节点池中选择合适的 node 来运行 Pod,并利用 Kubelet 完成对 Pod 进行生命周期管理和自动化运维;当节点池资源不够时,需要对节点池进行扩容,再对容器化应用进行扩容。
对于 Serverless Kubernetes 而言,最重要的一个概念是将容器的运行时和具体的节点运行环境解耦。只有如此,用户无需关注 node 运维和安全,降低运维成本;而且极大简化了容器弹性实现,无需按照容量规划,按需创建容器应用 Pod 即可;此外 Serverless 容器运行时可以被整个云弹性计算基础设施所支撑,保障整体弹性的成本和规模。
在 2017 年底,我们启动 Serverless Kubernetes 项目的时候,我们一直在思考,如果 Kubernetes 天生长在云上,它的架构应该如何设计。我们在现有 Kubernetes 的设计实现上,进行了扩展和优化。构建了 Cloud Scale 的 Nodeless K8s 架构——内部代号为 Viking,因为古代维京战船以迅捷和便于操作而著称。
Scheduler
传统 K8s scheduler 的主要功能是从一批节点中选择一个合适的 node 来调度 Pod,满足资源、亲和性等多种约束。由于在 Serverless K8s 场景中没有 node 的概念,资源只受限于底层弹性计算库存,我们只需要保留一些基本的 AZ 亲和性等概念支持即可。这样 scheduler 的工作被极大简化,执行效率极大提升。此外我们定制扩展了 scheduler,可以对 Serverless workload 进行更多的编排优化,可以在保证应用可用性的前提下充分降低了计算成本。
可伸缩性
K8s 的可伸缩性受到众多因素的影响,其中一个就是节点数量。为了保障 Kubernetes 兼容性,AWS EKS on Fargate 采用 Pod 和 Node 1:1 模型(一个虚拟节点运行一个 Pod),这样将严重限制了集群的可扩展性,目前单集群最多支持 1000 个 Pod。我们认为,这样的选择无法满足大规模应用场景的需求。在 ASK 中我们在保持了 Kubernetes 兼容性的同时,解决了集群规模受限于 Node 影响,单集群可以轻松支持 10K Pod。此外传统 K8s 集群中还有很多因素会影响集群的可伸缩性,比如部署在节点上的 kube-proxy,在支持 clusterIP 时,任何单个 endpoint 变更时就会引起全集群的变更风暴。在这些地方 Serverless K8s 也使用了一些创新的方法限制变更传播的范围,这些领域我们将持续优化。
基于云的控制器实现
我们基于阿里云的云服务实现了 kube-proxy、CoreDNS、Ingress Controller 的行为,降低系统复杂性,比如:
- 利用阿里云的 DNS 服务 PrivateZone,为 ECI 实例动态配置 DNS 地址解析,支持了 headless service
- 通过 SLB 提供了提供负载均衡能力
- 通过 SLB/ALB 提供的 7 层路由来实现 Ingress 的路由规则
面向工作负载的深度优化
未来充分发挥 Serverless 容器的能力,我们需要针对工作负载的特性进行深度优化。
- Knative:Knative 是 Kubernetes 生态下一种 Serverless 应用框架,其中 serving 模块支持根据流量自动扩缩容和缩容到 0 的能力。基于 Serverless K8s 能力,阿里云 Knative 可以提供一些新的差异化功能,比如支持自动缩容到最低成本 ECI 实例规格,这样可以在保障冷启动时间的 SLA 并有效降低计算成本。此外通过 SLB/ALB 实现了 Ingress Gateway,有效地降低了系统复杂性并降低成本。
- 在 Spark 等大规模计算任务场景下,也通过一些垂直优化手段提高大批量任务的创建效率。这些能力已经在江苏跨域的用户场景中得到验证。
Serverless 容器基础设施
对于 Serverless 容器而言,我们梳理的用户重点诉求是:
- 更低的计算成本:弹性成本要低于 ECS,long run 应用成本要接近 ECS 包年包月
- 更高的弹性效率:ECI 扩容速度要远高于 ECS
- 更大的弹性规模:与传统 ECS 节点扩容不同,一个大规模容器应用动辄需要数万核的弹性算力。
- 持平的计算性能:ECI 计算效能需要和同规格 ECS 有一致的性能表现
- 更低的迁移成本:与现有容器应用生态完美集成
- 更低的使用成本:全自动化安全和运维能力
ECI 的关键技术选择如下:
基于轻量化 Micro VM 的安全容器运行时
对于云产品而言,首先的考虑就是安全性。为此,ECI 选择基于袋鼠云原生容器引擎和轻量化 Micro VM 来实现安全、隔离的容器运行时。除了运行时的资源隔离之外,不同用户之间的网络、存储、quota、弹性 SLO 等一系列能力也基于阿里云基础设施,实现了严格的多租隔离。
在性能方面,除了袋鼠容器引擎在 OS/容器方面的高度优化之外,ECI 在容器执行上优化集成了现有阿里云基础设施能力,比如支持 ENI 网卡直通、存储直接挂载。这些能力保障 ECI 中应用执行效率等于甚至略优于现有 ECS 运行环境。
基于 Pod 的基本调度单位和标准、开放的 API 接口
与 Azure ACI, AWS Fargate on ECS 不同,在 ECI 设计初期就确定了基于 Pod 作为 Serverless 容器的基本调度和运行单位,这样可以更加简单地结合上层 Kubernetes 编排系统。
ECI 提供提供了 Pod 的生命周期管理能力,包括 Create/Delete/Describe/Logs/Exec/Metrics 等。ECI Pod 与 K8s Pod 能力一致,不同之处在于其沙箱基于 Micro VM 而非 CGroup/Namespace。这样使得 ECI Pod 可以比较完美地支持各种 K8s 应用,包括 Istio 这样以 sidecar 方式动态注入的技术。
此外标准化的 API 屏蔽了底层资源池的具体实现,可以同时可以容纳底层不同形态、不同架构、不同的资源池和生产调度实现。ECI 底层架构做了多次优化、迭代,比如袋鼠安全沙箱的创建可以通过神龙架构的 MOC 卡进行 offload,但是这些对上层应用和集群编排是无感的。
此外 API 需要拥有足够的通用性支持在多个场景中使用,让用户在 ASK/ACK、自建 K8s 和混合云场景中都可以充分利用 Serverless 容器的优势和价值。这个也是阿里云 ECI 和友商一个重要的不同。
ECI 与 ECS 并池架构
通过并池我们有能力充分整合阿里云弹性计算资源池的算力,包括多种模式(按量,spot,RI,Saving Plan 等),多种机型供应(GPU/vGPU, 新 CPU 架构上线),多样化的存储能力(ESSD,本地盘)等,让 ECI 在功能、成本和规模上更有优势,满足用户对计算成本和弹性规模的强诉求。
Serverless 容器的挑战
Serverless 容器资源创建过程首先是一个计算资源的创建装配过程,是计算、存储、网络多个基础 IaaS 资源的协同装配过程。然而与 ECS 不同,Serverless 容器有很多独立的挑战。
根据 Sysdig 2019 年容器的调研报告(https://sysdig.com/blog/sysdig-2019-container-usage-report/), 超过 50% 的容器生命周期小于 5 分钟。Serverless 容器需要具备秒级的启动速度才能满足用户对 Serverless 容器的启动诉求。Serverless 容器自身的启动速度主要受如下因素影响:
底层虚拟化资源的创建和组装
通过端到端管控链路的优化 ECI 可以将资源准备时间优化到亚秒级。
Micro VM 操作系统启动时间
袋鼠容器引擎针对容器场景对操作系统进行了大量剪裁和优化,极大减少了 OS 启动时间。
镜像下载时间
从 Docker 镜像仓库下载镜像并在本地解压缩是一个非常耗时的操作。下载时间取决于镜像大小,通常在 30 秒到数分钟不等。在传统 Kubernetes 中, worker 节点会在本地缓存已下载过的镜像,这样下次启动不会重复下载和解压。为了实现极致弹性成本效率,ECI 和 ECS 采用并池的策略,计算存储分离的架构,这也意味着我们不可能通过传统方式利用本地盘来做容器镜像的缓存。
为此我们实现了一个创新的方案:可以将容器镜像制作成一个数据盘快照。当 ECI 启动时,如果镜像快照存在,可以直接基于快照创建一个只读数据盘,并随着实例启动自动挂载,容器应用直接利用挂载数据盘作为 rootfs 进行启动。基于盘古 2.0 架构和阿里云 ESSD 云盘的极致 I/O 性能,我们可以将镜像加载的时间缩小到 1 秒以内。
这个领域还有很大发展空间,下一步会进一步和多个团队共同优化 Serverless 容器的启动效率。
此外, Serverless 容器的调度相比 ECS 更关注资源弹性供给的确定性。Serverless 容器强调按需使用,而 ECS 更多是提前购买预留。在大规模容器创建场景下,单用户单 AZ 弹性 SLO 保障是一个很大的挑战。在电商大促、跨年活动和最近的突发疫情保障的一系列用户支持中,用户对于云平台是否能够提供弹性资源供给确定性 SLO 是极度重视的。此外,结合 Serverless K8s,上层调度器和 ECI 弹性供给策略配合,我们可以给用户更多对弹性资源供给的控制能力,平衡弹性的成本,规模和持有时间等不同需求维度。
Serverless 容器的并发创建效率也至关重要。在高弹性场景,用户要求 30s 内启动 500 Pod 副本来支持突发流量,类似 Spark/Presto 等计算业务对并发启动的诉求更大。
为了有效减低计算成本,Serverless 容器应该提升部署密度。由于采用 MicroVM 技术,每个 ECI 实例拥有独立的 OS 内核。此外为了兼容 K8s 语义,还有一些辅助进程运行在 ECI 内部。目前每个 ECI 进程会有 100M 左右的额外开销。类似 EKS on Fargate,每个 Pod 也有近 256M 左右的系统开销。这部分会降低 Serverless 的部署密度。我们需要将共性的开销下沉到基础设施之上,甚至通过 MOC 软硬一体的方式来进行卸载。