CoreOS是如何将Kubernetes的性能提高10倍的?

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
日志服务 SLS,月写入数据量 50GB 1个月
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 本文讲的是CoreOS是如何将Kubernetes的性能提高10倍的,【编者的话】本文是CoreOS近期对Kubernetes扩容性的一些针对性试验、检测和研究,分析并且得出了对Kubernetes集群部署和pod吞吐量等Kubernetes集群性能问题、扩容性问题上一系列的尝试和见解。
本文讲的是CoreOS是如何将Kubernetes的性能提高10倍的 【编者的话】本文是CoreOS近期对Kubernetes扩容性的一些针对性试验、检测和研究,分析并且得出了对Kubernetes集群部署和pod吞吐量等Kubernetes集群性能问题、扩容性问题上一系列的尝试和见解。该文章回顾了从硬件到软件层面采用缩小范围以及使用Kubernetes提供的端对端API性能指标和使用benchmarking作为基准工具等手段进行对建立不同规模集群过程中的pod吞吐量测试,从而发现Kubernetes集群调度器性能的潜在瓶颈和潜在解决方案。

扩容性对任何一个分布式系统的成功而言都是一个重要的因素。在CoreOS,我们非常喜欢Kubernetes,希望能够通过对上游的贡献来推进这个项目。去年11月,我们组建了一个团队,专门研究Kubernetes的扩容性。我们设定了一个目标来检测和理解Kubernetes集群的性能,从而获取集群在工作量很大的情况下的表现性能,来获取Kubernetes集群的性能问题大概在什么地方。

很快我们就开展了这方面的工作,我们发现了一系列的瓶颈。通过解决这些瓶颈,我们把Kubernetes调度基准在1千个节点上调度3万个pod的时间从8780秒降到587秒。在这篇文章里,分享了我们是如何获得这个超过了十倍的性能提升,并且希望能够抛砖引玉,让社区可以进一步提升Kubernetes的扩容性。

Kubernetes架构概览

为了理解和提高Kubernetes的性能,我们首先需要建立一个适于当前能力的基线。一个Kubernetes集群是由一整套控制管理集群操作的API节点来组成的,API节点跑在工作节点上,应用的pods也同样跑在这些节点上。我们最初把目光聚集在控制层部件,因为它们参与了集群层面的每一个调度操作,这是我们理解性能最有可能提升的地方。Kubernetes的构架参见下图。
scale-arch.png

对Kubemark的试验

Kubernetes社区最近推出了Kubemark,用来测试控制层部件的性能。Kubemark模拟了工作节点,可以在一个单独的CPU内核上模拟10个真实节点,让我们以最低的复杂度和消耗来模拟大型集群。

我们对Kubemark的第一个使用是做了一个密度测试,来测量在每一个节点上调度30个pod,Kubemark所需要的时间。对一个100个节点的集群来说,有3千个pod需要调度和跑起来;对于1000个节点的集群而言,那就有3万个pod。这些测试结果显示了在不同时期的pod数量。我们所有的测试,集群都是连接在一个etcd集群上,etcd跑在一个单独机器上。
Pods:  229 out of 3000 created,  211 running, 18 pending, 0 waiting
Pods:  429 out of 3000 created,  412 running, 17 pending, 0 waiting
Pods:  622 out of 3000 created,  604 running, 17 pending, 1 waiting
...
Pods: 2578 out of 3000 created, 2561 running, 17 pending, 0 waiting
Pods: 2779 out of 3000 created, 2761 running, 18 pending, 0 waiting
Pods: 2979 out of 3000 created, 2962 running, 16 pending, 1 waiting
Pods: 3000 out of 3000 created, 3000 running, 0 pending,  0 waiting

我们以一个拥有100节点的集群测试来开始我们的调查,它在150秒内完成了调度3千个节点的任务。pod的吞吐量在20个pod/秒。为了更好的理解这个日志,我们写了一个 plot工具 来画图。

下面这个图显示了由 replication controller建立但并非调度的pod,显示了它们一旦被调度到集群的机器里跑起来的时候。
scale-03.png

我们很快注意到这个图显示了一个pod创建的线性情况, 在20个pod/秒,看上去很低,说明存在一个潜在的可以提高的瓶颈和目标。我们就从这里开始性能的旅程。

奔向更好吞吐量的旅程

我们脑海中想到的第一件事情是也许硬件资源吃紧了。如果是这样的话,我们可以简单地通过增加资源来提高调度的性能。我们又跑了测试,监控CPU、内存、IO使用率到顶的情况。结果看上去如下:
scale-05.png

从我们所观察到的来看,没有任何物理资源是被完全使用的。这说明问题出在软件上。

