时间:2021-07-01 10:21:17 帮助过:60人阅读
作者: Dong | 新浪微博: 西成懂 | 可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明 网址:http://dongxicheng.org/mapreduce-nextgen/hadoop-jira-yarn-45/ 本博客的文章集合:http://dongxicheng.org/recommend/ 重大消息:我的Hadoop新
作者:Dong | 新浪微博:西成懂 | 可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明
网址:http://dongxicheng.org/mapreduce-nextgen/hadoop-jira-yarn-45/
本博客的文章集合:http://dongxicheng.org/recommend/
Hadoop jira链接:https://issues.apache.org/jira/browse/YARN-45
所属范围(新特性、改进、优化或Bug):改进
修复版本:2.1.0-beta及以上版本
所属分支(Common、HDFS、YARN或MapReduce):YARN
涉及模块:resourcemanager
英文标题:“Scheduler feedback to AM to release containers”
背景介绍
在2.1.0-beta之前,ResourceManager本身没有提供直接的资源抢占RPC接口,也就是说,从语义上讲,YARN是不支持资源抢占的。然而,Hadoop最著名的调度器(参考我的这篇文章:Hadoop调度器总结)之一Fair Scheduler(参考我的这篇文章:Hadoop 0.21.0中公平调度器实现)最大特色之一是支持资源抢占,它当然不想抛弃这个功能变得跟Capacity Scheduler(参考我的这篇文章:Hadoop容量调度器介绍)一样平庸,由于它就拐弯抹角的实现了资源抢占,它是怎么实现的呢,方法很简单也很粗鲁:当需要为某个“更重要”的应用程序分配资源而资源不够用时,需要抢占别的应用程序占用的资源来“拆东墙补西墙”,采用的策略非常野蛮,在事先不告诉应用程序主管(指ApplicationMaster)的情况下,强制杀死它的弟兄(任务),很显然,各个应用程序主管会非常的不满,这也有损YARN资源管理的形象,随着Hadoop生态系统的完善,当然不希望这种不和谐的场面出现,于是更友好地资源抢占策略提上了日程。
在正式介绍YARN资源抢占策略之前,我先介绍一下为什么需要有资源抢占策略,这种策略用在哪些场景下?我们都知道,YARN作为一个资源管理系统,最重要的工作是管理集群中的所有资源,并按照应用程序各种资源要求将满足要求的资源分配给他们,比如有些应用程序优先级高,更重要,有资源要先给它;有些应用程序需要跑一个服务(Service),想要质量高一点的资源;有些应用程序跑的任务是一个“团伙”,需要资源全部到位后才会一起运行等,YARN作为一个“服务商”,要尽量满足各种形形色色的客户要求,而为了提供更优质的服务,让客户整体满意度更高,抢占机制是必须的。总结起来,抢占机制通常用于以下几种场景:
(1)重分布各应用程序的资源量和公平资源量。比如,当集群资源动荡时,调度器需要时不时的调整各个队列资源分布情况,以保证尽可能公平公正地分配资源。
(2)杀死特定的container。这种场景也很多,比如杀死一个正在运行的任务将其迁移到另外一个更优质的节点(比如locality更高,CPU性能更好等)上运行,杀死一个运行在存在IO瓶颈节点上的任务(比如Shuffle热点节点),并将其迁移到一个IO环境良好的节点上运行(注意,YARN 只对CPU和内存资源进行了隔离,其他资源比如网络和磁盘IO没有隔离,仍可能产生瓶颈哦,这个短时间内搞不定,需要看cgroup的进展)。
(3)管理员对集群中个别节点进行维护。为了对一批机器进行维护,通常先要“友好的”杀死这些节点上的任务,以让他们进行一些“善后”处理工作,比如对一些service任务,可以做一些checkpoint以便下次恢复运行现场。
讲到这里,我需要再提醒一下各位读者,YARN的定位是一个通用的资源管理系统,类似于一个云操作系统,可以管理一个集群或者数据中心中的各种资源,它不仅仅用来跑MapReduce这样的应用,可也以跑MPI、Storm、Spark这样的计算框架,当然,更可以跑Service,比如一个mysql实例、一个Web Server等,只不过是,由于YARN处于发展初级阶段,很多地方尚不完善。
解决方案
为了更友好的支持资源抢占,YARN提出了新方案,具体如下:当需要抢占某个应用程序的资源时, ResourceManager先将待抢占的资源发送给应用程序的ApplicationMaster,让它自行了断对应的任务,比如做一些checkpoint以帮助下次运行时恢复现场等(然后再杀死对应的任务),如果在一定时间内,ApplicationMaster“无视”老大(即ResourceManager)的命令,则ResourceManager再进一步强制干掉这些任务。需要注意的是,集群的资源量变化是动态的,不同时刻,总的资源量,正在使用的资源量等信息是变化的,ResourceManager要求ApplicationMaster强制释放的资源可能在下一刻已经自行得到了释放,这种情况下,是没必要强制杀死任务的。
对于前面提到的场景,我们可以概括为,在(1)(3)两种场景中,ResourceManager向ApplicationMaster发送一个总的资源量即可,具体杀死哪些任务凑齐这些资源,完全由ApplicationMaster自己决定,比如它可以选择一些刚刚启动的任务(这样代价最小);第(2)中场景中,ResourceManager必须显式指明要杀死的Container列表,ApplicationMaster收到该列表后,严格执行命令依次杀死这些Container中运行的任务。
读者可能已经注意到,这个Hadoop jira链接很长,几个主要人物进行了反复的技术讨论,线上讨论,线下讨论……,方案也是在不同变化,一会变成“ResourceManager只发送总的资源量,以便将更多的权利下放给ApplicationMaster”,一会变成“ResourceManager发送需释放的Container列表,以彰显ResourceManager绝对的控制权力”,最终,当YARN项目的老大Arun C Murthy假期归来之后,一拍版定为最初的方案,也就是兼顾三种场景的方案,具体如下:
在心跳信息,即ResourceManager应答给ApplicationMaster的信息AllocateResponse中(即RPC函数AMRMProtocol#allocate()的返回值,注意从2.1.0-beta开始,AMRMProtocol协议被改名为ApplicationMasterProtocol)增加PreemptionMessage消息,对应ProtocolBuffers的定义如下:
message PreemptionMessageProto {
optional StrictPreemptionContractProto strictContract = 1;
optional PreemptionContractProto contract = 2;
}
message StrictPreemptionContractProto {
repeated PreemptionContainerProto container = 1;
}
message PreemptionContractProto {
repeated PreemptionResourceRequestProto resource = 1;
repeated PreemptionContainerProto container = 2;
}
message PreemptionContainerProto {
optional ContainerIdProto id = 1;
}
message PreemptionResourceRequestProto {
optional ResourceRequestProto resource = 1;
}
在PreemptionMessageProto定义中,StrictPreemptionContractProto是必须释放的container列表(不可忽略,若忽略,ResourceManager强制干掉这些container),PreemptionContractProto则给出资源总量和建议释放的container列表, ApplicationMaster可自己选择释放哪些container以凑集总资源量,这样给ApplicationMaster留下了发挥空间,可做的更加智能些。当然,ApplicationMaster收到这些信息后,可自行决定是否杀死对应的container,它可以选择忽略,由ResourceManager强制杀死它们,需要注意的是,集群资源状态时动态变化的,ApplicationMaster使用的资源在不断的释放中,ResourceManager此刻要求释放的container,下一刻可能就不要求了。
在这个jira链接中,ResouceManager和ApplicationMaster之间的协议进行了修改,这就要求各个调度器均要充分利用这个修改增加更加先进的抢占机制,同时已有的ApplicationMaster也要修改对应代码以便能够理解这种消息的语义,接下来各个模块的负责人都有活干了,这也进一步说明了,通信架构最好不要动,一旦动了,就会产生无数的工作量。由于该jira的修改产生的相关链接如下:
(1)CapacityScheduler: support for preemption (using a capacity monitor):
https://issues.apache.org/jira/browse/YARN-569
(2)RM changes to support preemption for FairScheduler and CapacityScheduler:
https://issues.apache.org/jira/browse/YARN-567
(3)FairScheduler: support for work-preserving preemption:
https://issues.apache.org/jira/browse/YARN-568
(4)User guide for preemption:
https://issues.apache.org/jira/browse/YARN-650
(5)Basic AM changes to support preemption requests (per YARN-45):
https://issues.apache.org/jira/browse/MAPREDUCE-5189
当然,在YARN发展初期,这种改动是正常的,毕竟YARN这种系统本身就是从无数应用中抽象出来的,他总伴随应用种类的增加而不断的发展与前进。
我们学到了什么
涉及到系统底层通信语义的修改,一定要反复磋商,对于YARN而言,一定要清楚各个组件的定位和职责,不可赋予一个组件它不应该具备的职责,这样下去,所有组件的职责会变得过于交叉错乱,失去了架构的简洁性。
原创文章,转载请注明: 转载自董的博客
本文链接地址: http://dongxicheng.org/mapreduce-nextgen/hadoop-jira-yarn-45/
作者:Dong,作者介绍:http://dongxicheng.org/about/
本博客的文章集合:http://dongxicheng.org/recommend/