网易轻舟 Serverless 平台 Knative 性能调优实践

百家 作者:InfoQ 2020-07-04 10:42:50
作者 | 刘勤龙
策划 | 田晓旭

Serverless 技术关注者对其价值点讨论⼤多是基于公有云场景的云函数等产品,其关注点在资源支付方式更加细粒度,和公有云 Baas 的粘合上,和私有云环境中业务团队关注的价值不太契合;在我们对业界落地场景调研以及同业务团队⼀起实践后,我们发现私有云环境中业务团队关心的 Serverless 价值可概括为三点:

提效:加快业务团队迭代效率, Serverless 对开发流水线重新对分工,业务开发人员聚焦业务,无需操心运维和扩容等诸多事项;

  1. 降本:按需实时弹性可避免资源浪费,最大程度发挥资源优势;

  2. 解耦:支持事件触发,将各个组件通信的逻辑变成事件进⾏解耦合,非常适合业务的扩展和变化;

  3. 其中“提效”和“降本”为核心价值,解耦为重要考虑点。

我们认为 Serverless 出现不是为了替代现有的 Serverful(传统云)框架,两者是互补的关系,Serverless 有其业务场景优势(后续⽂章再展开),合适最重要。笔者目前工作是聚焦轻舟 Serverless(“轻舟”系网易研发的云原生基础设施平台代号)和业务团队⼀起实现业务开发的提效、降本和解耦。当前开源 Serverless 方案很多,而选型强大活跃开源社区方案让我们能够持续改进自己的 Serverless 平台。基于此诉求,我们很早便选型了 Knative,因为从一开始其社区非常活跃,有 Google,IBM,RedHat 等大公司参与,其次是标准先行。而事实也在慢慢印证了我们的选择。

如图所示, Knative 占据了 34% 的份额,遥遥领先于第⼆名 OpenFaaS,Knative 是搭建 Serverless 平台的首选。( 数 据 来 源 于 CNCF 2019 年 社 区 调 查 报 告 )

目前,网易轻舟云原生团队已经和网易云音乐前端团队合作共建云音乐 Serverless 部署平台 ALPACA,将 Serverless 用于前端场景。该平台架构如下图。

其中轻舟负责底层能力,Knative 是其中的核心能力,我们基于其业务场景,对 Knative 进行了压测分析,也做了性能调优 POC,本文主要从性能角度,基于 Serverless 前端使用场景对 Knative 进行分析,尝试揭开 Knative 核心数据路径性能真相并给出调优思考。

⼀、Knative 系统内的数据路径分析

本文暂不讨论流量如何导⼊到 ALPACA 平台,先聚焦到 ALPACA 平台 Knative 系统内部本身。

Knative 系统内部数据路径是, Knative 网关 ->Activator->Queue  Proxy->业务 App;社区推荐使用的方式是不注入 Sidecar 以获取更佳的性能,因此我们讨论场景是“不注入 Sidecar,管控面使用 Pilot,Knative 网关使用轻舟的 API 网关产品”。

Knative 系统内部默认的数据路径如上图,用户业务流量经过一层 Knative 网关,经过 Activator  到达 Queue Proxy 代理组件,最后到达应用程序。

从上图可知,默认情况下流量经过三层代理(Knative 网关、Activator、Queue Proxy)后才到达应用 APP,每⼀层代理均可能是性能的拦路虎。

我们的分析思路如下:

  • Knative 网关这⼀层承载了流量管理、灰度发布等功能必须存在,当前使用轻舟 API 网关产品充当,性能均调优过,本身性能没什么问题,非本次核心关注点

  • App 为用户的业务代码性能无法控制,平台层面不可操作,也非关注点于是将性能分析要点集中到剩余的两层代理(Activator 和 Queue Proxy)上。

首先 Activator 作用是:

  • 冷启动充当看门人,业务 POD  0-1 流量会经过 Activator 组件

  • 突发流量的保护者,将 Activator 加⼊到核心路径,充当缓冲,流量将会在 Activator 缓存(0.8 版本 加入功能)