在一个类似Kubernetes这样庞大的代码库中去发现瓶颈,犹如大海捞针。我们需要一步步来缩小范围。幸运的是,Kubernetes提供了大多数端对端API调用的性能指标(被 Prometheus 这个开源项目所收集)。我们第一步就是在这里面寻找。我们又跑了测试,监控了调度器的指标。结果如下:
# HELP scheduler_e2e_scheduling_latency_microseconds E2e scheduling latency (scheduling algorithm + binding)
# TYPE scheduler_e2e_scheduling_latency_microseconds summary
scheduler_e2e_scheduling_latency_microseconds{quantile="0.5"} 23207
scheduler_e2e_scheduling_latency_microseconds{quantile="0.9"} 35112
scheduler_e2e_scheduling_latency_microseconds{quantile="0.99"} 40268
scheduler_e2e_scheduling_latency_microseconds_sum 7.1321295e+07

我们发现调度器端到端的延迟达到7ms,相当于140pod/秒的吞吐量,比我们之前测试看到的20pod/秒要高出很多。这说明瓶颈在调度器自身以外。

我们继续通过查看性能指标和日志来缩小问题的范围。我们发现瓶颈在replication controller里。看这里:
wait.Add(diff)
for i := 0; i < diff; i++ {
go func() {
    defer wait.Done()
    if err := rm.podControl.CreatePods(...); err != nil {
        ...
    }
}()
}
wait.Wait()

我们打印了日志,发现等到500  CreatePods()  用了25秒。这正好是20pod/秒,但  CreatePods()  的延迟只有1ms。

不久之后,我们在客户端用户里发现了一个速率限制。速率限制是用来保护API服务器不被过度使用。在我们的测试中,我们并不需要它。 我们提高了限制,想看看调度速度的边界。它没有完全解决问题。

