导读:Serverless 如今已经成为备受关注、发展前景广阔的技术方向,但一个系统究竟需要具备哪些能力,才能更好地支撑 Serverless 应用落地?随着 Kubernetes 与云原生技术快速发展,Serverless 在 Kubernetes 之上又该如何实践?本文将从 Serverless 应用的核心特性出发,探讨一个优秀的 Serverless 应用管理平台应具备哪些关键能力,并帮助您更深入地理解 Knative 的 Serverless 应用管理方式。
为什么需要 Knative

Serverless 已经成为行业普遍看好的技术趋势。多项调查报告显示,越来越多的企业和开发者正在使用 Serverless 构建线上业务,而且这一采用比例仍在持续上升。
在这一趋势下,再来看 IaaS 架构的演进路径。早期企业上云,通常是基于 VM 的方式来使用云资源,线上服务往往通过 Ansible、Saltstack、Puppet 或 Chef 等工具部署在 VM 中。直接在 VM 内启动应用,会让线上服务对 VM 环境配置产生较强依赖。随着容器技术兴起,越来越多的团队开始通过容器方式在 VM 中部署应用。
但如果需要部署十几个甚至几十个应用,就意味着要在成百上千台 VM 上快速完成部署、升级和运维,这无疑是一件非常复杂且令人头疼的事情。而 Kubernetes 很好地解决了这类问题,因此如今越来越多的企业开始通过 Kubernetes 的方式使用云资源。随着 Kubernetes 的普及,各大云厂商也纷纷推出 Serverless Kubernetes 服务,用户无需自行维护 Kubernetes 集群,就可以直接通过 Kubernetes 语义使用云能力。
既然 Kubernetes 已经如此成熟,为什么还需要 Knative?要回答这个问题,首先要梳理 Serverless 应用通常具备哪些共同特征:
- 按需使用,自动弹性
能够按需使用云资源,在业务流量上涨时自动扩容,在流量下降时自动缩容,因此必须具备自动弹性伸缩能力。
- 灰度发布
需要支持多版本管理,在应用升级过程中可以采用多种灰度发布策略平滑上线新版本。
- 流量管理
需要能够管理南北向流量,并支持按照流量百分比将请求分配到不同版本,从而实现精细化灰度控制。
- 负载均衡、服务发现
在应用弹性伸缩过程中,实例数量会动态变化,因此流量管理必须同时具备负载均衡与服务发现能力。
- Gateway
当多个应用部署在同一个集群中时,需要一个统一的接入层网关,对多个应用以及同一应用的不同版本进行统一流量治理。
随着 Kubernetes 和云原生概念的兴起,很多人的第一直觉可能是直接在 Kubernetes 之上部署 Serverless 应用。那么,如果要在原生 Kubernetes 上落地 Serverless 应用,我们通常会怎么做?

首先,需要一个 Deployment 来管理 Workload,还需要通过 Service 对外暴露服务并提供服务发现能力。当应用发生重大变更、新版本发布时,往往需要先暂停观察,确认无问题后再逐步提升灰度比例。这种场景下,通常就需要使用两个 Deployment。
v1 Deployment 代表旧版本,在灰度发布时逐步减少实例数;v2 Deployment 代表新版本,在灰度过程中逐步增加实例数。HPA 代表弹性伸缩能力,每一个 Deployment 都需要各自的 HPA 来管理弹性配置。
这里其实存在天然冲突:假设原本 v1 Deployment 有三个 Pod,在灰度时将其中一个 Pod 升级到 v2,此时就会有 1/3 的流量进入 v2 版本。然而当业务高峰来临时,由于两个版本都配置了 HPA,v1 和 v2 会同时扩容,最终 v1 与 v2 的 Pod 数量将不再保持最初设定的 1/3 比例。
因此,传统这种基于 Deployment 实例数的灰度发布策略,与弹性伸缩配置之间存在天然矛盾。而如果改为基于流量比例进行灰度,就不会受到实例数量变化的影响,这时往往就需要引入 Istio 等服务治理能力。

引入 Istio 作为 Gateway 组件后,Istio 不仅能够管理同一应用不同版本之间的流量灰度,还可以对不同应用进行统一流量管理。看起来很理想,但进一步分析会发现,问题依然存在。先梳理一下在原生 K8s 之上手动管理 Serverless 应用通常需要哪些资源:
- Deployment
- Service
- HPA
- Ingress
- Istio
- VirtualService
- Gateway
这些资源几乎都需要为每一个应用维护一份,如果是多个应用,就要维护多套配置。这些对象分散在 Kubernetes 内部,难以直接体现“应用”这一更高层级的概念,同时整体管理和维护成本也非常高。

