面向容器的资源调度技术对比 - 阿里技术
摘要:本文以资源分配理念,拍卖、预算、抢占出发,引出Borg、Omega、Mesos、Kubernetes架构、数据、API的特点比较。然后梳理资源共享各种不同共享形式的内容,接着对比任务类型,最后回到资源利用率和基于数据预测角度,看相关系统是如何运用和实现各自场景目标。最后给出阿里巴巴电商在线服务资源调度器Zeus关键技术内容。
进入这个领域的门槛不在具体某个技术,而业务场景和技术选型的映射匹配,特别是周边系统的完善程度,决定了如何选择方案、如何制定落地计划。本文不是为了全面分析某个调度器,也不是全面对比某个关键点在不同调度器之间特色,而是基于笔者的理解,阐述在一个新场景下,如何设计或者完善一个资源调度器,从已有调度器系统吸取架构或模块经验,最低成本实现贴合自身业务场景的资源调度器。例如吸取调度器二层架构模式、数据集中管理方式、统一RestFull API、资源分时共享策略、在离线任务类型抽象等。
1 从资源分配理念来看已有调度器
在资源调度器中,资源分配理念:拍卖、预算或抢占,往往是混合运用。资源分配理念,折射出了资源调度器所在的生态系统或者说周边配合系统的成熟度、运行习惯。例如,Google从最早的广告拍卖机制起,拍卖的理念在Google内部就形成了一种经验,那么资源竞拍被分配出来的结果,大家很容易达成一致。而国内企业,往往是预算驱动,更趋向预算、采购,谁预算谁使用。这种环境下,资源被谁使用基本可以预见,成本也是比较容易找到归属者。在拍卖机制下资源抢占,初始分配是不大会发生,只有在运行时发生资源不够用的时候出现,低优先级的任务被Kill。在预算机制下,资源分配初期、运行时过程中,都会发生抢占。拍卖的另外一种好处是便于资源流动起来,不仅是资源利用率提升,更是资源投入产出比的最大化。而预算往往是一次性的,重点业务资源优先保障,使得适应性、灵活性、激励业务效率提升变得不如拍卖。
不同策略落地在架构、数据、API层面有着非常多的共同之处。从中不难发现Borg是始祖,后来的Mesos、Omega、Kubernetes、Zeus等都延续着Borg的某些重要特征,而又随技术发展,引入新的特征。针对每个系统的具体分析,可以参照各系统发表过的论文及官方文档[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,其他的调度、admission管理都是作为服务,以client访问API server,对外提供丰富的生态工具,例如脚本、web管理页面、控制台命令等。通过Http 协议实现的序列API,执行容器到资源分配管理的几乎全部操作。支持以标签形式动态调整应用的属性,从而影响Jobs调度策略。
Mesos
Mesos API[3]包括SchedulerHttp、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格式化、请求跨语言支持RESTFULLAPI,或者自定义一种描述语言。从面向机器到面向应用,调度器承担的责任由薄到厚。不过,多语言、跨平台支持能力,特别是参数和响应格式的统一是基本要求。
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核,尽量不要使用这些计算资源服务应用。毕竟和系统中断抢资源,非常不明智的。
基于Linuxcgroup 实现的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]http://www.umbrant.com/blog/2015/mesos_omega_borg_survey.html
http://www.infoq.com/cn/articles/comparison-of-mesos-omega-and-borg
[2] Large-scalecluster management at Google with Borg http://research.google.com/pubs/pub43438.html
[3] Mesos: A Platform for Fine-GrainedResource Sharing in the Data Center
https://www.cs.berkeley.edu/~alig/papers/mesos.pdf
Scheduler Http. http://mesos.apache.org/documentation/latest/scheduler-http-api/
Executor Http. http://mesos.apache.org/documentation/latest/executor-http-api/
Internal C++ API. http://mesos.apache.org/documentation/latest/doxygen-style-guide/
Kubernetes on Mesos https://github.com/mesosphere/kubernetes-mesos
[4] Omega: flexible, scalable schedulersfor large compute clusters
http://research.google.com/pubs/pub41684.html
[5]Kubernetes docs
https://github.com/kubernetes/kubernetes/tree/master/docs
http://kubernetes.io/docs/user-guide/
[6]http://www.infoq.com/cn/articles/Kubernetes-system-architecture-introduction
[7]http://www.wired.com/2013/03/google-borg-twitter-mesos/
http://www.cngulu.com/2870.html
[8] A short introduction to queueing theory
[9]资源调度等待开销感知的虚拟机整合
[10] NilabjaRoy,Abhishek Dubey and Aniruddha Gokhale. Efficient Autoscalling in the Cloudusing Predictive Models for Workload Forecasting 2011 IEEE 4thInternational on Cloud Computing.
[11] Fei MA,Feng LIU,Zhen LIU.Mulit-objectiveOptimization for Initial Virtual Machine Placement in Cloud Data Center.Journalof Information & Computatioal Science 9:16 2012
[12] Maria Couceiro,Paolo Romano etc. AMachine 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. EnergyEfficient VM Placement Supported by Data Analytic Service. 2013
[15]Berkin Ozisikyilmaz, Machine learningmodels to predict performance of computer system design alternatives. 37thInternational Conference on Parallel Processiong 2008
[16] Performance prediction and optimizationusing Linux cgroup with IO throttle. LinxuCon Europe 2012
[17]Archana Ganapathi etc. Statics-DrivenWorkload Modeling for the Cloud