导语: 本文以资源分配理念:拍卖、预算、抢占出发,引出Borg、Omega、Mesos、Kubernetes架构、数据、API的特点比较。然后梳理资源共享各种不同共享形式的内容,接着对比任务类型,最后回到资源利用率和基于数据预测角度,看相关系统是如何运用的和实现各自场景目标的。最后给出 阿里巴巴 电商在线服务资源调度器Zeus关键技术内容。
需要指出的是,进入这个领域的门槛不在具体某个技术,而业务场景和技术选型的映射匹配,特别是周边系统的完善程度,决定了如何选择方案、如何制定落地计划。整篇文章不是为了全面分析某个调度器,也不是全面对比某个关键点在不同调度器之间特色,而是以作者经验理解,在一个新场景下,如果需要设计或者完善一个资源调度器,那么,应该梳理那些关键场景和需求。选择性地从已有调度器系统吸取架构或模块经验,最低成本实现贴合自身业务场景的资源调度器。例如吸取调度器二层架构模式、数据集中管理方式、统一RestFull API、资源 分时 共享策略、在离线任务类型抽象等。
本文避免讨论生态,因为太过庞大,超出本文的主题。
关键词:资源调度器 Borg Omega Mesos Kubernetes Zeus
以下是正文:
1.资源分配理念看已有调度器
在资源调度器中,资源分配理念:拍卖、预算或抢占,往往是混合运用。资源分配理念,折射出了资源调度器所在的生态系统或者说周边配合系统的成熟度、运行习惯。例如, Google 从最早的广告拍卖机制起,拍卖的理念在Google内部就形成了一种经验、选择的爱好或者内部的默契,那么资源竞拍被分配出来的结果,大家很容易达成一致、理解。而国内企业,往往是预算驱动,周边系统的运行习惯,更趋向预算、采购,谁预算谁使用。这种环境下,资源被谁使用基本可以预见,成本也是比较容易找到归属者。在拍卖机制下资源抢占,初始分配是不大会发生,只有在运行时发生资源不够用的时候出现,低优先级的任务被Kill。在预算机制下,资源分配初期、运行时过程中,都会发生抢占。不同哪种分配背后共同追求的资源流动性是一致的。拍卖的另外一种好处是便于资源流动起来,不仅是资源利用率提升,更是资源投入产出比的最大化。而预算往往是一次性的,重点业务资源优先保障,使得适应性、灵活性、激励业务效率提升变得不如拍卖。
不同策略落地在架构、数据、API层面有着非常多的共同之处。从中不难发现Borg是始祖,后来的Mesos、Omega、Kubernetes、Zeus等都延续着Borg的某些重要特征,而又随技术发展,引入新的特征。针对每个系统的具体分析,可以参照Google、Baidu上通过关键词查询出来的相关文章或者各系统发表过的论文及官方文档[1,2,3,4,5,6,7]。
1.1 架构层面
Borg
调度器架构图如图1所示[2],是Google建造的一个主控制核心,管理公司所有的数据库。两级优先级:服务性的高优先级和批处理的低优先级。两阶段调度:找到可行的节点,然后为最终放置对这些节点评分。
图1 Borg架构图
Borglet向Master汇报状态,从而master确认borglet是否存活,以及是否需要执行Borglet上的任务迁移等操作。任务、资源的状态数据更新是周期性的,而不是变化通知机制。
Job使用BCL来描述,通过RPC命令tool提交到Borg master。Borg大量的调度任务属于Jobs,但是集群70%左右的CPU是给service的。
Borg 一层框架,在框架上跑Schedule。框架是Borglet和BorgMaster之间进行状态通信,确保资源存活性、任务运行时数据收集,同时PAXOS协议,确保多master数据一致性,支持并发和容灾。而Schedule与BorgMaster进行数据读写,实现资源的分配和回收管理等。
Mesos
Twitter研发的超级网络系统,Mesos的出现比YARN早,引入两级调度的理念。两级调度通过一个名为资源邀约的新API发起,邀约是有时间限制的,激励应用程序去实现快速地调度。Mesos[3]里面并没有拍卖的影子,更注重公平性,允许短任务预留一些资源。时间期限就是资源的共享的生命周期。在Mesos中,资源邀约是悲观的或独占的。如果资源已经提供给一个应用程序,同样的资源将不能提供给另一个应用程序,直到邀约超时。
Borg和Mesos并不只是能让他们的服务器群智能化处理他们的数据,他们还让管理集群就像操作一台机器一样处理所有的数据[7]。
Omega
重点在介绍基于状态的资源管理组件,Omega[4]的资源管理器基本上,只是一个记录每个节点状态的关系数据库,使用不同类型的乐观并发控制解决冲突。这样的好处是大大增加了调度器的性能(完全并行)和更好的利用率。
Omega采取多版本控制的、乐观锁机制在遇到偶尔的资源冲突时候。所有资源状态存储在基于PAXOS协议实现的事物系统中,外部调度器访问并执行资源调度。
Kubernetes
作为Docker生态圈中重要一员,由Google开源,整个设计重点之一在于方便分布式复杂应用的部署和管理[5,6]。Kubernetes吸收了Borg使用过程中大量的实践经验,当然整个系统因为涵盖的功能较多,延续Borg完备、复杂性,相对Mesos等稍微简单些。Kubernetes面向云端,需要考虑的功能点非常多。例如网络、负载均衡、资源管理、高可用、镜像更新、存储、安全、监控等。Kubernetes架构如图2所示。
图2 Kubernetes架构图
总结: 主动、定时汇报的框架,还是变更通知的框架比较适合呢?状态基于PAXOS协议分布式事务一致性,还是集中数据库存储基于实践的成本、简单性、阶段目标出发,变更通知和数据库可以精简系统、快速搭建原型。如果要应对百万级服务器,那么PAXOS协议、定时汇报应该就是标配的技术方案了。通知模式,消息重发(发的频率、次数)、消息处理(脏数据、临界数据)、数据补偿等需要仔细设计,避免时不时的消息数据错误导致资源使用不一致,引发后续解救。PAXOS协议脑裂是一个潜在的风险,但是,相对通知模式还是显得优雅和透明些。
两级调度:第一级选择机器(也就是业务编排),第二级分配容器资源。或者第一级选资源,第二级业务编排组织。这个过程,局部最优可以加速资源调度性能,全局最优可以获取最佳的资源位。具体场景具体选择,并且都可以作为参数传入调度器。
两种或多种优先级:高优先级、低优先级,分别对应在线服务、监控服务、运维服务,离线短周期Jobs、批量Jobs等。业务优先级的定义和变更,需要业务层面全局的评估和系统自动化更新,并及时反馈到调度器中。业务方都趋向把自己的业务定位高优先级。确定不可抢占业务。
并发支持的程度和粒度,面向链路也就是队列,还是面向资源状态。每次申请资源全局最优还是局部最优,一旦发生冲突,乐观锁还是悲观锁。实践经验,先解决业务需求,求得生存,然后优化性能。
在整个架构之外,模拟器也是非常重要的子系统。尤其是资源调度器这种基础的服务系统,资源一旦分配错误或者不可用,造成的影响非常大。整个结构友好的支持模拟数据进行算法验证必不可少。总是假设, 容器技术 、生态的其他产品都是可信赖、高可用、跨语言API服务的。
1.2 数据层面
Borg
在Google已经运行了10多年,是一个效率极高的系统。典型的Borgmaster使用10至14个内核和50GB内存,数据主要集中在内存。1分钟启停1万个task进程。99%的Web UI响应时间小于1s,95%的polling borglet时间小于10s。针对成千上万节点,每分钟调度的速率为10K任务。典型调度时间是25秒左右(这依赖于具体节点的本地化。下载二进制占这个时长的80%,Torrent和树协议用于分发二进制文件)。单个cell内部98%机器都是混跑(prod/non-prod, long-running service/batch jobs),整个Borg系统中83%的机器是混跑。意味着Google资源共享不是简单的固定配额共享,又或者整机交付的共享,而是实时动态的共享。
在混部CPI方面,增加作业会导致其他作业进程CPI增加0.3%(CPI越大表示程序执行越慢),机器CPU使用率每增加10%会导致作业进程CPI增加2%。混跑集群平均CPI 1.58,专用集群1.53。另外Borglet的CPI:混跑1.43,专用1.20。结论:CPI差别不大,因此混跑并不会显著的降低程序运行时间!
资源利用率主要的度量指标是单元压缩。也就是一个业务单元使用的资源最小化程度。一个典型的cell中,prod作业调度占70% CPU,55%Memory,实际使用占60% CPU,85% Memory。通过Borglet的周期性、实时计算,调整资源实例的配额,从而进行资源压缩。配置或者Jobs调度参数等都以JSON或者YAML格式实现。
Google的效率,从Google一个PE可以运维上万台服务器,可见相当先进了。
成本计费方面:将Job的提交、配置、具体每个task的资源使用情况都保存到一个数据库中,并提交SQL查询,供计费、debug、错误分析、容量规划。
Mesos
更关注资源公平性,简化了Borg的复杂性,做得相当薄,只有10K行代码。
Omega
典型的集群利用率约为60%。秒级的调度时间是典型的。
Kubernetes
Google开源的Golang语言实现的、支持Docker容器的新一代资源调度器。和Borg Omega一样,都有一个共享的持久化状态存储模块,用于实现资源状态一致性。Borg的Job Conf里有230个参数,用户tune代价大、易出错,Kubernetes做了参数的自动化适应。
总结: 数据也就是资源状态以及调度分布数据,持久化DB还是Paxos协议实现的分布式事务存储,没有最好,只有更好。不过,提供API查询,特别是页面可视化操作,都是必须的。有时候对资源分配的结果,也是需要可解释的,这依赖数据可视化、中间过程透明化。
流程或者分配或者运行时或者异常故障等数据的沉淀,用于故障分析、完善周边系统、动态修正实例配额、容量水位、容量准入。数据沉淀并分析是非常有价值的。
成本计算基于调度器历史过程申请资源的使用规模和时间,还是基于业务预算的资源,还是最后落地的流程记录数据,不论哪种方式,对资源的粒度和时间片的统一界定非常重要。
所有对数据的操作在资源调度器层,尽量限制在原子层面,流程或者业务数据一致性交给上层或者业务发起端控制。这样,资源调度器层基本无状态、原子更新,分布式一致性就比较简单、集中。业务需求,交给业务处理。如果业务层校验或者其他要求,资源不满足需求,要么业务层自我修复,要么业务层要向链路下游层层回滚,最终确保资源调度器资源申请和使用最终一致性。否则,资源数据不一致引发资源超卖或者资源提前“用完”,而实际有资源的尴尬。
1.3 API 层面
Borg
缓存的机器分数、每种任务类型计算一次的可行性,在做调度决策时,不要试图全局最优。复杂的规范语言。整个master是一个API server,其他的调度、admiss IO n管理都是作为服务,以client访问API server,对外提供丰富的生态工具,例如脚本、web管理页面、控制台命令等。通过Http 协议实现的序列API,执行容器到资源分配管理的几乎全部操作。支持以标签形式动态调整应用的属性,从而影响Jobs调度策略。
Mesos
Mesos API[3]包括Scheduler Http、Executor Http、internal C++ API。Mesos已经开始引入更多Kubernetes的概念来支持Kubernetes API [3]。仔细的比较Mesos、Kubernetes两者的生态、开源社区发展,两者之间的竞争是明显的。虚拟机友好化、容器类(例如Docker)友好化的API或者二次开发,成为业界选择的焦点。Mesos目前对计算集群支持的比较友好,而Kubernetes对虚拟机,尤其是云端支持的更友好。
Omega
Omega 基于Borg发展起来的Google新一代系统,Omega论文并没有给出详细API说明。Omega重点在对比过去的架构和新架构的优势,API猜测基本延续了Borg的相关功能。当对比讨论Omega的时候,Mesos已经开源,许多概念已经在Mesos中实现了。当讨论Kubernetes的时候,自然想到Mesos的冲击力,并随着Docker容器技术的兴起、云计算的发展,人们开始忘记Omega,似乎只有Mesos和Kubernetes,以及共同的祖先Borg。
Kubernetes
Kubernetes[5]从新开始,为不同调度器组件提供一套干净的API。Kubernetes做了参数的自动化适应。采用专门的RESTFULL API 提供服务。Kubernetes是用Golang语言写的,它轻量、模块化、可移植还有扩展性。
总结: 参数JSON格式化、请求跨语言支持RESTFULL API,或者自定义一种描述语言。从面向机器到面向应用,调度器承担的责任由薄到厚。不过,多语言、跨平台支持能力,特别是参数和响应格式的统一是基本要求。
API完整定义了调度器的功能边界、服务规范程度、迭代升级效率、以及和周边生态系统的交互形式等。从已知的序列资源调度器来看,Http协议、JSON格式参数和响应,没有理由不遵守。
所有API的交互,建议异常信息贯穿整个链路,并且添加各个链路的标识,这样在一个生态型的资源调度体系内,进行故障排查或者调试业务过程,具有非常大的便利性。
2.资源共享看已有调度器
资源共享的过程离不开两个维度:资源粒度、时间片。资源的效率=Σ(在线资源粒度*时间片*利用率) -Σ(资源离线粒度*时间片)。资源效率包括两部分,在线部分和离线部分,离线部分主要是机器故障到恢复的过程,优化这部分资源效率,提升服务器在线率。软硬件故障通用措施有:故障预警、故障检测、故障自动修复、故障自动化处理流程等。效率简单的按照在线减去离线,只是为了描述:减少离线的浪费,有利于总体资源效率的提升。实际计算出来的数值不一定和真实现状相一致的含义。下面章节提到的资源共享,主要是在线资源部分。
不论哪种资源共享形式都没有好坏之分,只有合适与不合适服务的业务场景,并且最终有无实现资源的充分利用。往往是多种方式存在于一个大的系统里面。可能针对这个场景是固定配额,另外一个场景是动态配额,对于A业务是集群独占,对于B业务是混合部署。
语言的差异也会影响共享方式。例如 Java 语言,对内存资源就没法做到不重启而动态调配内存。C++语言可以根据进程历史内存消耗,动态地释放内存给邻居进程。而CPU、NETIO、DISKIO等,可以动态的分配资源占比。例如Borg,CPU、NETIO、DISKIO看作可压缩资源,而Memory size、Disk Size不可压缩资源。如果不可压缩资源(如Mem,disk空间)紧张,Borglet立即开始杀进程,从低优先级开始直到资源不紧张。如果可压缩资源(CPU,IO带宽)紧张,Borglet开始约束进程的资源使用,优先保障latency-sensitive的进程(如long-running service)。如果仍然紧张,Borgmaster开始迁移走一些task进程。可以看出,Borglet不是固定配额给service和jobs,而是动态统一控制共享。运行时CPU等资源调配在Borglet端可以直接执行的,而不是外界主动发起、触发BorgletAPI执行相应操作。
2.1 固定配额:悲观
固定配额,是指实例启动前和运行期间,实例占用的资源规格保持不变。或者物理机或者集群在混部过程,对某一类型的任务分配固定的资源占比。例如,单实例2个CPU逻辑核、4G Memory 空间、20G Disk 空间,磁盘IOPS、网络IOPS 最大100MB/s 等。例如物理资源层面,整个资源70%给在线服务,30%给离线服务。在线部分分配多个实例或者离线部分启动多少JOB,资源总和不超过各自的比例上限。通常固定配额主要使用场景是在线Service。在线Service类型任务往往是long time running, 服务响应时间优先。在线服务即使需要资源压缩,往往也是实例数量层面,也就是容量水位层面进行控制,几乎不会执行动态的实例规格调整。不过也有例外,如果通过一段时间的数据收集处理,发现实例规格缩小或者放大,资源利用率更高或者响应时间更好,那么,会执行新的规格升级。
2.2 动态配额:乐观
动态配额,是指实例运行期间,CPU或Memory或NETIO等根据实时运行需求,进行动态的调配,只要所在物理机资源够用。动态配额模型,一旦支持动态的增加,也就意味着支持动态的减少,也就是一旦资源不够用的时候,高优先级任务继续运行,低优先级任务逼迫释放资源,甚至Kill进程或者服务,进行硬降级。或者停止服务的某些子功能,释放部分资源,进行软降级。不难发现,动态配额往往是混部场景,并且被Kill的也是离线的JOBs。这带来另外一个问题,离线JOBs管理模块,能够及时知晓JOBs的全局状态,并及时重新在新的位置启动Job,确保任务的总体Job数量和计算能力。
前面提到,可压缩资源可以做到平滑伸缩,不可压缩资源往往需要实例重启。对于C、C++ 伸缩更方便,伸缩时间片可以更小,而对于Java,成本相对较高,需要重新启动JVM,伸缩时间片更大。
更大粒度的动态化,例如对在线service所在的实例集群,进行批量下线,批量释放整机资源交给离线或者其他服务系统。时间片到了,离线任务被迁走,在线服务实例启动。这种方式隔离比较彻底,在线和离线之间几乎没有影响。特别是在线、离线底层基础环境不统一的时候,可以做到升级解耦。而对于基础环境统一的系统,也可以方便在线、离线各自对物理机层面的参数调整、充分挖掘物理机资源效率。
在一个大的资源体系内,可能A集群是更大粒度的动态化,B集群是小粒度的动态化。依赖周边工具系统非常成熟,才能做到快速在线、离线环境隔离、环境上下文切换。并且调度系统能够瞬时感知并支持集群容量变化。很好的实施大粒度变化,更依赖周边系统工具。
2.3 分时租约共享
时间片的选择,不是孤立的,往往和一定的资源共享粒度紧密相关。分时租约,在Mesos里面就是邀约方式,时间片到了,资源就强制释放。租约的优势在于,时间片的长度已知。对于离线任务,吞吐量优先的场景,那么可以充分利用Jobs的运行时间,合理调配,充分进行资源的并发调度,提升吞吐量,包括错开时间片内的峰值消耗。类似于流水线作业,让CPU、IO、DISK合理发挥作用。
2.4 分时随机共享
分时随机共享,可以看作分时租约的一般化场景。随机对资源粒度、时间片、上下文切换的能力要求更高。从Borg论文看,分时随机共享,更多的是离线任务共享在线服务所在资源,资源一旦不够用的时候,离线任务将被Kill。而在线任务压力较低时候,IO等资源可以向离线任务倾斜而不影响在线服务的前提下。C++这种语言实现的任务特别适合,对JVM这种,只能在CPU层面实现随机调整。
不论时间片的大小、时机的选择,都需要一个强大的容器技术来实现资源的快速隔离、敏感的资源监控系统,进行资源消耗的追踪、预测、调配。更上一层任务管理系统,能够感知任务的存活和进度,并进行任务层面的调度。
2.5 资源预留
资源预留,可以减少任务被Kill掉、被迁移的次数。在资源紧张的情况下,可以快速从预留的资源池,快速的影响资源请求。从弹性效率看,对于批量的、针对在线服务的容量水位控制,加速一次批量的成功率,特别是大资源坑位的快速交付,资源预留也是非常好的措施。从容灾的角度,不同机房考虑其他机房整体不用的时候,承担其他机房迁移过来的流量,相应的资源预留也有必要的。
资源预留的客观性需求,必然牺牲一部分资源的利用率。恰当的预留规模就显得非常必要了。至于预留多少,没有绝对的指标。不同于银行存款准备金率,该数值直接影响资金的流动。资源预留更多的是效率、应急响应所需。
3.任务类型看已有调度器
资源调度器服务的任务类型,主要分为Jobs、Services。Jobs的特点:短周期,也有长的运行1天甚至1个礼拜的,大部分运行周期是分钟级别;批量提交、运行;吞吐量优先;CPU、IO密集型;优先级相对低些;失败后可以重新分配;函数式的过程,也就是多次运行结果,只要输入不变,结果也一致的。Service的特点:长周期,也有运行1天甚至1个礼拜的;活动营销型服务;大部分运行周期是季度或者年的,提交后就一直运行;服务响应时间敏感;CPU、IO密集型都有;优先级特别高。有些基础类型或者管控系统,有时候也作为service任务看待,这些系统不允许被抢占。例如,基础存储系统、监控运维系统、权限风控系统等,这些没有直接服务外面客户,但对业务稳定性、可用性至关重要。做到任务资源不抢占,也就是固定配额模式,带来好处:业务之间彼此的影响相对比较小。不好地方:资源分配不合理或者突发需求更多资源的时候,资源浪费或者资源吃紧。在一个大的资源调度管理生态系统中(周边依赖非常多的工具、平台,而不是仅仅一个调度器就搞定),抢占必然发生的,抢占的对象、范围、频率、时机,在不同的场景下,以不同策略应对。
3.1 分配时抢占
分配时抢占,例如在不同优先级别任务共同部署在一个集群的时候,当出现更高优先级任务实例需要资源时候,空闲资源又不足以应付,此时,低优先级任务实例将被Kill,释放资源。或者直接叠加到低优先级任务所在资源位置上。分配时抢占往往是约定的规则下执行的。为了最小化应用之间的影响,抢占尽量不集中在一个点或者一个应用或者一个业务层面,风险分散式折中。任务能被Kill,默认要求被kill应用是无状态的,这样资源够用的时候,可以自动恢复。另外抢占之后,即使从资源配额角度看,实例资源的诉求都满足,从业务稳定性、综合负载均衡看,热点尽量避开。在高负荷运作的集群,添加资源或者释放资源都需要综合评估。
3.2运行时抢占
运行时抢占,多半牺牲离线JOBs,如果离线JOBs没有,那么偶尔会牺牲在线低优先级Service。运行时抢占,对容器技术要求比较高,需要快速资源释放、重新分配。在计算密集型场景下,CPU动态调配确实带来非常好的效果。如果整个宿主机资源已经吃紧,再怎么调配CPU,也不能缓解压力。在线Service内存、磁盘空间大小往往不是瓶颈,磁盘IO、网络带宽的使用,可以进行软降级。
对于被系统中断等使用的CPU核,尽量不要使用这些计算资源服务应用。毕竟和系统中断抢资源,非常不明智的。
基于Linux cgroup 实现的CPU共享:CPU子系统和CPU set两种方式,针对运行时的抢占效果的好坏,需要通过真实场景观察确定。因为业务特征对效果有一定影响。业务对时间的敏感性,磁盘IO、网络IO的队列技术,就需要慎重使用。
4.资源利用率和预测运用
资源利用率在第2部分已经提到,与资源粒度、时间片、利用率、服务器在线率等都有关联。这些抽象层面背后,还有那些方面需要仔细实施,以确保最终的效率、利用率的提升。下面列举部分信息如下。
4.1 负载预测
负载预测,预测的实时性、准确性,应用实例规格的优化、运行时动态资源的分配、全局热点把握,都是至关重要的前置技术。
负载数据主要包括CPU利用率、Memory消耗、Disk消耗,磁盘IO、网络IO,甚至DB IO等。从这些历史数据中,多维度对应用、应用实例层面分别给出面向不同时间片大小的预测值,其实是非常具有挑战的事情。数据规模、采集的并发实时性,噪声和突发流量甚至限流等,都对模型的响应时间、模型的准确率提出了很高的要求。因为错误的预测可能导致意想不到的调度影响。
负载预测和业务QPS、RT关联起来,甚至和能源消耗、成本关联起来,除了趋势评估,还可以帮助决策。由此对数据的协同分析,也需要专业的团队进行跟进。[12,13,14,15,16,17]
4.2 迁移最少
在资源调度系统甚至任何系统中,都会存在例外,存在系统规则或者模型无法应对或者之前没有预估到的案例。迁移最少,大型资源池调度过程中,也是需要考量并优化的点。迁移成本,包括迁移的次数、迁移的规模、迁移的影响。
物理机故障不可避免,按照万分之三的概率计算,一万台服务器,每天大约3台服务器触发硬件故障,这些硬件故障上面的实例要么直接不工作,要么从新创建。无状态的,直接扩容,有状态的涉及到数据搬迁。
集群碎片整理或者负载整理,都需要对实例进行上线、下线操作。迁移的过程,其实就是服务资源“暂停”服务的过程。迁移次数、规模不得不考虑。
有时候就是纯粹的资源替换,因为网络或者机型或者业务需要,做到迁移最少,在资源预算或者业务规划时候必须考量。看起来不是资源调度器的责任,但是,初期需要资源调度器的建议,从而降低二次梳理成本。
对于依赖性的JOBs,在业务开始时候,就应该考虑依赖关系。典型的数据搬迁、服务调用,做到同一机架或者交换机都带来性能提升。一种迁移最少的方案参考论文[10]。
4.3 等待最短
在微观层面,资源调度器资源调度,特别是大规模Jobs调度,排队以及排队开销客观存在。排队的长度和公平性,有时候很矛盾的。降低排队时间,一方面提升业务体验,另外一方面资源分配效率更高,资源在线工作时间片更多,资源利用率也就更好。
各种应对等待的队列算法,例如轮询、带权值、优先级,都有各自的优缺点。具体场景需要具体选择[8,9]。
4.4 碎片最少
碎片最少是默认的,实际选择执行的路径有所不同。空闲优先,也就是铺开优先。另外一种是饱和优先,也就是紧凑优先。在相同资源、相同碎片的时候,是优先向空闲结点部署,还是将已有结点打饱和,没有绝对的标准。方便大规格资源的申请,那么打饱和比较妥当,这样相同碎片量的情况下,大块资源比较多。
在计算碎片的时候,需要综合评估CPU、Memory、Disk等维度,通常CPU是核心竞争资源,优先评估CPU的碎片。确保CPU关键资源的充分利用,CPU资源在容器或者实例层面,很容易动态调整而不需要重新实例化等。一些碎片最少的算法参考论文[11]。
如果实际分配过程中,确实存在碎片无法分配出一个资源位,那么可以将余下的CPU核绑定到已知实例上。虽然CPU资源利用起来了,如果上层流量均衡调度,那么,这种相对其他实例多出的CPU资源,可以提升响应时间,但是并没有提升QPS,只对稳定性有帮助。
4.5 资损最少
VM代价计算模型当中,除了资源粒度、时间片等因素外,还需要考虑资损,尤其是电商交易类在线服务。服务器状态异常或者故障,有时候会有造成用户或者商家或者企业的财务损失。尽管业务架构层面会极大程度规避这种情况的出现,实际过程中,如果把资损最少融入常规调度策略中,那么,一旦发生局部集群的大面积故障,资损理论上就降到最低。在已知的资源调度器中,代价更多的集中在资源本身,也就是IAAS层考量,而把业务层的需求,例如,资损最少交给PAAS或者SAAS层解决。从最初的小型机、商用数据库、专有集群等,到分布式普通机器,自研发系统,不同阶段的技术形态和投入是不一样的。整个链路层面,层层把控资损,其实最后落到资源调度器层面的影响相对较少。
另外一个角度就是业务性价比,总是期望将业务收益最大、故障影响最敏感的系统,独立部署,资源优先保障。例如广告系统。
4.6 快速恢复
在有限资源的系统里面,或者高负载运作系统里面,局部故障的影响会被放大。在大规模的资源系统里面,每个应用的实例规模比较大,重启或者上下线实例,几乎没有丝毫影响。失败的流量占比几乎可以忽略,失败的请求重新分配到其他结点,对其他结点的压力增长也是微小的。但是,几乎每个结点压力都达到阈值90%左右的话,那么,即使是很少量的结点故障,影响也会放大。例如,秒杀或者抢购商品,实例的稳定性要求非常高。很难做到机器100%无故障,除了业务容量冗余之外,故障快速恢复可以减轻故障影响。
和资损类似,故障快速恢复落到资源调度器层面的责任或者压力,其实非常微弱,甚至可以忽略,除非是特殊的业务。针对故障物理机承载的实例重启速度的分布,进行有效的控制,可以从微观层面,提升故障的快速恢复能力。
5.阿里电商调度Zeus实践
在第一部分的架构、数据、API分析总结里面,已经把阿里的一些实践经验概要描述了一下。本部分从整体上对Zeus进行概要总结。
5.1 上下游架构
阿里电商业务的复杂程度,很难用一个图或一句话描述清楚。从资源调度的层面看,阿里的在线服务资源调度系统Zeus依赖或者配合的系统,多达十几个。每一个被依赖的系统,除了服务资源调度器之外,还服务其他场景。下面以Zeus实际运作过程中关联或者依赖的视角,给出整体抽象架构示意图,如图3所示。
图3阿里在线资源调度架构图
Zeus向下,依托阿里自有IAAS服务,例如核心的容器技术,运维监控的底层通道系统。对上,衔接运维发布系统、监控视图、环境巡检、打标系统等等。Zeus提供资源调度过程和结果的可视化数据视图。对接成本容量管控,在资源申请、回收、成本核算等整个资源生命周期,提供相关数据服务。
通过模拟演练,配合流量压测、追踪调度系统,提前发现不合理部署并自动调配。做到大促高峰流量场景下,业务的高可用,低成本开销。
5.2 调度策略
基于预算的统筹安排,这意味着资源存在某种程度的“边界”:就是“预算”。超出预算就变得很被动。为了提升资源利用率,负载均衡,需要跨资源边界的共享,以共赢合作方式来推动。而Google Borg的竞拍模式,从一开始资源是面向所有组织业务、相对公平的。两种模式选择都不是凭空的,都是伴随企业自身技术发展、贴合各自实际业务特征产生的。没有优劣,只有合适与否。
Zesu支持在线、离线混合部署。一种,在离线任务固定配额,在单机或者集群层面固定配额,此时,在离线之间的资源争抢是可以预知的,或者说资源的边界不打破,理论上就不存在资源的干扰。这种模式,有实践过。另外一种,在线离线任务的运行时资源抢占,当在线任务资源紧张,单节点离线任务就需要释放CPU或者磁盘IO或者网络带宽资源。
抢占发生的时刻,除了初始分配、也包括运行时时刻。例如,在线和离线之间抢占,甚至包括在线任务之间的资源抢占。
另外一种抢占,或者说资源倾斜,或者说业务管理需求吧。在线任务又细分中间件基础服务、运维监控基础服务、安全风险控制等业务模块,这些重要的业务资源优先保障,不被抢占。
对待碎片,总体上碎片最少。候选资源结点排序上,铺开优先和紧凑优先都有。看具体资源池和对应业务的需求而定。用于特殊场景下,甚至存在运行时动态确定资源的策略,例如秒级别响应资源服务需求。
故障预警、故障检测、环境巡检、打标、提升资源在线率、流程数据一致性等,也有相应的策略。例如:基于Golang实现的队列,支持配置的批量更新、采集等。基于Golang 协程和Map,实现多级并发的机器选择和计算得分排序等。
5.3 利用率和预测
资源利用率相对阿里过去有不少提升,每年节约成本亿为单位。相对业界,特定的资源池利用率达到甚至超过业界水平,总体打平的利用率,与业界还有一些差距。这些差距和业务场景、内部依赖配合的系统工具的成熟度、发展计划都有关联。
预测目标是某种程度把整个系统的流转过程,数据化、模型化、自动化。预测的能力某种程度决定了资源调度系统最终能达到的理想状态。在阿里内部,针对在线或者离线任务的负载预测、容量水位预测、全链路模型等,都有相关的团队在负责,并经历了几届双11的考验,越来越稳定、高效、准确。具体预测模型、算法上面,延续着业界已公开的论文,并结合阿里业务场景,做适合业务发展需要裁剪实践。
5.4 云端调度
随着云计算的发展,电商混合云部署架构的成熟。几乎所有企业未来都面临云端调度的问题。在云端的资源调度、混合云调度,对系统的协同能力、快速上下线能力提出了更高的要求。2015年双11,充分利用了 阿里云 的公共云计算资源来分担一部分流量,阿里、淘宝、支付宝在今年双11做到了这一点,并且扛住了严酷的流量考验。实现了交易上云的关键技术的突破。未来,在云端的交易更加普遍,云端资源调度的技术、经验更加丰富。在技术、经验完善后,电商会分享给业界,让大家享受云带来的低成本、便捷、高效。
附:参考文献
[1]
[2] Large-scale cluster management at Google with Borg
[3] Mesos: A Platform for Fine-Grained Resource Sharing in the Data Center
~alig/papers/mesos.pdf
Scheduler Http.
Executor Http.
Internal C++ API.
Kubernetes on Mesos
[4] Omega: flexible, scalable schedulers for large compute clusters
[5]Kubernetes docs
[6]
[7]
[8] A short introduction to queueing theory
[9]资源调度等待开销感知的虚拟机整合
[10] Nilabja Roy,Abhishek Dubey and Aniruddha Gokhale. Efficient Autoscalling in the Cloud using Predictive Models for Workload Forecasting 2011 IEEE 4th International on Cloud Computing.
[11] Fei MA,Feng LIU,Zhen LIU.Mulit-objective Optimization for Initial Virtual Machine Placement in Cloud Data Center.Journal of Information & Computatioal Science 9:16 2012
[12] Maria Couceiro,Paolo Romano etc. A Machine Learning Approach to Preformance Perdiction of Total Order Broadcast Protocols. SASO10-2008
[13]Xiaoqiao Meng,Canturk Isci etc. Efficient Resource Provisioning in Compute Clouds via VM Mulitplexing. ICAC 10, June 7-11, 2010
[14]Dapeng Dong and John Herert. Energy Efficient VM Placement Supported by Data Analytic Service. 2013
[15]Berkin Ozisikyilmaz, Machine learning models to predict performance of computer system design alternatives. 37th International Conference on Parallel Processiong 2008
[16] Performance prediction and optimization using Linux cgroup with IO throttle. LinxuCon Europe 2012
[17]Archana Ganapathi etc. Statics-Driven Workload Modeling for the Cloud