Serverless 应用真正需要的是面向应用的管理能力,例如应用托管、升级、回滚、灰度发布、流量治理以及弹性伸缩等。而 Kubernetes 提供的更多是 IaaS 层面的资源抽象。因此,在 Kubernetes 与 Serverless 应用之间,实际上还缺少一层面向应用编排的抽象能力。
Knative 正是构建在 Kubernetes 之上的 Serverless 应用编排框架。除了 Knative 之外,社区中也存在多种 FaaS 类编排框架,但这些框架编排出的应用缺乏统一标准,每个框架都有自己独立的一套规范,而且通常与 Kubernetes API 并不完全兼容。不兼容的 API 往往意味着更高的使用门槛和更弱的可复制性。云原生领域的一个核心标准就是 Kubernetes API 标准,而 Knative 管理的 Serverless 应用保持了 Kubernetes API 语义的一致性。与 Kubernetes API 良好兼容,正是 Knative 云原生特性的关键体现。
Knative 是什么?

Knative 主要解决的问题,是在 Kubernetes 之上提供通用的 Serverless 编排与调度能力,为上层 Serverless 应用提供面向应用层的原子化操作。同时,它通过 Kubernetes 原生 API 对外暴露服务接口,保持与 Kubernetes 生态工具链的深度融合。Knative 拥有 Eventing 和 Serving 两个核心模块,本文主要介绍 Serving 的核心架构。
Knative Serving 简介

Serving 的核心对象是 Knative Service。Knative Controller 会根据 Service 的配置,自动操作 Kubernetes Service 和 Deployment,从而达到简化应用管理的目标。
Knative Service 对应一个名为 Configuration 的资源。每当 Service 发生变化且需要创建新的 Workload 时,就会更新 Configuration;而每次 Configuration 更新,都会生成一个唯一的 Revision。Revision 可以理解为 Configuration 的版本管理机制。从理论上讲,Revision 一旦创建完成,通常就不会再被修改。
Route 主要负责 Knative 的流量管理。Knative Route Controller 会根据 Route 配置自动生成 Knative Ingress 配置,而 Ingress Controller 则基于这些 Ingress 策略实现路由管理。
Knative Serving 对应用 Workload 的 Serverless 编排,本质上的起点在于流量控制。首先,流量会到达 Knative 的 Gateway,Gateway 会根据 Route 配置,自动按百分比将流量拆分到不同的 Revision 上。与此同时,每个 Revision 都拥有自己独立的弹性伸缩策略。当请求流量增加时,当前 Revision 会自动扩容,而且各个 Revision 的扩容策略彼此独立、互不影响。
基于流量百分比对不同的 Revision 进行灰度发布,并为每个 Revision 配置独立的弹性策略,Knative Serving 通过对流量的统一控制,实现了流量管理、自动弹性和灰度发布三者之间的有机结合。
Knative Serving API 详解

上图展示了 Knative Autoscaler 的工作机制。Route 负责接入流量,Autoscaler 负责执行弹性伸缩。当没有业务请求时,系统会自动缩容到零;缩容到零之后,Route 接收到的新请求会先转发到 Activator。当第一个请求到来时,Activator 会先保持住 HTTP 连接,然后通知 Autoscaler 执行扩容。待 Autoscaler 完成第一个 Pod 的扩容后,Activator 再把流量转发到 Pod,从而实现即使缩容到零,也尽量不损失流量请求。
到这里,Knative Serving 的核心模块与基本原理已经介绍完毕,相信你已经对 Knative 有了初步认识。在理解其原理的过程中你可能也会发现,想要真正将 Knative 用起来,仍然需要维护不少 Controller 组件和 Gateway 组件(例如 Istio),同时还要持续投入一定的 IaaS 成本和运维成本。

如果 Gateway 组件采用 Istio 实现,仅 Istio 本身就需要十几个 Controller;如果还要考虑高可用,可能会增加到二十多个 Controller。Knative Serving Controller 如果全部按高可用方式部署,也需要十几个实例。这些 Controller 带来的 IaaS 成本和运维成本都不低。此外,冷启动问题同样十分明显:虽然缩容到零可以降低业务低谷期的成本,但第一批流量请求也有可能因此超时。
Knative 和云的完美融合
为了解决上述问题,我们将 Knative 与阿里云进行了深度融合。用户依然按照 Knative 原生语义使用,但底层的 Controller、Gateway 等能力已深度嵌入阿里云体系之中。这样既保证了用户能够基于 Knative API 使用云资源、避免厂商锁定风险,也能同时享受到阿里云基础设施带来的现有优势。

