本文来自OPPO互联网基础技术团队,转载请注名做者。同时欢迎关注咱们的公众号:OPPO_tech,与你分享OPPO前沿互联网技术及活动。
什么是YARN?html
Apache Hadoop YARN:Yet Another Resource Negotiator,另外一种资源协调者。node
Apache Hadoop YARN 是一种新的Hadoop资源管理器。它是一个通用资源管理系统,可为上层应用提供统一的资源管理和调度,它的引入为集群在利用率、资源统一管理和数据共享等方面带来了巨大好处。也就是说YARN在Hadoop集群中充当资源管理和任务调度的框架。web
ResourceManager是YARN中的主节点服务,它负责集群中全部资源的统一管理和做业调度。算法
简单来说,ResourceManager主要完成的功能包括:apache
NodeManager是YARN集群中的每一个具体节点的资源和任务管理者。NodeManager的主要功能包括:segmentfault
用户提交的每一个应用程序均包含一个ApplicationMaster,主要功能包括:api
Container是YARN中的资源抽象,它封装了某个节点上的多个维度的资源,如CPU、内存、磁盘、网络等。当ApplicationMaster向ResourceManager申请资源时,ResourceManager为ApplicationMaster 返回的资源是用Container表示的。缓存
当用户向YARN中提交一个应用程序后,YARN将分两个阶段运行该应用程序:安全
第一阶段:启动ApplicationMaster;性能优化
第二阶段:由ApplicationMaster建立应用程序;为它申请资源,并监控它的整个运行过程,直到运行完成。
以下图所示,以一个mapreduce程序提交到YARN的过程进行分析。
第1步:
client 读取做业配置信息并建立Job的环境,调用job.waitForCompletion 方法,向集群提交一个MapReduce 做业 。
第2步:
资源管理器给任务分配一个新的做业ID 。
第3步:
做业的client核实做业的输出路径,计算输入文件的分片,将做业的资源 (包括:Jar包、配置文件,split信息等) 拷贝到HDFS集群上的做业提交目录。
第4步:
经过调用资源管理器的submitApplication()来提交做业。
第5步:
当资源管理器收到submitApplciation()的请求时,就将该请求发给调度器 (scheduler),调度器向NodeManager发送一个启动container的请求。
第6步:
节点管理器NodeManager启动container,内部运行着一个主类为 MRAppMaster的Java应用。其经过创造一些对象来监控做业的进度,获得各个task的进度和完成报告 。
第7步:
而后其经过分布式文件系统HDFS来获取由客户端提早计算好的输入split,而后为每一个输入split建立一个map任务,根据mapreduce.job.reduces建立 reduce任务对象。
若是做业很小,为了下降延迟,可采用Uber模式。在该模式下,全部的Map Task和Reduce Task都在ApplicationMaster所在的Container中运行。
第8步:
若是不是小做业,那应用管理器向资源管理器请求container来运行全部的map和reduce任务 。
这些请求是经过心跳来传输的,包括每一个map任务的数据位置。好比:存放输入split的主机名和机架(rack),调度器利用这些信息来调度任务,尽可能将任务分配给存储数据的节点或相同机架的节点。
第9步:
当一个任务由资源管理器的调度器分配给一个container后,AppMaster经过联系NodeManager来启动container。
第10步:
任务由一个主类为YarnChild的Java应用执行,在运行任务以前首先本地化任务须要的资源。好比:做业配置、JAR文件以及分布式缓存的全部依赖文件 。
第11步:
最后,启动并运行map或reduce任务 。
YARN中的任务将其进度和状态 (包括counter)返回给应用管理器。
客户端每秒 (经过mapreduce.client.progressmonitor.pollinterval设置) 向应用管理器请求进度更新,展现给用户。
除了向应用管理器请求做业进度外,客户端每5秒会经过调用 waitForCompletion()来检查做业是否完成,时间间隔能够经过 mapreduce.client.completion.pollinterval来设置。
做业完成以后,应用管理器和container会清理工做状态、做业的执行详情记录文件.jhist会被转移到历史服务器目录、container的执行日志会被nodemanager上传到HDFS集群供用户长期查询。
如图所示,ResouceManager主要包括如下几个部分组成:
ResouceManager分别针对普通用户、管理员和Web提供了三种对外服务。具体实现分别对应:
ClientRMService:处理普通用户的提交程序、终止程序、获取程序状态等请求
AdminService:处理管理员的刷新队列、更新ACL权限等请求
RMWebApp:展现集群资源使用状况和应用程序执行状态等信息的web页面
该模块主要包括几个组件:
NMLivelinessMonitor:监控nodemanager的存活状态,若是nodemanager超时未汇报心跳信息,则将从集群中剔除该节点
NodesListManager:维护正常节点和异常节点列表,相似于集群的黑名单和白名单节点
ResourceTrackerService:处理来自NodeManager的请求,主要包括注册和心跳请求
ResouceManager自带了很是全面的权限管理机制,主要由如下三个模块构成:
RMDelegationTokenSecretManager;
DelegationTokenRenewer;
ClientToAMSecretManager。
该模块主要包括几个组件:
ApplicationACLSManager :管理应用程序的查看和修改权限
RMAppManager:管理应用程序的启动和关闭
ContainerAllocationExpirer:监控AM是否在规定的时间内将得到的container在NodeManager上启动
该模块主要的组件包括:
AMLivelinessMonitor:监控AM是否存活
ApplicationMasterLauncher:与nodemanager通讯以启动ApplicationMaster
ApplicationMasterService:处理来自ApplicationMaster的注册和心跳两种请求
ResourceManager使用有限状态机维护有状态对象的生命周期,共维护了4类状态机,分别是:
RMApp:一个Application的运行生命周期
RMAppAttempt:一个Application运行实例的生命周期
RMContainer:一个Container的运行生命周期
RMNode:一个NodeManager的生命周期
该模块主要就是涉及资源调度一个组件,比较常见的实现是:
FairScheduler:公平调度器
CapacityScheduler:容量调度器
YARN采用了基于事件驱动的并发模型,该模型可以大大加强并发性,从而提升系统的总体性能。
在YARN中全部核心服务实际上都是一个中央异步调度器,包括:
ResourceManager
NodeManager
MRAppMaster等。
它们维护了事先注册的事件和事件处理器,并根据接收的事件类型驱动服务的运行
上面介绍的ResourceManager的各个服务和组件均是经过中央异步调度器组织在一块儿的。不一样的组件之间经过事件交互,从而实现了一个异步并行的高效系统。
为了保障公司的计算资源获得充分利用,大数据平台这边统一使用YARN进行资源管理与调度。
目前在咱们的YARN集群上主要支撑了绝大部分的离线应用(MapReduce、Hive SQL、Spark-Submit、Spark SQL)和一部分实时业务(Spark streaming、Flink)。
随着业务快速发展,为了知足业务的大量计算任务需求,咱们对YARN集群作了一些探索和实践的工做。
目前集群的机器规模由开始的几百台发展到如今的5000+台、单集群最大节点数2500+、单集群管理的Container数10w+、单集群日调度Container数近1亿。
对YARN开展的一些稳定和优化工做,主要包括四个方面:
YARN HA的实现通常是采用基于zookeeper的共享存储。YARN将共享存储系统抽象成RMStateStore,以保存恢复ResourceManager所必需的信息。但一些异常任务写zk的大小会超过znode的大小,从而会触发整个YARN服务的异常。
有一次咱们收到线上YARN集群主备频繁切换的告警,随后业务反应大量的做业处于一直处于NEW_SAVING(等待提交状态),整个系统处于不可用状态。
由于当时咱们只有一个集群,整个的影响面很是大,只能快速备份RM堆栈信息和进程日志,随后进行重启操做。重启集群后,发现集群恢复了一段时间,随后又出现了相似反复的状况,而每次出现的时间和频率都没有规律可循。
经过搜索日志错误关键字,在社区中找到相关的issue,基本能够判断是因为异常任务致使的,结合异常发生的频率能够推测出是非调度任务触发的。
随后咱们在群里公告目前发现的问题,并紧急合入社区相关patch,后面集群没有再发现一样的异常。
咱们随后查阅历史做业服务器,发现了相似的异常任务,task数量很是大,依赖的jar包很是多,RMStateStore持久化了这些jar包的引用关系,咱们在测试集群也验证了这个问题。
因此咱们要限制RM持久化RMStateStore写zk的大小,社区相关patch包括:YARN-2368 、YARN-346九、YARN-612五、YARN-5006。
mr任务申请内存和cpu超过yarn调度最大资源问题,特别是大任务的话会写大量错误诊断信息到zk上,影响整个集群其余任务的正常提交。
咱们在任务提交的时候可以快速检测并失败这类任务,并减小打印错误诊断信息。
修复跨集群的一些问题:spark任务跨集群问题&mr任务跨集群问题:
由于咱们的集群是由不少个HDFS集群组建成的一个大YARN集群,而咱们每一个小集群的defaultFS和客户端的defaultFS都是不一样的。
这样默认会形成做业的提交目录没法被appmaster彻底清除,长期运行后会致使单级目录文件数超过namenode的最大限制而致使没法提交新的任务。
YARN队列权限是解决提交任务的用户或所属组是否有队列的提交权限,而用户和组映射关系的默认的实现类是ShellBasedUnixGroupsMapping。
它是获取ResourceManager本地机器的操做系统的用户和组关系。咱们开发了权限插件,新增了自定义的用户和组映射关系实现类HeyTapGroupsMapping,对接咱们内部的权限系统的用户和组关系;
默认的状况下,YARN的8088端口未作相关认证,攻击者可经过rest api 提交任务,下载与集群网络相通的脚本执行异常攻击,不少公司都遭受过此攻击;咱们的改动是在YARN的提交任务rest 接口处添加开关支持,通常咱们的集群任务是经过授信的客户端提交,因此咱们默认关闭REST API任务的提交。
相关安全漏洞连接:Hadoop Yarn REST API未受权漏洞利用挖矿分析
https://segmentfault.com/a/11...
咱们的集群以前会有不少的大的mr任务,这部分任务会浪费集群比较多的资源,而且容易触发不少集群bug问题。
针对mr任务支持按队列配置提交队列的任务最大task数量,超过直接拒绝任务提交。这部分的实现是在MR任务的AppMaster初始化做业的JobImpl类中对做业的信息进行检查。
集群不免会有异常的时候,当异常的时候每每会出现任务大量pending和Running的状况,系统内部大量消息处理堆积。
若是咱们不作熔断处理,ResourceManager会因为事件长期堆积而超过JVM最大内存而oom崩溃。
咱们的改动是当集群总的running任务数+accept任务数超过历史安全阈值则进行拒绝提交;按子队列熔断数量限制,考虑实际实施过程当中,子队列一些任务偶尔也会由于集群内部缘由(网络问题、HDFS抖动问题)发生阻塞,因此按子队列熔断会形成一些问题,暂时不上线。
而集群级别的熔断是颇有必要的。集群的熔断实现是在RM处理客户端请求的ClientRMService组件里实现,对集群的调度器不会产生压力。
支持hadoop客户端、hiveserver、spark任务提交时,经过zk动态拉取配置文件,减小因配置文件改动的重启频率。
咱们的改动是在hadoop-common包里增长读取远程zookeeper配置中心的功能类,hadoop-hdfs包里增长功能类的引用,客户端经过配置选择模式和对比本地和远程配置更新时间,来最终拉取合适的配置。
咱们打印收集ResourceManager的堆栈信息和阅读源码,发现YARN调度算法有两个能够优化的地方。
YARN在计算两个队列的优先级时,有多个地方须要计算队列的资源使用状况。而它每次都是从新递归计算全部子队列的资源,这个操做很耗cpu资源。
咱们的修改是第一次直接计算,后面直接使用第一次的结果,减小了大约2/3的时间消耗。
YARN默认会选取全部队列和任务进行选择排序,咱们剔除了不须要资源的队列和任务的排序,大大地减小了排序的规模。
集群节点的上的IO很大一部分来源于任务启动以前的jar包下载,默认是同一个任务的jar包才能共享,这样会致使不少公共jar包的重复下载问题。
在YARN中合理使用分布式缓存并设置公共资源,能够大幅减小没必要要jar包的重复下载,减小集群IO。
YARN中涉及到的HDFS操做主要包括:
这些服务都是公共服务,一旦涉及到的HDFS集群卡了一下就会形成整个计算集群任务的堆积。所以咱们逐渐在把这些公共服务拆迁到一个独立HDFS集群减小因为业务异常大IO任务的干扰。
每一个队列按照业务进行划分,子队列都有优先级划分,便于故障恢复。资源的合理使用,大多数队列都设置了资源的最小值和最大值。即尽可能保障优先级队列能在集群高峰期拿到最小资源,且集群空闲时大多数任务能充分利用集群资源。每一个队列都限制了运行app的最大数量,避免一个队列内部过多任务争抢资源发生死锁的状况和减小过多任务运行对集群的访问压力。
经过咱们的监控告警工具能提早发现和解决不少问题;主要包括:RM主备切换及可用性监控、慢任务、堵塞的队列、异常状态APP数量监控、YARN持久化zk状态目录监控、YARN事件堆积监控等。
例如:YARN集群开启了cgroup对任务使用的cpu资源进行隔离、使用LinuxContainerExecutor限制用户对nodemanager的危险操做以及限制非法用户;
经过咱们的大任务监控平台可以定位集群中的异常大任务,能够协助业务进行任务的优化工做;
任何一个系统都不是100%的可靠,如某一个YARN集群在异常状况下没法快速诊断问题并恢复的状况下。咱们能经过内部平台的部署系统对提交任务的服务配置进行更新,并快速切换计算任务到其余正常的计算集群;