结果,我们又发现了一个速率限制,并且修复了一个程序的非有效路径( #17885 )。在那些变化之后,我们得以看到了最终的提高。在100个节点的建立中,平均建立速度从20pod/秒提高到超过300pod/秒,在50秒中完成,平均pod吞吐量在60pod/秒。
scale-00.png

目光转向调度器

然后我们尝试在1千个节点的集群上进行提高。然而,我们这次没这么幸运。看看下图:
scale-07.png

在一千个节点的集群上,花了5243秒来跑3万个pod,平均吞吐量在5.72pod/秒。Creation rate持续增加,但running rate一直比较低。

我们然后又进行了测试,查看调度器的性能指标。这次,调度延迟变成了开始时的60ms,到结束时(即3万个pod)增加到了200ms。结合我们在日志和图表中所见,我们意识到以下两点:
  • 60ms的延迟很高。调度器很可能变成了瓶颈。如果我们能把它降低,这样就能增加调度速度,这样pod的running rate就很有可能变高。
  • 调度延迟随着被调度pod总体数量的增加而上升,这导致了集群pod的running rate的下降。这在调度器里面是个扩容问题。

调度器的代码库是很复杂的,我们需要很细致的归档才能理解调度器在哪块花费了时间。但是,在Kubernetes上面重复同样的过程是很耗时的,我们的测试用了超过两个小时才完成。我们想要一个更加轻便一些的方法来做调度器组建测试,从而集中我们的精力和时间。这样,我们就能写一个像Go unit test那样的调度器的benchmark做基准工具。这个工具测试调度器作为一个整体,而不用启动不必要的部件。更多细节可以从我们的 幻灯片 中找到关于调度器性能测试以及在 Kubernetes pull request#18458 中看到。

通过使用benchmarking做基准的工具,我们高效地工作,打破调度器在1千个节点集群的3万个pod建立上的瓶颈。

例如,在 Kubernetes的issue#18126 中,我们有如下pprof (performance profiling)结果:
scale-06.png

总共的79秒钟内, Round() 方法只用了18秒。我们觉得这对于取整而言是失效的。我们用更加有效的实现方式调整了这个问题( PR #18170 )。结果,我们把对1千个节点上调度1千个pod的平均调度延迟时间从53秒降低到23秒。

这样,我们可以挖掘出更多没有效率且成为瓶颈的代码。在以下的upstream issue中我们进行了汇报并做了提升:

通过使用这些变化,我们获得了难以置信的新能提升——调度吞度量达到51pod/秒。我们又一次跑了调度器的基准为1千个节点集群上调度3万个pod,拿它和之前的结果相比较,请看下图:
scale-01.png

请注意这个过程比跑Kubemark时间更长,有可能是垃圾回收导致的。我们把所有东西放在同一个程序里,Kubemark在不同的进程里来跑调度器、API服务器和controller管理器。但这个区别不影响比较的结果,假设这样是有可比性的。

现状和未来的步骤

通过我们的优化,我们重新跑了Kubemark“1千个节点/3万个pod”测试。结果如下图:
scale-02.png

现在,平均pod吞吐量为16.3pod/秒,之前数据为5.72pod/秒。首先,我们看到了吞吐量的提高。第二,这个数字仍然比我们调度器基准的要低。我们确信在这点上,调度器本身不太可能是瓶颈。有很多其他因素,比如远程调用延迟、API服务器中的垃圾回收等等。这可能是一个未来性能提升的下一个探索方向。

扩容Kubernetes

在这篇博文中,我们讨论了我们是如何分析类似于性能指标和CPU归档的实验结果来确定性能瓶颈和提高调度器的。

为了更好的理解调度器,我们提供了一个基准工具,我们用它来验证我们的性能提升。到我们目前的工作位置,我们把1千个节点上调度3万个pod的时间从8780秒降低到了587秒,给Kubernetes发了4个PR。

尽管在这里描述的技术很简单,把我们的想法过程分享给大家会帮助其他人通过把调查研究切分成能够处理的一块一块,从而来debug复杂的分布式系统。

这里重要的是以下几点:
  • 性能指标提供了一个便利和非常亟需的观察系统的视野
  • 使用基准是一个图解性能和发现任何潜在问题的有效方式
  • 画图是一种在一段时间后观察系统比较好的方法

原文链接:Improving Kubernetes Scheduler Performance (翻译:韩佳瑶)

===========================
译者介绍
韩佳瑶 ,才云科技(Caicloud)联合创始人。

原文发布时间为: 2016-02-24 
本文作者:juliahan
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:CoreOS是如何将Kubernetes的性能提高10倍的?
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
2月前
|
Prometheus Kubernetes 监控
Kubernetes 性能调优与成本控制
【8月更文第29天】随着 Kubernetes 在企业中的广泛应用,如何有效地管理和优化 Kubernetes 集群的性能和成本成为了一个重要的课题。本篇文章将介绍 Kubernetes 性能监控的基础知识,以及一些实用的成本优化技巧,包括资源配额的设置、Pod 密度的提高和集群规模的合理调整。
74 1
|
2月前
|
Kubernetes 算法 测试技术
Kubernetes的垂直和水平扩缩容的性能评估
Kubernetes的垂直和水平扩缩容的性能评估
41 6
|
API 容器 Kubernetes
当 K8s 集群达到万级规模,阿里巴巴如何解决系统各组件性能问题?
作者 | 阿里云容器平台高级技术专家 曾凡松(逐灵) 本文主要介绍阿里巴巴在大规模生产环境中落地 Kubernetes 的过程中,在集群规模上遇到的典型问题以及对应的解决方案,内容包含对 etcd、kube-apiserver、kube-controller 的若干性能及稳定性增强,这些关键的增强是阿里巴巴内部上万节点的 Kubernetes 集群能够平稳支撑 2019 年天猫 618 大促的关键所在。
|
2月前
|
Kubernetes 安全 Linux
在K8S中,calico和cilium这两种cni有什么区别?cailico的ipip模型和ciliume的vxlan模型,两种不通模型性能也不同,它们怎么处理数据的?
在K8S中,calico和cilium这两种cni有什么区别?cailico的ipip模型和ciliume的vxlan模型,两种不通模型性能也不同,它们怎么处理数据的?
|
4月前
|
Kubernetes 网络协议 Cloud Native
Kubernetes网络问题排查分享两则(1)——calico特定场景下的网络性能问题
在对Kubernetes项目[kosmos](https://github.com/kosmos-io/kosmos)与Calico网络性能进行对比测试时,发现kosmos在跨集群容器网络的性能显著优于Calico的集群内网络(约6Gbit/s对比2.9Gbit/s)。物理机网络测试达到9.38Gbit/s,显示Calico有68%的性能损耗。问题定位到网卡的checksum/offload参数,尝试用`ethtool`调整后虽短暂提升,但随后恢复原状。转载自:https://mp.weixin.qq.com/s/XsQZCSqZAXJK46zqc7IpLw
|
12月前
|
Kubernetes jenkins 持续交付
jenkins结合k8s构建流水线如何提升运行性能和构建效率
jenkins结合k8s构建流水线如何提升运行性能和构建效率
|
11月前
|
存储 Kubernetes 应用服务中间件
使用CoreOS来部署一个Kubernetes集群,包括必要的步骤和关键概念
使用kubeadm join命令将其他CoreOS节点加入Kubernetes集群。在每个节点上运行以下命令,其中<控制平面节点IP>是Kubernetes控制平面节点的IP地址,<令牌>是在初始化控制平面时生成的令牌。
180 0
|
12月前
|
Kubernetes 调度 容器
kubernetes调度器性能调优
kubernetes调度器性能调优
BXA
|
缓存 Kubernetes 负载均衡
如何优化Kubernetes的性能和资源利用率优化
根据业务实际需求可以添加或删除节点。如果我们的业务中有一段时间流量比较大可以考虑增加节点来增加集群的承载能力,等过了这段时间之后就可以减少节点了以节省成本
BXA
12589 2
|
Kubernetes 安全 API
【kubernetes】API Server 保证性能的方式
【kubernetes】API Server 保证性能的方式
117 0
下一篇
无影云桌面