做者简介git
Darren Shepherd,Rancher Labs联合创始人及首席架构师。在加入Rancher以前,Darren是Citrix的高级首席工程师,他在那里从事CloudStack、OpenStack、Docker的工做,并构建下一代基础设施编排技术。在加入Citrix以前,Darren曾在GoDaddy工做,他设计并领导一个团队实施公有和私有IaaS云。github
本文转自Rancher Labs
2020年年初,Rancher开源了海量集群管理项目Fleet,为大量的Kubernetes集群提供集中的GitOps式管理。Fleet最重要的目标是可以管理100万个分布于不一样地理位置的集群。当咱们设计Fleet架构时,咱们但愿使用标准的Kubernetes controller架构。这意味着咱们能够扩展Kubernetes的数量比以前要多不少。在本文中,我将介绍Fleet的架构、咱们用于测试扩展规模的方法和咱们的发现。
数据库
随着K3s用户量爆发式增加(目前Github Star已经超过15,000),边缘Kubernetes也开始迅猛发展。一些企业已经采用了边缘部署模型,其中每一个设备都是单节点集群。或者你可能会看到使用3个节点的集群来提供高可用性(HA)。关键点在于咱们须要处理的是大量小型集群,而不是一个有不少节点的大型集群。现现在,几乎任何地方的工程师都在使用Linux,他们都但愿使用Kubernetes来管理工做负载。虽然大多数K3s的边缘部署少于10,000个节点,但达到100万个节点并不是不可能。而Fleet将知足你的规模扩展要求。
api
Fleet架构的关键部分以下:缓存
Fleet使用两阶段pull方法架构
Fleet是一组由标准K8S API交互驱动的K8S Controlleride
Fleet agent不须要一直保持链接测试
要从git中进行部署,Fleet Manager首先要复制并存储git中的内容,而后Fleet manager决定须要使用git中的内容更新哪一个集群,并建立部署记录供agent读取。当agent能够读取时,agent将check in以读取部署集群,部署新的资源并报告状态。
设计
咱们使用两种方法来模拟100万个集群。首先,咱们部署了一组大型VM(m5ad.24xlarge - 384 GiB RAM)。每一个VM使用k3d运行10个K3s集群。而后这10个集群每一个都运行750个agent,每一个agent都表明着一个下游的集群。总的来讲,每一个VM模拟7500个集群。平均来看,部署一个VM、在Fleet注册全部集群并达到稳定状态大约须要花费40分钟。在两天的时间里,咱们以这种方式启动虚拟机,直到达到10万个集群。在最初的10万个集群中,咱们发现了大部分的扩展问题。在解决了这些问题以后,扩展变得至关可预测。以这一速度,模拟剩下的90万个集群将会花费很长的时间以及至关可观的资金。
3d
而后,咱们采用第二种方法:运行一个模拟器,它能够执行100万个集群会进行的全部API调用,而不须要下游的Kubernetes集群或部署Kubernetes资源。取而代之的是,模拟器进行API调用以注册新集群、发现新部署并报告它们的成功状态。使用这种方法,咱们在一天内实现了从0到100万个模拟集群。
Fleet manager是一个运行在Kubernetes集群上的controller,运行在3个大型虚拟机(m5ad.24xlarge - 384 GiB RAM)和一个RDS(db.m5.24xlarge)实例上。实际上,咱们使用K3s来运行Fleet Manager集群。咱们这样作是由于Kine已经在其中集成了。我将在后面解释什么是Kine以及为何使用它。尽管K3s针对的是小规模的集群,但它多是最容易大规模运行的Kubernetes发行版,咱们使用它是由于其简单易用。值得注意的是,在EKS这样的托管提供商上,咱们没法大规模运行Fleet,稍后我会解释这一点。
咱们遇到的第一个问题彻底出乎意料。当一个Fleet agent注册到Fleet Manager时,它会使用一个临时的集群注册令牌(token)。而后,该令牌被用来为该集群/agent建立新的身份和凭证。集群注册令牌和该agent的凭证都是服务帐户。咱们注册集群的速度受到controller-manager为服务帐户建立令牌的速度的限制。通过研究,咱们发现咱们能够修改controller-manager的默认设置来提升咱们建立服务帐户的速度(-concurrent-serviceaccount-token-syncs=100)和每秒API请求的整体数量(-kube-api-qps=10000)。
Fleet是做为Kubernetes Controller编写的。所以,将Fleet扩展到100万个集群意味着要在Kubernetes中管理数千万个对象。正如咱们所了解的,etcd并无能力管理这么大的数据量。Etcd的主要空间有8GB的限制,默认设置为2GB。关键空间包括当前的值和它们以前还没有被垃圾收集的值。在Fleet中,一个简单的集群对象大约须要6KB。对于100万个集群,咱们至少须要6GB。可是一个集群通常包含10个左右的Kubernetes对象,加上每一个部署一个对象。因此在实际操做中,咱们更有可能须要超过100万个集群10倍的内存空间。
为了绕过etcd的限制,咱们使用了Kine,这使得使用传统的RDBMS运行任何Kubernetes发行版成为可能。在这个规模测试中,咱们运行了RDS db.m5.24xlarge实例。咱们没有尝试对数据库进行适当的大小调整,而是从最大的m5实例开始。在测试结束时,咱们在Kine中拥有大约2000万个对象。这意味着以这种规模运行Fleet不能在EKS这样的托管提供商上进行,由于它是基于etcd的,也不会为咱们的需求提供足够可扩展的数据存储。
这个测试彷佛并无把数据库push得很厉害。诚然,咱们使用了一个很是大的数据库,但很明显咱们还有不少垂直扩展的空间。单条记录的插入和查找继续以可接受的速度进行。咱们注意到,随机列出大量对象(最多一万个)将会花费30秒到一分钟的时间。但通常来讲,这些查询会在不到1秒的时间内完成,或者在很是粗暴的测试下5秒也能够完成。由于这些耗时很长的查询发生在缓存重载期间,因此对系统总体影响不大,咱们将在后面讨论。尽管这些缓慢的查询并无对Fleet形成明显的影响,但咱们仍是须要进一步调查为何会出现这种状况。
当controller加载缓存时,首先会列出全部对象,而后从列表的修订版开始监控。若是有很是高的变化率而且列出对象花费了很长的时间,那么你很容易陷入这样的状况:你完成了列表但没法启动监控,由于API Server的监控缓存中没有这个修订版,或者已经在etcd中被压缩了。做为一个变通办法,咱们将监控缓存设置为一个很是高的值(–default-watch-cache-size=10000000)。理论上,咱们认为咱们会遇到Kine的压实问题(compact),但咱们没有,这须要进一步调查。通常来讲,Kine在压实(compact)的频率上要低不少。但在这种状况下,咱们怀疑咱们添加记录的速度超过了Kine压实的速度。这并不糟糕。咱们并不但愿坚持要保持一致的变化率,这只是由于咱们正在快速注册集群。
Kubernetes controller的标准实现是将你正在处理的全部对象缓存在内存中。对于Fleet,这意味着咱们须要加载数百万个对象来创建缓存。对象列表的默认分页大小为500。加载100万个对象须要2000个API请求。若是你假设咱们能够每秒钟进行一次列表调用、处理对象并开启下一页,这意味着加载缓存须要30分钟左右。不幸的是,若是这2000个API请求中的任何一个失败,这个过程就会从新开始。咱们尝试将页面大小增长到10,000个对象,但看到总体加载时间并无明显加快。咱们开始一次列出1万个对象以后,咱们就遇到了一个问题,Kine会随机花费超过1分钟的时间来返回全部对象。而后Kubernetes API Server会取消请求,致使整个加载操做失败,不得不从新启动。咱们经过增长API请求超时(-request-timeout=30m)来解决这个问题,但这不是一个可接受的解决方案。保持较小的页面大小能够确保请求的速度更快,但请求的数量增长了失败概率,并致使整个操做重启。
重启Fleet controller将须要花费45分钟的时间。这一重启时间一样适用于kube-apiserver和kube-controller-manager。这意味着你须要很是当心。这也是咱们发现运行K3s不如运行RKE等传统发行版的一点。K3s将api-server和controller-manager结合到同一个进程中,这使得重启api-server或controller-manager的速度比本来应有的速度慢,并且更容易出错。模拟一场灾难性的故障,须要彻底重启全部服务,包括Kubernetes,这一切花了几个小时才恢复上线。
加载缓存所需的时间和失败的概率是迄今为止咱们发现的扩展Fleet的最大问题。从此,这是咱们要解决的首要问题。
经过测试,咱们证实了Fleet的架构能够扩展到100万个集群,更重要的是,Kubernetes能够做为一个平台来管理更多的数据。Fleet自己与容器没有任何直接的关系,能够当作只是一个简单的应用,在Kubernetes中管理数据。这些发现为咱们开启了一个可能性,即把Kubernetes更多的看成一个通用的编排平台来写代码。当考虑到你能够很容易地将一套controller与K3s捆绑在一块儿,Kubernetes就变成了一个很好的自成一体的应用server。
在扩展规模方面,从新加载缓存所需的时间使人担心,但绝对是可控的。咱们将继续在这方面进行改进,使运行100万个集群不只是可行的,并且是简单的。由于在Rancher Labs,咱们喜欢简单。