“千万”并发:Kubernetes 1.2v 开启谷歌级别性能之旅

2016-03-29

随着Kubernetes1.2v发布,K8S现在能支持1000个节点的集群(即1千万请求/秒),附带对大多数API操作(99%尾部这段)延迟降低80%。这意味着在最近的6个月内,K8S支持的容量增加了10倍同时还保证用户使用感受——99%pod启动时间少于3秒,大多数API操作99%延迟在几十毫秒(唯一例外是LIST操作,对于很大的集群需要几百毫秒)。Kubernetes 1.2v的千万并发令人乍舌?三个月后,K8S 1.3v将会再次带来10倍的提升。     


kubernetes 1.2v千万并发实测,请看视频:

在这个视频里,我们看到集群规模上升到1000个节点上到达10MQPS(即每秒1千万请求),还包括了滚动更新,没有宕机时间和任何尾部延迟。这在互联网上也足以列入前百强的表现。 

        接下来,我们来介绍一下K8S是如何做到这些的,以及我们未来在K8S扩容性上进一步提高的计划。

方法论:

     我们对于K8S的扩容性做的基准是基于以下服务层面上的目标(ServiceLevel Objectives):

        1. API的相应:99%的API调用返回时间都小于1秒

        2. Pod启动时间:99%的pod和它们容器(pull好的镜像)在5秒内启动

        只有这两点同时满足,我们才说K8S的扩容性到达了怎样怎样一个节点的数量。我们持续收集和报告这些测量数据来作为我们项目测试的框架,测试也相应的分成了两个部分:API相应时间和pod启动时间。


API响应

    K8S为用户提供了一些抽象概念来代表他们的应用,比如说,用冗余控制器(即RC, Replicaiton Controller)作为一群pod的抽象。把所有RC列出来或把一个给定的RC所包含的所有pods列出来,就是一个很常见的场景(usecase)。但从另外一方面来说,很少会有需要去把系统里的所有pods列出来,比如说3万个pod(即比如1000个节点,每个节点有30个pod)意味着150MB的数据(即5KB/pod* 3万pods)。这个测试使用冗余控制器。

        对于这个测试来说(假设N是集群里的节点数量),我们做了:

    (1)创建大约3*N个的不同数量的冗余控制器(5,30,250副本),这样我们总共会有30*N的副本。我们分步来进行它们的创建(即不是同时开始的),然后一直等到它们跑起来。

    (2)在每个冗余控制器上都进行一些操作(扩容,列出所有实例等),把这些操作也分步来做,来测试每个操作的延迟性。这个和一个真实的用户会进行的常规集群操作很类似。

    (3)停止和删除系统内的所有冗余控制器。

        这些测试的结果,请看下面“Kubernetes 1.2参数”的数据。

        在1.3版本中,我们计划会进一步延伸这些测试,内容会包含创建服务、部署、DaemonSets和其他API对象。


Pod启动时间端对端的延迟

        用户对K8S来跳用和启动一个pod所需时间非常感兴趣。这个不仅仅是初次创建pod,而且也包括当节点失败的时候,冗余控制器需要多久来创建一个代替的pod。

        对于这个测试来说(假设N是集群里的节点数量),我们做了:

      (1)创建一个单独的冗余控制器,有30*N的副本,等它们全部都跑起来。我们也跑高密度的测试,有100*N的副本,但集群内的节点数量少一些。

     (2)启用一系列的单个pod的冗余控制器-没200毫秒起一个。对于每一个,我们都测量“端到端启动总时间”(后面会具体定义这个时间)

      (3)停止和删除系统中所有冗余控制器和pods

        端到端启动总时间,我们的定义是指从用户给API server 发送需要生成一个冗余控制器请求那刻开始,一直到pod的“running&ready”这个状态返回给用户,这个过程走表的时间。这意味着,“podstartup time”(pod启动时间)包含了RC的创建,依次序的话即创建pod、调度器调度pod、Kubernetes建立intra-pod的网络、启动容器、等待pod对健康检查成功回应,以及到最后pod把它的状态返回给API server,API server再给用户,这一整个过程的所需时间。

        我们当然可以通过去掉等待的时间或者创建pod的时间来人为大大地缩短“pod startup time”(pod启动时间),但我们还是秉持坚信一个更为广义的定义来契合最为现实的场景,才能使广大用户理解他们对K8S性能的真实期待。