其次 Queue Proxy 作用是:

Queue  Proxy 以 Sidecar⽅式和应⽤容器部署到同⼀个 Pod,Queue  Proxy 是为了配合完成扩缩容事宜以及满足 App 可观测性要求,以 Sidecar 方式部署主要考虑到对 App 应用无侵入,功能描述如下:

  • 完成观测性数据收集向 Autoscaler 同步当前的并发监控,以便实现自动伸缩功能

  • 代理业务容器, 完成指标的统计,并将对应的数据汇报给后端的⽇志 / 监控 / 分布式跟踪服务

Activator 必要性分析

谈到 Activator 必要性,需要先了解当前 Serverless  难题“冷启动”,所谓冷启动是 Serverless 缩容到 0  后,重新从 0 扩容到 1 的过程,该过程目前是非常慢的,也是业界难题,根据社区对 Knative 冷启动分析得知,冷启动时间大概 6s ,很显然 6s 的冷启动任何业务都⽆法容忍;当前可以尽量优化冷启动时间,但是想达到 ms 级别,做到业务⽆感知,挑战非常大,目前有两种解决思路:

方向 1: 温启动,通过冗余方式建立预热池来解决,当需要 0-1 时候,从预热池取,然后将用户程序注入,省去建立容器的过程

方向 2: 通过默认预留实例来规避

目前该问题我们先通过方向 2 来解决,至于方向 1 也在考虑,但是涉及到的开发工作量大,且需要对 K8s 框架改动,需要根据需求触发。所以目前在我们使用场景中不需要 Activator 帮助从 0-1 扩容。

对于突发流量保护功能,在使⽤场景中可降低扩容触发的并发要求,预留出一定的 Pod 计算能力来抵御突发流量;因此在目前业务场景中,Activator 存在必要性⼀般,可以考虑将其从核心数据路径中彻底去除。

QueueProxy 必要性分析

Queue Proxy 核心作用是收集 App 的指标(并发、RPS 等)来决定扩容,当前以 Sidecar⽅式部署是非常有必要的:

  • 将核心指标统计逻辑提炼到 Queue Proxy,对 App 无任何代码逻辑侵⼊,基础设施和应用 App 业务逻辑分离,独立运维

  • 收集扩容指标支持跨语言

所以 Queue Proxy Sidecar 是非常有必要的,但是相比裸业务容器而言,会增加⼀层代理(该场景就像服务网格 Server Sidecar⼀样),导致业务容器性能降低,这是选择这种架构所要付出的资源成本,我们要做的就是将该成本降到最小。

如上图,总结下分析结论,从性能⾓度出发,我们需要关注:

  • 将 Activator 从数据路径中去除

  • 重点关注 Queue Proxy 和 App 路径

  • 关注 Knative 网关和 Queue Proxy 路径

⼆、开源 Knaitve 性能实际测试

从上文的分析结论可知,我们得到了具体的性能关注点,于是对这些关注点进行实际的性能测试。