首先是 Gateway 与云能力的融合,直接使用阿里云 SLB 作为 Gateway。采用云产品 SLB 的优势包括:
- 具备云产品级别的能力支撑,提供 SLA 保障;
- 支持按需付费,无需额外购买 IaaS 资源;
- 用户无需承担复杂运维成本,也不用额外处理高可用问题,云产品本身已具备高可用能力。

除了 Gateway 组件之外,Knative Serving Controller 同样会带来一定成本,因此我们也将 Knative Serving Controller 与阿里云容器服务进行了深度整合。用户只需要拥有一个 Serverless Kubernetes 集群,并开启 Knative 功能,就可以基于 Knative API 直接使用云能力,而且无需为 Knative Controller 额外付出任何成本。
Knative 的冷启动问题

接下来再来看冷启动问题。传统应用在未开启弹性配置时,实例数量通常是固定的;而由 Knative 管理的 Serverless 应用,默认就具备弹性策略,在没有流量时会自动缩容到零。传统应用在流量低谷期,即使没有业务请求,实例数也依然保持不变,这从资源利用率来看是一种浪费;但它的好处是请求通常不会超时,任意时刻到来的请求都能较快被处理。而如果缩容到零,那么第一个请求到达后才会触发扩容流程。
在 Knative 的模型中,从 0 到 1 的扩容通常需要 5 个步骤串行完成,只有这 5 个步骤全部完成之后,第一个请求才能真正被处理,而此时往往已经接近甚至超过超时阈值。因此,Knative 缩容到零虽然有效降低了常驻资源成本,但首批请求的冷启动问题也十分突出。可以看出,弹性本质上是在成本与效率之间寻找平衡。

为了解决首个实例的冷启动问题,我们推出了保留实例功能。保留实例是阿里云容器服务 Knative 的独有能力。社区版 Knative 默认会在无流量时缩容到零,但缩容到零之后,从 0 到 1 的冷启动问题始终很难彻底解决。冷启动不仅涉及 IaaS 资源分配、Kubernetes 调度、镜像拉取等底层环节,还与应用自身启动耗时密切相关。应用启动时间可能从毫秒级到分钟级不等,而这本质上属于业务层面的行为,底层平台几乎无法完全控制。
ASK Knative 针对这一问题的思路,是通过低成本的保留实例来平衡资源成本与冷启动体验。阿里云 ECI 提供多种实例规格,不同规格在计算能力和价格上都有差异。如下所示,是 2c4G 配置下计算型实例与突发性能型实例的价格对比。

从上图可以看出,突发性能实例相比计算型实例便宜 46%。这意味着在没有流量时,如果使用突发性能实例来承载服务,不仅能够缓解冷启动问题,还能进一步节省大量成本。
除了价格优势之外,突发性能实例还有一个非常突出的能力,那就是 CPU 积分。突发性能实例可以借助 CPU 积分应对突发性能需求。它能够持续积累 CPU 积分,当实例性能无法满足负载要求时,可以通过消耗已积累的 CPU 积分,平滑提升计算能力,而不会影响部署在实例上的运行环境和应用。借助 CPU 积分,您可以从整体业务视角更合理地分配计算资源,把业务平峰期剩余的计算能力无缝转移到高峰期使用(可以简单理解为“油电混动”模式)。有关突发性能实例的更多细节可参见相关资料。
因此,ASK Knative 的策略是在业务低谷期使用突发性能实例替换标准计算型实例;当第一个请求到来时,再无缝切换回标准计算型实例。这样既能降低流量低谷期的资源成本,又可以把低谷期积累的 CPU 积分在业务高峰时释放出来,让用户每一分资源投入都更高效。
使用突发性能实例作为保留实例只是默认策略,用户也可以根据业务需要,指定其他类型的实例作为保留实例规格。当然,用户还可以配置最少保留一个标准实例,从而关闭保留实例功能。
总结
Knative 是 Kubernetes 生态中最流行的 Serverless 编排框架之一。社区原生 Knative 需要常驻的 Controller 和常驻网关组件才能持续提供服务,这些常驻实例不仅会带来额外的 IaaS 成本,也增加了大量运维负担,提升了应用 Serverless 化的落地难度。因此,我们在 ASK 中对 Knative Serving 进行了完全托管,帮助用户以开箱即用的方式获得更极致的 Serverless 体验。
Serverless 公众号,持续发布 Serverless 技术最新资讯,汇集更全面的 Serverless 技术内容,关注 Serverless 发展趋势,也更关注你在实际落地过程中遇到的困惑与问题。