Kubernetes 1.2 实测数据

    所以结果如何呢?我们再Google Compute Engine上跑了测试。对于1000个节点的集群,master使用了一个n1-standard-32的VM(32核,120GB内存)。


API响应

        下面两张图表代表了 99% API调用的延迟在K8S 1.0版本和1.2版本之间的对比,基于100个节点的集群(柱状越短,表现越好)

        对于LIST的操作,我们单独来呈现结果,因为这些操作的延迟要高很多。

        我们也跑了1000个节点的集群的测试。

        因为LIST操作要大的多,所以我们再一次把这些操作的测试结果单独来呈现:所有的延迟,在两个不同的集群尺寸下,都低于1秒。

 


pod启动端到端延迟

        关于“pod启动时间延迟”的结果(即前面说到的“pod端到端延迟”的部分)显示在下图。为了有参考,我们把K8S1.0版本针对100个节点集群的结果也显示在了图里的第一部分。

    

由图可见,K8S 1.2 在性能上显著减少了100个节点集群尾部(即99%这段)延迟时间,现在在K8S可提供的最大集群尺寸范围内可以提供很低的pod启动延迟。跟6个月之前相比,K8S现在1000个节点的集群无论在API调用延迟和pod启动延迟上都有了全方面的提高。

Kubernetes 1.2性能飞跃是怎么做到的:

(1)在API server层面上创建“read cache”(read缓存)

参见: https://github.com/kubernetes/kubernetes/issues/15945

(2)在Kubelet里引入pod生命周期事件发生器(即PLEG -Pod Lifecycle Event Generator)

参见: https://github.com/kubernetes/kubernetes/blob/master/docs/proposals/pod-lifecycle-event-generator.md

(3)提高调度器的流量

参见: https://coreos.com/blog/improving-kubernetes-scheduler-performance.html 

(4)一个更高效的JSON parser

对Kubernetes 1.3版本的规划:

    

    当然,我们工作还远未结束,我们会持续提高Kubernetes的性能,就像Google对内使用Borg那样,把K8S的scale增加到无穷大。基于对底层测试和生产环境中对容器集群的使用场景,我们目前对1.3已经有了如下规划:

        (1)目前的瓶颈依然还是API server,花费大量时间在给JSONobject进行排列。我们家化增加protocol buffer来为集群内的组件沟通以及在etcd内存储JSON objects做可选路径。用户依然可以使用JSON来跟APIserver进行沟通,但由于大量的K8S的沟通是集群内(API server向节点、调度器向API server等)。我们期待使用在master上CPU和memory的消耗会有显著降低。

        (2)Kubernetes使用标签来标示成组的objects。比如,来找到哪些pods属于一个给定的冗余控制器,会需要把所有在同一个namesapce下的并且还符合标签选择器的pod都扫一遍。因此对于做一个有效的标签索引的增加可以充分利用已有的APIobject缓存,这样能更快速的来查找并且匹配符合标签选择器的对象,速度会提高很多。

        (3)调度的决定来自于很多不同的因素,包括基于资源来分布pods,基于相同的选择器来分步pods(比如同一个服务、冗余控制器、工作等)等等。这些计算,尤其是选择器的分步,可能还是有改进空间的,参见:  https://github.com/kubernetes/kubernetes/issues/22262 

        (4)再就是etcd 3.0的发布值得期待,其中在设计上就有Kubernetes应用场景的考虑,将会带来性能上的提高和引入新功能。CoreOS已经在开展把Kubernetes引入etcd3.0版本的工作,参见: https://github.com/kubernetes/kubernetes/pull/22604

    对于K8S 1.3的期待不至于这个列表,可以预见的是,我们将会在K8S1.3看到一个类似从1.0到1.2一样的飞跃。


结语:

        在过去的六个月,我们见证了Kubernetes性能的极大飞跃,能够跑1000个节点的集群,同时还具备和之前版本较小集群规模同样出色的回应性。但我们对此远远不满足,我们会把Kubernetes推到更强大,K8S1.3将会更大程度地提高系统的scale、性能和回应性,同时还会增加新的功能,使得K8S更好地来适应高需求的、基于容器集群的应用。

点击体验,开启谷歌级数字化之旅
立即体验
立即咨询