在 Knative 框架下,性能可以通过 CPU 和实例个数横向扩展性能,所以后续测试均固定在单个业务容器,通过对比测试来发现性能瓶颈,业务容器选型社区简单的 go 语言实现的 helloworld 服务程序(镜像为 hub.c.163.com/qingzhou/knative/demo/helloworld-go:v0.1),采用测试工具 Hey(https://github.com/rakyll/hey )使⽤HTTP 长连接进行测试。

测试环境

  • Knative serving 0.14

  • 物理机容器

  • 轻舟网关

  • 三台独立的物理机器避免相互影响

测试方法

1. 部署测试 server kservice

root@pubt1-k8s59:/home/liuqinlong# cat performance.yamlapiVersion: serving.knative.dev/v1alpha1kind: Servicemetadata:  name: helloworld-go  namespace: defaultspec:  template:    metadata:      labels:        app: helloworld-go      annotations:        autoscaling.knative.dev/maxScale: "1"        autoscaling.knative.dev/minScale: "1"    spec:      containers:        - image: hub.c.163.com/qingzhou/knative/demo/helloworld-go:v0.1          env:            - name: SIMPLE_MSG              value: "helloworld-go"

2. 测试命令

hey -z 60s -c 70 --host "helloworld-go.default.example.com" "<http://10.178.67.100/>"

3. Knaitve 原生性能数据测试

  • 默认数据路径进行压测

如下结果显示,虽然 Activator 采用 HPA 进行性能扩展,但是其扩容非常慢,如果性能测试时候没有来得及扩容 Activator,对整个延迟影响效果巨⼤只有 920Qps。即使 Activator 扩容成了 8 个发现 p90 延时也在 7ms 以上,Qps 约 7 千。

避坑说明:在测试过程中,需要确认 Activator HPA 扩容是否生效,笔者测试过程中默认环境中没有安装 metrics-server 导致 Activator 无法 HPA 扩容。整个核⼼路径中 Activator 默认限制单个 CPU,其使用率达到 100%,导致 QPS 非常低(才 920),P90 延迟要 111ms,p99 延迟要 195.2ms

  • 原生容器对比含有 Queue Proxy sidecar 的容器

经过前文的分析 Queue Proxy 以 Sidecar⽅式存在是 Knative 架构要求,当前测试 case 情况下,加⼊Queue Proxy Sidecar 后,相⽐原⽣容器,QPS 从 3.9w->3.1w,P90 延迟翻倍(2.5->4.2)。

相对来说,在相同并发压力情况下,因为新增⼀层代理延迟肯定提升,QPS 会跟着降低。但是我们发现 CPU 损失代价有些大,CPU 使⽤率达到了 1497% (Server CPU 才 482.4%),理论测试的 App 为 hello world 程序业务逻辑⾮常简单,业务处理延迟不长,Queue Proxy 和当前测试 App CPU 使用率比值最好是 1:1,所以 Queue Proxy 存在 CPU 异常消耗的问题,需要进行调优解决。

注意:v0.14 Queue Proxy 性能要比 v0.9 版本 Queue Proxy 性能要好,后⽂Queue Proxy 测试版本均采⽤的是 v0.14 版本,下面给出性能对比:

QPS 提升 (31891.7207-20505.6853)/20505.6853 = 55%(计算过程后文不再赘述)。

测试结论
  • Activator 加⼊到数据路径中,在没有扩容情况下,性能⾮常差 QPS 只有 920,经过 HPA 扩容成 8 个后,QPS 可达 7776.1257

  • 业务容器引入 Sidecar 后,数据路径变长,相同压⼒下 QPS 从 3.9w -> 3.1w,P90 延迟翻倍(2.5->4.2),但是 CPU 使⽤率达到了 1497%,和 Server CPU 消耗差距约三倍,需对 Queue Proxy⾼CPU 问题进行分析

  • Knative 社区对 Queue Proxy 也在不断优化中,社区 v0.14 Queue Proxy 相比 v0.9 版本的 Queue Proxy 性能提升明显,QPS 2w->3w,延迟 6ms->4.2 ms

三、Knaitve 数据路径性能优化

经过对 Knative 性能测试,进⼀步确认了下面性能调优点:

  1. 数据路径上去除 Activator

  2. Queue Proxy 和 App 路径优化

  3. 优化 Knative Gateway 性能

数据路径上去除 Activator

分析对比去除 Activator 路径带来的性能收益,如下表,将 Activator 移出核心数据路径后,QPS 能力提升三倍(7776.1257 -> 25569.5698),且 P99 延迟大幅降低

Queue Proxy 和 App 路径优化
  1. 组件优化

经过对 Queue Proxy-> App 路径分析,有两种优化方法,阐述如下:

优化方向一:优化 Queue Proxy

优化 Queue Proxy HTTP 代理解析过程,延迟大幅度降低(4.2->2.4 ms),且 CPU 使用率大幅度降低(代理 CPU 使用率接近 Server CPU 使用率),QPS 小幅度提升。

优化方向二:将 Queue Proxy 替换成 Envoy

优化后 QPS 相对社区 Queue Proxy 版本提升 23%,延迟也大幅度降低,代理 CPU 使用率接近 ServerCPU 使用率。

  1. 框架优化

框架上协议栈穿透,通过 sockmap 以及 sock redirect 特性加速 Queue Proxy 和业务容器 App 之间通信。原理如下图:

基于轻舟的基于 EBPF 的高性能网络加速组件 --SOPS,开启该功能,测试结果如下:

  • 针对于 Queue Proxy 代理,组件优化 + 协议栈穿透, QPS 提升 26%

  • 针对于 Envoy Proxy 代理,协议栈穿透,QPS 提升 44%

  • 在当前测试 Case 场景下,协议栈穿透,可以提升业务容器 QPS 上限约 20%。

Knative 系统内全路径测试结果

注:单位百分百 CPU 支撑的 Qps= Qps/(Gateway(cpu%)+ QueueProxy(cpu%) + server(cpu%))

  • 轻舟调优的 Queue Proxy 可以将 QPS 提升 23%,连同 SOPS 一起可将 QPS 提升 43%

  • 使用 Envoy 替代 Queue Proxy 可将 QPS 提升 39%,连同 SOPS 一起可将 QPS 提升到 55%

  • 轻舟调优的 Queue Proxy 可以将 Queue Proxy CPU 占比高问题解决

  • 使用 Envoy 替换 Queue Proxy 可将 QPS 额外提升 12%,单位 CPU 百分比支撑的 QPS 基本一致

Knative 社区也在讨论 Envoy 代替 Queue Proxy,但是具体何时未知,考虑到工作量较大,我们打算 follow 社区进度;从性能角度和使用场景考虑,当前优化 Queue Proxy 也不差,所以先优化 Queue Proxy 来满足业务需求。

优化 Knative Gateway 性能

网关性能优化方面轻舟网关团队已经做了较多工作,性能也较为可观,在 Knative 当前使用场景,我们计划将 Gateway 底层网络更换成轻舟高性能网络,继续降低延迟,提升 Gateway 性能天花板,降低 CPU 使用率,使得单位百分比 CPU 支撑更多的业务 QPS。

总结

Knative 框架内,默认情况下引入了三层代理路径,固定压力(70 连接)下测试发现,默认情况下 Knative 性能表现非常不佳;经过调优(去除 Activator 这⼀层代理 + 使用 Queue Proxy v0.14 并优化 + 使用 Sops 加速 Queue Proxy 和 App 路径)Knative 框架性能表现还是非常优异的。

和裸业务容器相比:

1、单位百分比 CPU 支撑的 QPS 5:1

2、链路的变长,当前测试场景和测试方法下,链路延迟 p90 提升 2.5->4.7   约 2.2ms

从性能角度看 Knative 业务容器和裸业务容器,直接使用容器性能是最好的,使用 Knative 业务容器牺牲还是可以接受的。

下面进一步探讨,Knative 和 K8s 到底是什么关系?

从功能角度看,Knative 框架是 K8s 补充,工作在业务层次,解决业务的 “什么时候该扩容”,“怎么扩容”,“什么时候触发业务运行”等问题,是专业搞定业务自动扩缩容和事件触发的功能组件。

Knative 框架支持功能并不什么新鲜事情,其功能特性,完全可以通过,K8s 容器 + 智能网关 + 自定义扩容数据收集机制和并发控制 + 自己编码事件机制来代替 + 上层业务封装逻辑来替代,但是需较多的研发投入,而且对接 API 为私有 API 接口,对用户有绑定。

从自动扩容角度看,业务的扩缩容也可以通过 HPA 来完成,但是这种方案速度较慢,一般 3-5 分钟,无法适应业务快速扩容需求。

我们基于 K8s 角度对 Knative 框架下一个定义:Knaitve=K8s++,是⼀种对 K8s 补充,是一种通过牺牲 CPU 和局部的延迟,换取业务流量管理能力(红绿发布、回滚、流量管理)和业务扩展能⼒(自动扩容能力、事件机制等)的开源软件框架。

四、业务流量导⼊Knative

前文性能分析均是基于单个业务 Pod,Knative 本身性能可从单个业务 Pod 横向扩展出多个业务 Pod 来进行性能扩容而且其非常擅长这一点,这里不赘述。下面介绍业务流量如何从外部导入 Knative 系统,因为 Knative 系统内部扩展性没什么问题,我们需要使得接入 Knative 系统部分具备更强的横向扩展能⼒,以满足业务扩容的性能需求。

在选型之初,我们打算按照如下架构图,流量接入到 Knative 系统。流量经过 Nginx Https 代理 -> 轻舟网关 -> 轻舟 Knative 网关 -> Queue Proxy -> 业务 App,其中:

Nginx:主要作用是 HTTPS 加密

轻舟网关:主要做 URL 路径和域名路径的转换、业务降级

轻舟 Knative 网关:主要实现红绿发布、流量管理等功能

上图中业务路径比较长,特别是经过了三次 7 层网关(Nginx、轻舟网关、轻舟 Knative 网关),且 Nginx 和轻舟网关存在能力集重复问题,所以我们打算做如下调整:

使用轻舟网关接管 Nginx 的 HTTPS 的能⼒,缩短七层代理的路径,采用轻舟网关自动降级功能,业务降低避免了人为操作,为了方案的可扩展(性能横向扩展、未来 IPv6 需要等)和部署的灵活性,引入低延时的轻舟的四层 LB。架构如下图,做到各个层可横向扩展。

因为方案降级需求,轻舟网关需要连云外的降级资源,但 Knative 网关无法管理该云外资源,所以目前无法将 Knative 网关和轻舟网关融合成一个网关。未来 Serverless 平台不再需要云外的降级资源,再将轻舟网关和轻舟 Knative 网关合并,达到如下流量框架,进一步缩短流量路径,达到最佳性能。

实现轻舟网关和轻舟 Knative 网关的融合需要修改 Knative,原因是:Knative 默认通过域名来区分应用,非常适合公有云,但是往往私有云业务场景,域名是固定且受限的,甚至有时候固定嵌入到客户端代码中,所以通过域名进行应用区分非常不适合,对于 HTTP 协议来说,我们需要使用请求路径来区分应用。

五、总结和展望

基于云原生化的泛前端部署平台依赖的底层 Knative 场景,通过分析,我们发现 Knative 社区默认情况下性能非常差,配置调优(不注入 Sidecar + 将 Activator 从数据路径中去除后 + 使用 Queue Proxy v0.14 版本)后,除 Queue Proxy CPU 偏高外,性能还可以,特别是经过调优 Queue Proxy、框架上协议栈穿透优化以及业务流量导入路径缩短后,性能可满足绝大部分业务需求,目前社区对于性能也在继续优化中(v0.14 相比 v0.9 QPS 性能约有 55% 提升),我们相信社区 Knative 数据路径的性能会越来越好。

作者介绍:

刘勤龙,网易杭州研究院资深云计算开发工程师,7 年服务端开发和优化经验,负责网易轻舟四层负载均衡数据面设计,参与轻舟服务网格性能优化,目前专注于轻舟云原生 Serverless 平台底层的开发和优化工作。主要关注 Kubernetes、Istio、Knative、Cilium 等技术领域。


InfoQ 写作平台欢迎所有热爱技术、热爱创作、热爱分享的内容创作者入驻!

还有更多超值活动等你来!

扫描下方二维码

填写申请,成为作者

开启你的创作之路吧~


点个在看少个 bug 

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接