作者|TanLin本文介绍了美团如何解决大规模集群管理问题,并设计出优秀合理的集群调度系统。当Kubernetes作为云原生技术的代表,我们更关心的问题、挑战和相应的推广策略。同时本文也介绍了一些针对美团业务需求场景的特殊支持。希望这篇文章能够帮助或者启发对云原生领域感兴趣的同学。集群调度系统简介大规模集群管理难点简介运营大规模集群的挑战集群调度系统设计时的选择美团集群调度系统演进之路多集群统一调度:提升数据中心资源利用调度引擎服务:为PaaS赋能云原生实现服务的未来展望:构建云原生操作系统简介集群调度系统在企业数据中心中扮演着举足轻重的角色。随着集群规模和应用数量的不断增加,开发者处理业务问题的复杂度也大幅增加。如何解决大规模集群管理问题,设计优秀合理的集群调度系统,保证稳定性、降低成本、提高效率?本文将一一解答。|备注:文章首发于《新程序员003》云原生时代开发者专栏。集群调度系统简介集群调度系统又称数据中心资源调度系统,一般用于解决数据中心的资源管理和任务调度问题。其目标是实现数据中心资源的有效利用,提高资源利用率,并为业务方提供自动化运维能力,降低服务运维管理成本。业界知名的集群调度系统,如开源OpenStack、YARN、Mesos、Kubernetes等,知名互联网公司如谷歌的Borg、微软的Apollo、百度的Matrix、阿里巴巴的伏羲、ASI等。集群调度系统作为互联网企业最核心的IaaS基础设施,在过去十年间经历了多次架构演进。随着业务从单体架构向SOA(Service-OrientedArchitecture)演进和微服务的发展,底层IaaS设施也逐渐从裸机物理机时代走向容器时代。虽然在演化过程中我们要处理的核心问题没有发生变化,但是由于集群规模和应用数量的快速膨胀,问题的复杂度也呈指数级增长。本文将阐述大规模集群管理面临的挑战和集群调度系统的设计思路,并以美团集群调度系统的实现为例,阐述如何通过创建多集群来持续提高资源利用率。集群统一调度服务,并提供Kubernetes引擎服务赋能。PaaS组件、更好的业务计算服务体验等一系列云原生实践。大规模集群管理的难度众所周知,业务的快速增长带来服务器规模和数据中心数量的激增。对于开发者来说,在大规模集群调度系统的业务场景中,必须解决两个难题:如何管理大规模集群在数据中心的部署和调度,尤其是在跨数据中心的场景下,如何实现资源分配的弹性和调度能力,在保证应用服务质量的前提下,尽可能提高资源的利用率,充分降低数据中心的成本。如何改造底层基础设施,为业务端打造云原生操作系统,提升计算服务体验,实现应用的自动容灾响应和部署升级等,减轻业务端对业务端的精神负担底层资源管理,让业务方更专注于业务本身。大规模集群运维的挑战为了在真实的生产环境中解决以上两个问题,可以进一步分解为以下四大大规模集群运维管理的挑战:如何解决用户多样化的需求并快速响应.业务调度需求和场景丰富且动态。作为集群调度系统等平台服务,一方面需要能够快速交付功能,及时满足业务需求;将需求抽象成平台上可以实现的通用能力,并长期迭代。这是对平台服务团队技术演进规划的考验,因为一不小心,团队就会陷入无休止的业务功能开发。虽然满足了业务需求,但会造成团队工作的低水平重复。如何在保证应用服务质量的同时提高在线应用数据中心的资源利用率。资源调度一直是业界公认的难题。随着云计算市场的快速发展,各家云计算厂商不断加大对数据中心的投入。数据中心的资源利用率很低,加剧了问题的严重性。Gartner研究发现,全球数据中心服务器的CPU利用率只有6%到12%,甚至亚马逊弹性计算云(EC2,ElasticComputeCloud)的资源利用率也只有7%到17%,这表明资源浪费有多严重。原因在于在线应用对资源利用率非常敏感,业界不得不预留额外的资源来保证重要应用的服务质量(QoS,QualityofService)。集群调度系统需要消除多个应用程序混合运行时应用程序之间的干扰,实现不同应用程序之间的资源隔离。如何为应用,尤其是有状态应用提供实例异常的自动处理,屏蔽机房差异,减少用户对底层的感知。随着服务应用规模的不断扩大和云计算市场的成熟,分布式应用往往部署在不同区域的数据中心,甚至跨越不同的云环境,实现多云或混合云部署。集群调度系统需要为业务端提供统一的基础设施,实现混合多云架构,屏蔽底层异构环境。同时降低应用运维管理的复杂度,提高应用的自动化程度,为业务提供更好的运维体验。如何解决单个集群过大或集群过多导致的集群管理相关的性能和稳定性风险。集群本身生命周期管理的复杂度会随着集群规模和数量的增加而增加。以美团为例,我们采用的两地多中心多集群方案,在一定程度上避免了集群过大带来的隐患,解决了业务隔离、地域延迟等问题。随着边缘集群场景、数据库等PaaS组件云化需求的出现,可以预见小型集群的数量将有明显的上升趋势。由此带来的集群管理复杂度、监控配置成本、运维成本都大幅增加。此时,集群调度系统需要提供更有效的运行规范,保障运行安全、告警自愈和变更效率。设计集群调度系统时的权衡为了应对上述挑战,一个好的集群调度器将发挥关键作用。但现实中从来没有完美的系统,所以在设计集群调度系统时,我们需要根据实际场景在几个矛盾中做出取舍:集群调度系统的系统吞吐量和调度质量。系统吞吐量是我们评价一个系统好坏的重要标准,但是在一个在线的面向服务的集群调度系统中,调度质量更为重要。因为每次调度结果的影响都是长期的(几天,几周,甚至几个月),非异常情况不做调整。因此,如果调度结果有误,将直接导致业务延迟增加。调度质量越高,需要考虑的计算约束越多,调度性能越差,系统吞吐量越低。集群调度系统的架构复杂性和可扩展性。系统对上层PaaS用户开放的功能和配置越多,支持的提升用户体验的功能就越多(比如支持应用资源抢占和应用实例的回收和自愈),意味着系统的复杂度更高,而且各个子系统更容易发生冲突。集群调度系统的可靠性和单集群规模。单个集群规模越大,调度范围越大,但对集群可靠性的挑战也越大,因为爆炸半径会变大,故障影响会更大。在小单体集群的情况下,虽然可以提高调度并发度,但是调度的范围变小,调度失败的概率变高,集群管理的复杂度变大。目前业界的集群调度系统可以分为单级调度器、二级调度器、共享状态调度器、分布式调度器和混合调度器五种不同的架构(见下图1)。都是根据各自的场景需求做出了不同的选择,没有绝对的好坏之分。图1集群调度系统架构分类(来自MalteSchwarzkopf-集群调度器架构的演进)单体式调度器使用复杂的调度算法结合集群的全局信息计算出高质量的放置点,但延迟较高。比如Google的Borg系统,开源的Kubernetes系统。二级调度器通过将资源调度与作业调度分离,解决了单片调度器的局限性。二级调度器允许根据具体的应用有不同的作业调度逻辑,同时保持了不同作业之间共享集群资源的特性,但无法实现高优先级应用的抢占。代表系统有ApacheMesos和HadoopYARN。共享状态调度器以半分布式的方式解决了两级调度器的局限性。共享状态下的每个调度器都有一份集群状态副本,调度器独立更新集群状态副本。一旦本地状态副本发生变化,整个集群的状态信息都会更新,但是持续的资源争用会导致调度器的性能下降。代表系统是谷歌的Omega和微软的Apollo。分布式调度器使用相对简单的调度算法来实现大规模高吞吐量、低延迟的并行任务放置。但由于调度算法相对简单,缺乏全局的资源使用视角,难以实现高质量的作业安置效果。加州大学的Sparrow等性系统。混合调度程序将工作负载分散到集中式和分布式组件中,对长时间运行的任务使用复杂的算法,而对短期运行的任务则依赖分布式布局。MicrosoftMercury就采用了这种方法。因此,如何评价一个调度系统的好坏主要取决于实际的调度场景。以业界使用最广泛的YARN和Kubernetes为例。虽然这两个系统都是通用资源调度器,但实际上YARN侧重于短任务的离线批处理,而Kubernetes侧重于在线长时间运行的服务。除了架构设计和功能上的差异(Kubernetes是单调度器,YARN是二级调度器),两者的设计理念和视角也不同。YARN更专注于任务,注重资源复用,避免远程数据多副本。目标是以更低的成本和更高的速度执行任务。Kubernetes更关注服务状态,关注错峰、服务画像、资源隔离,以保障服务质量为目标。美团集群调度系统的演进在容器化的过程中,美团根据业务场景的需要,将集群调度系统的核心引擎从OpenStack换成了Kubernetes,并完成了98%以上的在线业务容器化覆盖。2019年底既定目标。但仍面临资源利用率低、运维成本高等问题:集群整体资源利用率不高。例如,CPU资源的平均利用率仍处于行业平均水平,远远落后于其他一线互联网公司。有状态服务容器化率不够,尤其是MySQL、Elasticsearch等产品没有使用容器,在业务运维成本和资源成本上有很大的优化空间。考虑到业务需求,VM产品会长期存在,VM调度和容器调度是两个环境,导致团队虚拟化产品运维成本高。因此,我们决定启动集群调度系统的云原生改造。构建具有多集群管理和自动化运维能力的大规模高可用调度系统,支持调度策略推荐和自助配置,提供云原生底层扩展能力,在保证应用服务质量的同时提高资源利用率.核心工作是围绕保障稳定、降低成本、提高效率三个方向构建调度体系。保证稳定性:提高调度系统的健壮性和可观测性;降低系统各模块之间的耦合度,降低复杂度;提升多集群管理平台的自动化运维能力;优化核心系统组件的性能;保证大规模集群的可用性。降低成本:深度优化调度模型,打通集群调度与单机调度的衔接。从静态资源调度到动态资源调度,引入离线业务容器,形成自由竞争和强控制的结合。在保证优质业务应用服务质量的前提下,提高资源利用率,降低IT成本。提升效率:支持用户根据个性化业务需求自主调整调度策略,积极拥抱云原生领域,为PaaS组件提供编排、调度、跨集群、高可用等核心能力,提升运维效率.图2美团集群调度系统架构图最后,美团集群调度系统架构按照领域分为三层(见上图2),调度平台层,调度策略层,调度引擎层:平台层负责针对业务接入,打通美团基础设施封装原生接口和逻辑,提供容器管理接口(扩容、更新、重启、缩容)等功能。策略层提供多集群统一调度能力,持续优化调度算法和策略,结合业务服务水平和敏感资源,通过服务分级提高CPU使用率和分配率。引擎层提供Kubernetes服务,保障多个PaaS组件云原生集群的稳定性,将通用能力下沉到编排引擎,降低业务云原生实现的接入成本。通过精细化运营和产品功能打磨,我们一方面管理了近百万个美团容器/虚拟机实例,另一方面将资源利用率从行业平均水平提升至一流水平,同时支持PaaS组件容器化和云原生落地。多集群统一调度:提高数据中心资源利用率评价和评估集群调度系统的好坏,资源利用率是最重要的指标之一。因此,虽然我们在2019年完成了容器化,但容器化不是目的,而是手段。我们的目标是通过从VM技术栈到容器技术栈的切换,给用户带来更多的收益,比如全面降低用户的计算成本。资源利用率的提高受到集群中个别热点主机的限制。一旦扩容,业务容器就可以扩展到热点主机。TP95耗时等业务绩效指标会出现波动,所以我们只能跟同行业的其他公司一样。通过增加资源冗余来保证服务质量。原因是Kubernetes调度引擎的分配方式简单的考虑了Request/LimitQuota(Kubernetes为容器设置请求值Request和约束值Limit,作为用户申请容器的资源配额),属于静态资源分配。这样一来,虽然不同的主机分配了相同数量的资源,但由于主机服务的不同,主机的资源利用率也存在很大差异。在学术界和工业界,有两种常见的方法来解决资源使用效率和应用程序服务质量之间的冲突。第一种方法是通过高效的任务调度器,从全局的角度来解决;第二种方法是通过单机资源管理来加强应用程序之间的资源隔离。无论采用哪种方式,都意味着我们需要全面掌握集群状态,所以我们做了三件事:系统地建立了集群状态、主机状态、服务状态的关联,并结合调度仿真平台,综合考虑了峰值利用率和平均利用率,实现了基于主机历史负载和业务实时负载的预测和调度。通过自主研发的动态负载调整系统和跨集群重调度系统,实现集群调度与单机调度环节的联动,根据业务分类实现不同资源池的服务质量保障策略。经过三次迭代,实现了自己的集群联邦服务,更好的解决了资源预占和状态数据同步的问题,提高了集群间的调度并发性,实现了计算分离、集群映射、负载均衡、跨集群编排控制(参见下面的图3)。图3ClusterfederationV3版本架构第三版Clusterfederationservice按模块分为Proxy层和Worker层,独立部署:Proxy层会根据集群状态的因素和权重综合选择合适的集群进行调度,并选择合适的Worker分布询问。Proxy模块使用etcd进行服务注册、领导者选择和发现。Leader节点负责调度时抢占任务,所有节点都可以负责查询任务。Worker层对应处理Cluster的一部分查询请求。当集群任务阻塞时,可以快速扩展对应的Worker实例来缓解问题。当单个集群规模较大时,会对应多个Worker实例,Proxy将调度请求分发给多个Worker实例处理,提高调度并发度,降低每个Worker的负载。最后,通过多集群统一调度,实现了从静态资源调度模型到动态资源调度模型的转变,从而降低热点主机占比,降低资源碎片化比例,保证优质的服务质量业务应用程序。平均CPU利用率提高了10个百分点。集群资源利用率平均值的计算方法:Sum(nodeA.cpu.当前使用的核数+nodeB.cpu.当前核数+xxx)/Sum(nodeA.cpu.总核数+nodeB.cpu.总核数+xxx),每分钟一个点,当天所有数值取平均值。调度引擎服务:赋能PaaS服务云原生落地集群调度系统,不仅解决了资源调度问题,还解决了服务使用的计算资源问题。《Software Engineering at Google》一书中提到,集群调度系统作为ComputeasaService的关键组成部分之一,既要解决资源调度(从物理机拆解到CPU/Mem资源维度),又要解决资源竞争(解决“嘈杂邻居”问题)》)和应用管理(实例的自动化部署、环境监控、异常处理、服务实例数量保证、业务所需资源的确定、不同类型的服务等)。并且在某种程度上,应用管理比资源调度更重要,因为它会直接影响业务开发、运维和服务容灾的效率。毕竟互联网的人工成本高于机器成本。复杂有状态应用的容器化一直是业界的难题,因为这些不同场景下的分布式系统通常都会维护自己的状态机。当应用系统进行扩容或升级时,如何保证现有实例服务的可用性,以及如何保证它们之间的连通性,是比无状态应用复杂和棘手得多的问题。虽然我们有了容器化的无状态服务,但我们还没有完全意识到一个好的集群调度系统的全部价值。要想管理好计算资源,就必须对服务的状态进行管理,将资源与服务分离,提高服务的弹性。这就是Kubernetes引擎所擅长的。基于美团优化定制的Kubernetes版本,我们打造了美团Kubernetes引擎服务MKE:加强集群运维能力,完善集群自动化运维能力建设,包括集群自愈、告警系统、Event日志分析等,持续提升集群的Observability。建立关键业务标杆,与多个PaaS重要组件深度合作,快速优化Sidecar升级管理、Operator灰度迭代、告警分离等用户痛点,满足用户需求。持续提升产品体验,持续优化Kubernetes引擎。除了支持用户使用自定义Operator,它还提供了通用的调度编排框架(见图4),帮助用户以更低的成本接入MKE,获得技术红利。图4美团KubernetesEngine服务调度编排框架在推动云原生落地的过程中,一个被广泛关注的问题是:基于Kubernetes云原生方式管理有状态的应用,与之前自己搭建管理平台相比,有什么区别??对于这个问题,我们需要考虑问题的根源——可操作性:基于Kubernetes意味着系统实现了闭环,不用担心两个系统之间经常出现的数据不一致问题。可以做到毫秒级的异常响应,降低了系统的RTO(RecoveryTimeObjective,即恢复时间目标,主要是指业务停止服务所能容忍的最长时间,也是从灾难到业务系统恢复服务功能所需的最短时间周期)。也降低了系统运维的复杂度,服务实现了自动容灾。除了服务本身,服务所依赖的配置和状态数据都可以一起恢复。相比以往各PaaS组件的“烟囱式”管理平台,通用能力可以下放到引擎服务,降低开发和维护成本,并且依托引擎服务屏蔽底层异构环境,实现跨数据中心和多云环境服务管理。未来展望:构建云原生操作系统我们认为,云原生时代的集群管理将从以往管理硬件和资源的功能,全面转变为以应用为中心的云原生操作系统。带着这个目标,美团集群调度系统还需要重点关注以下几个方面:应用链路交付管理。随着业务规模和链路复杂度的增加,业务所依赖的PaaS组件和底层基础设施的运维复杂度已经超出了一般认知,对于刚接手项目的新人来说更是难上加难。因此,我们需要支持业务通过声明式配置交付服务并实现自主运维,为业务提供更好的运维体验,提高应用的可用性和可观察性,减轻业务对业务的负担。底层资源管理。边缘计算解决方案。随着美团业务场景的不断丰富,业务对边缘计算节点的需求增长速度远超预期。我们将参考行业最佳实践,形成适合美团的边缘解决方案,尽快为有需求的服务提供边缘计算节点管理能力,实现云边端协同。离线混合能力建设。线上业务集群资源利用率的提升是有上限的。根据谷歌在论文中披露的2019年数据中心集群数据,剔除离线任务,在线任务的资源利用率只有30%左右,这也说明进一步升级的风险更大,投入-产出比不高。未来,美团集群调度系统将继续探索线下混合部门。但是由于美团的线下机房相对独立,所以我们的实现路径会和业界通用的方案不一样。我们将从在线服务和近乎实时的任务开始。从底层做起,完成底层能力建设,再探索线上任务和线下任务的混合。综上所述,在设计美团集群调度系统时,总体遵循适度原则。在满足业务基本需求的情况下,保证系统稳定,然后逐步完善架构,提高性能,丰富功能。因此,我们选择了:在系统吞吐量和调度质量上,我们选择优先满足业务对系统的吞吐量需求,不过度追求单一的调度质量,而是通过重调度调整来提高。在架构复杂度和可扩展性方面,我们选择降低系统各个模块之间的耦合度来降低系统复杂度,扩展的功能必须是可降级的。在可靠性和单集群规模方面,我们选择通过多集群统一调度来控制单集群规模,保证系统可靠性,减小爆炸半径。未来,我们将按照相同的逻辑,不断优化迭代美团的集群调度系统,将其彻底转型为以应用为中心的云原生操作系统。作者简介谭林,美团基础研发平台/基础技术部。
