下面是Yarn的知识体系图,这篇文章会介绍所有涉及的知识点。
一、MRv1的架构和缺陷
Apache Hadoop 是一个开源软件框架,可安装在一个商用机器集群中,使机器可彼此通信并协同工作,以高度分布式的方式共同存储和处理大量数据。
在 MapReduce 框架中,作业执行受两种类型的进程控制:
一个称为 JobTracker 的主要进程,它协调在集群上运行的所有作业,分配要在 TaskTracker 上运行的 map 和 reduce 任务。
许多称为 TaskTracker 的下级进程,它们运行分配的任务并定期向 JobTracker 报告进度。
Apache Hadoop 的经典版本 (MRv1)
MapReduce1.x时存在的问题:
- 单点故障
- 节点压力大
- 不易扩展
- 只支持MapReduce作业
大型 Apache Hadoop 集群 (MRv1) 上繁忙的 JobTracker
为了解决可伸缩性问题,一个简单而又绝妙的想法应运而生:我们减少了单个 JobTracker 的职责,将部分职责委派给 TaskTracker,因为集群中有许多 TaskTracker。在新设计中,这个概念通过将 JobTracker 的双重职责(集群资源管理和任务协调)分开为两种不同类型的进程来反映。
不再拥有单个 JobTracker,一种新方法引入了一个集群管理器,它惟一的职责就是跟踪集群中的活动节点和可用资源,并将它们分配给任务。对于提交给集群的每个作业,会启动一个专用的、短暂的 JobTracker 来控制该作业中的任务的执行。有趣的是,短暂的 JobTracker 由在从属节点上运行的 TaskTracker 启动。因此,作业的生命周期的协调工作分散在集群中所有可用的机器上。得益于这种行为,更多工作可并行运行,可伸缩性得到了显著提高。
演进成为Yarn
- ResourceManager 代替集群管理器
- ApplicationMaster 代替一个专用且短暂的 JobTracker
- NodeManager 代替 TaskTracker
- 一个分布式应用程序代替一个 MapReduce 作业
二、Yarn概述
Apache Hadoop YARN (Yet Another Resource Negotiator,另一种资源协调者)是一种新的 Hadoop 资源管理器,它是一个通用资源管理系统,可为上层应用提供统一的资源管理和调度。它将资源管理和处理组件分开,它的引入为集群在利用率、资源统一管理和数据共享等方面带来了巨大好处。
- YARN是资源调度框架
- 通用的资源管理系统
- 为上层应用提供统一的资源管理和调度
三、Yarn的基础服务组件
YARN是Hadoop 2.0中的资源管理系统,它的基本设计思想是将MRv1中的JobTracker拆分成了两个独立的服务:一个全局的资源管理器ResourceManager和每个应用程序特有的ApplicationMaster。其中ResourceManager负责整个系统的资源管理和分配,而ApplicationMaster负责单个应用程序的管理。
下面是Yarn的架构图:
从上图可以看出Yarn的核心组件有:
1、Resourcemanager
RM是一个全局的资源管理器,集群只有一个,负责整个系统的资源管理和分配,包括处理客户端请求、启动/监控APP master、监控nodemanager、资源的分配与调度。它主要由两个组件构成:调度器(Scheduler)和应用程序管理器(Applications Manager,ASM)。
(1) 调度器
调度器根据容量、队列等限制条件(如每个队列分配一定的资源,最多执行一定数量的作业等),将系统中的资源分配给各个正在运行的应用程序。需要注意的是,该调度器是一个“纯调度器”,它不再从事任何与具体应用程序相关的工作,比如不负责监控或者跟踪应用的执行状态等,也不负责重新启动因应用执行失败或者硬件故障而产生的失败任务,这些均交由应用程序相关的ApplicationMaster完成。
调度器仅根据各个应用程序的资源需求进行资源分配,而资源分配单位用一个抽象概念“资源容器”(Resource Container,简称Container)表示,Container是一个动态资源分配单位,它将内存、CPU、磁盘、网络等资源封装在一起,从而限定每个任务使用的资源量。
此外,该调度器是一个可插拔的组件,用户可根据自己的需要设计新的调度器,Yarn提供了多种直接可用的调度器,比如FIFO Scheduler、Fair Scheduler和Capacity Scheduler等。
(2) 应用程序管理器
应用程序管理器负责管理整个系统中所有应用程序,包括应用程序提交、与调度器协商资源以启动ApplicationMaster、监控ApplicationMaster运行状态并在失败时重新启动它等。
2、ApplicationMaster(AM)
在用户提交一个应用程序时,一个称为 ApplicationMaster 的轻量型进程实例会启动来协调应用程序内的所有任务的执行。这包括监视任务,重新启动失败的任务,推测性地运行缓慢的任务,以及计算应用程序计数器值的总和。这些职责以前分配给所有作业的单个 JobTracker。ApplicationMaster 和属于它的应用程序的任务均在受 NodeManager 控制的资源容器(Container)中运行。
功能:
数据切分
为应用程序申请资源并进一步分配给内部任务。
任务监控与容错
负责协调来自resourcemanager的资源,并通过nodemanager监视任务的执行和资源使用情况。
有趣的是,ApplicationMaster 可在容器内运行任何类型的任务。例如,MapReduce ApplicationMaster 请求一个容器来启动 map 或 reduce 任务,而 Giraph ApplicationMaster 请求一个容器来运行 Giraph 任务。还可以实现一个自定义的 ApplicationMaster 来运行特定的任务,进而发明出一种全新的分布式应用程序框架,改变大数据世界的格局。可以查阅 Apache Twill,它旨在简化 YARN 之上的分布式应用程序的编写。
在 YARN 中,MapReduce 降级为一个分布式应用程序的一个角色(但仍是一个非常流行且有用的角色),现在称为 MRv2。MRv2 是经典 MapReduce 引擎(现在称为 MRv1)的重现,运行在 YARN 之上。
3、NodeManager(NM)
NodeManager 是 TaskTracker 的一种更加普通和高效的版本。没有固定数量的 map 和 reduce slots,NodeManager 拥有许多动态创建的资源容器(Container)。容器的大小取决于它所包含的资源量,比如内存、CPU、磁盘和网络 IO。一个节点上的容器数量,由配置参数与专用于从属后台进程和操作系统的资源以外的节点资源总量(比如总 CPU 数和总内存)共同决定。
功能:
- 单个节点上的资源管理和任务。
- 处理来自于resourcemanager的命令。
- 处理来自域ApplicationMaster的命令。
- 管理着抽象容器,这些抽象容器代表着一些特定程序使用针对每个节点的资源。
- 定时地向RM汇报本节点上的资源使用情况和各个Container的运行状态(cpu和内存等资源)
4、Container
Container是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当AM向RM申请资源时,RM为AM返回的资源便是用Container表示的。YARN会为每个任务分配一个Container,且该任务只能使用该Container中描述的资源。需要注意的是,Container不同于MRv1中的slot,它是一个动态资源划分单位,是根据应用程序的需求动态生成的。目前为止,YARN仅支持CPU和内存两种资源,且使用了轻量级资源隔离机制Cgroups进行资源隔离。
功能:
- 对task环境的抽象
- 描述一系列信息
- 任务运行资源的集合(cpu、内存、io等)
小结:
Client向ResourceManager提交的每一个应用程序都必须有一个Application Master,它经过ResourceManager分配资源后,运行于某一个Slave节点的Container中,具体做事情的Task同样也运行与某一个Slave节点的Container中。RM,NM,AM乃至普通的Container之间的通信,都是用RPC机制。
ResourceManager是Master上一个独立运行的进程,负责集群统一的资源管理、调度、分配等等;NodeManager是Slave上一个独立运行的进程,负责上报节点的状态;App Master和Container是运行在Slave上的组件,Container是yarn中分配资源的一个单位,包涵内存、CPU等等资源,yarn以Container为单位分配资源。
ResourceManager、NodeManager 和容器都不关心应用程序或任务的类型。所有特定于应用程序框架的代码都转移到它的 ApplicationMaster,以便任何分布式框架都可以受 YARN 支持 — 只要有人为它实现了相应的 ApplicationMaster。
四、Yarn的作业执行流程
当用户向YARN中提交一个应用程序后,YARN将分两个阶段运行该应用程序:第一个阶段是启动ApplicationMaster;第二个阶段是由ApplicationMaster创建应用程序,为它申请资源,并监控它的整个运行过程,直到运行完成,如下图所示。
根据上图,可将YARN的工作流程分为如下几个步骤:
- 用户向YARN中提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等;
- ResourceManager为该应用程序分配第一个Container,并与对应的NodeManager通信,要求它在这个Container中启动应用程序的ApplicationMaster;
- ApplicationMaster首先向ResourceManager注册,用户可以直接通过ResourceManager查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复图中的步骤4~7;
- ApplicationMaster采用轮询的方式通过RPC协议向ResourceMaster申请和领取资源;
- 一旦ApplicationMaster申请到资源后,便与对应的NodeManager通信,要求它启动任务;
- NodeManager为任务设置好运行环境(包括环境变量、JAR包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务;
- 各个任务通过某个RPC协议向ApplicationMaster汇报自己的状态和进度,以让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。在应用程序运行过程中,用户可以随时通过RPC向ApplicationMaster查询应用程序的当前运行状态;
- 应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己。
上述Yarn作业执行流程可以抽象、直观的表示为下面的流程图:
分配一个容器后,ApplicationMaster 会要求 NodeManager(管理分配容器的主机)使用这些资源来启动一个特定于应用程序的任务。此任务可以是在任何框架中编写的任何进程(比如一个 MapReduce 任务或一个 Giraph 任务)。NodeManager 不会监视任务;它仅监视容器中的资源使用情况,举例而言,如果一个容器消耗的内存比最初分配的更多,它会结束该容器。
ApplicationMaster 会竭尽全力协调容器,启动所有需要的任务来完成它的应用程序。它还监视应用程序及其任务的进度,在新请求的容器中重新启动失败的任务,以及向提交应用程序的客户端报告进度。应用程序完成后,ApplicationMaster 会关闭自己并释放自己的容器。
尽管 ResourceManager 不会对应用程序内的任务执行任何监视,但它会检查 ApplicationMaster 的健康状况。如果 ApplicationMaster 失败,ResourceManager 可在一个新容器中重新启动它。您可以认为 ResourceManager 负责管理 ApplicationMaster,而 ApplicationMasters 负责管理任务。
五、Yarn的资源调度模型
YARN提供了一个资源管理平台能够将集群中的资源统一进行管理。所有节点上的多维度资源都会根据申请抽象为一个个Container。
YARN采用了双层资源调度模型:
RM中的资源调度器将资源分配给各个AM:资源分配过程是异步的。资源调度器将资源分配给一个应用程序后,它不会立刻push给对应的AM,而是暂时放到一个缓冲区中,等待AM通过周期性的心跳主动来取;
AM领取到资源后再进一步分配给它内部的各个任务:不属于YARN平台的范畴,由用户自行实现。
也就是说,ResourceManager分配集群资源的时候,以抽象的Container形式分配给各应用程序,至于应用程序的子任务如何使用这些资源,由应用程序自行决定。
YARN目前采用的资源分配算法有三种。但真实的调度器实现中还对算法做了一定程度的优化。
(1)FIFO Scheduler
FIFO Scheduler把应用按照提交的顺序排成一个队列,并且是一个先进先出的队列,在进行资源分配的时候,先给队列中排在最前面的应用分配资源,待其满足资源需求后再给下一个应用分配资源,以此类推。
FIFO Scheduler是最简单也最容易的资源调度器,但它并不适用于共享集群。大的应用可能会占用较多的集群资源,这就将导致其他应用被阻塞,而且它也没有考虑应用的优先级,因而应用场景非常受限。
(2)Capacity Scheduler
Capacity Scheduler是Yahoo开发的多用户调度器,它以队列为单位划分资源,每个队列可设定一定比例的资源最低保证和使用上限,同时,每个用户也可设定一定的资源使用上限以防止资源滥用。而当一个队列的资源有剩余时,可暂时将剩余资源共享给其他队列。总的来说,Capacity Scheduler主要有以下几个特定:
容量保证。管理员可为每个队列设置资源最低保证和资源使用上限,而所有提交到该队列的应用程序共享这些资源;
灵活性。如果一个队列中的资源有剩余,可以暂时共享给那些需要资源的队列,而一旦该队列有新的应用程序提交,则其他队列释放的资源会归还给该队列;
多重租赁。支持多用户共享集群和多应用程序同时运行,为防止单个应用程序、用户或者队列独占集群中的资源,管理员可为之增加多重约束(比如单个应用程序同时运行的任务数等);
安全保证。每个队列有严格的ACL列表规定它的访问用户,每个用户可指定哪些用户允许查看自己应用程序的运行状态或者控制应用程序(比如杀死应用程序)。此外,管理员可指定队列管理员和集群系统管理员;
动态更新配置文件。管理员可根据需要动态修改各种配置参数,以实现在线集群管理。
关于Capacity Scheduler更加详细的信息,请参阅官方文档。
(3)Fair Scheduler
Fair Scheduler是Facebook开发的多用户调度器,同Capacity Scheduler类似。它以队列为单位划分资源,每个队列可设定一定比例的资源最低保证和使用上限,同时,每个用户也可设定一定的资源使用上限以防止资源滥用;当一个队列的资源有剩余时,可暂时将剩余资源共享给其他队列。当然,Fair Scheduler也存在很多与Capacity Scheduler不同之处,主要体现在以下几个方面:
资源公平共享。在每个队列中,Fair Scheduler可选择按照FIFO、Fair或DRF(即Dominant Resource Fairness算法)策略为应用程序分配资源。其中,Fair策略是一种基于最大最小公平算法实现的资源多路复用方式,默认情况下,每个队列内部采用该方式分配资源。这意味着,如果一个队列中有两个应用程序同时运行,则每个应用程序得到1/2的资源;如果有三个应用程序同时运行,则每个应用程序可得到1/3的资源;
支持资源抢占。当某个队列中有剩余资源时,调度器会将这些资源共享给其他队列,而当该队列中有新的应用程序提交时,调度器要为它回收资源。为了尽可能降低不必要的计算浪费,调度器采用了先等待再强制回收的策略,即如果等待一段时间后尚有未归还的资源,则会进行资源抢战;从那些超额使用资源的队列中杀死一部分任务,进而释放资源;
负载均衡。Fair Scheduler提供了一个机遇任务数目的负载均衡机制,该机制尽可能将系统中的任务均匀分配到各个节点上。此外,用户也可以根据自己的需要设计负载均衡机制;
调度策略配置灵活。Fair Scheduler允许管理员为每个队列单独设置调度策略(当前支持FIFO、Fair或DRF三种);
提供小应用程序响应时间。由于采用哦了最大最小公平算法,小作业可以快速获取资源并运行完成。
关于Fair Scheduler更加详细的信息,请参阅官方文档。
想要详细了解调度器,可以参见资料:Yarn 调度器Scheduler详解
六、Yarn的资源管理与配置参数
Yarn的内存管理:
yarn允许用户配置每个节点上可用的物理内存资源,注意,这里是“可用的”,因为一个节点上内存会被若干个服务贡享,比如一部分给了yarn,一部分给了hdfs,一部分给了hbase等,yarn配置的只是自己可用的,配置参数如下:
yarn.nodemanager.resource.memory-mb
表示该节点上yarn可以使用的物理内存总量,默认是8192m,注意,如果你的节点内存资源不够8g,则需要调减这个值,yarn不会智能的探测节点物理内存总量。
yarn.nodemanager.vmem-pmem-ratio
任务使用1m物理内存最多可以使用虚拟内存量,默认是2.1
yarn.nodemanager.pmem-check-enabled
是否启用一个线程检查每个任务证使用的物理内存量,如果任务超出了分配值,则直接将其kill,默认是true。
yarn.nodemanager.vmem-check-enabled
是否启用一个线程检查每个任务证使用的虚拟内存量,如果任务超出了分配值,则直接将其kill,默认是true。
yarn.scheduler.minimum-allocation-mb
单个任务可以使用最小物理内存量,默认1024m,如果一个任务申请物理内存量少于该值,则该对应值改为这个数。
yarn.scheduler.maximum-allocation-mb
单个任务可以申请的最多的内存量,默认8192m
Yarn cpu管理:
目前cpu被划分为虚拟cpu,这里的虚拟cpu是yarn自己引入的概念,初衷是考虑到不同节点cpu性能可能不同,每个cpu具有计算能力也是不一样的,比如,某个物理cpu计算能力可能是另外一个物理cpu的2倍,这时候,你可以通过为第一个物理cpu多配置几个虚拟cpu弥补这种差异。用户提交作业时,可以指定每个任务需要的虚拟cpu个数。在yarn中,cpu相关配置参数如下:
yarn.nodemanager.resource.cpu-vcores
表示该节点上yarn可使用的虚拟cpu个数,默认是8个,注意,目前推荐将该值为与物理cpu核数相同。如果你的节点cpu合数不够8个,则需要调减小这个值,而yarn不会智能的探测节点物理cpu总数。
yarn.scheduler.minimum-allocation-vcores
单个任务可申请最小cpu个数,默认1,如果一个任务申请的cpu个数少于该数,则该对应值被修改为这个数
yarn.scheduler.maximum-allocation-vcores
单个任务可以申请最多虚拟cpu个数,默认是32.
Yarn的内存相关配置参考:Yarn 内存分配管理机制及相关参数配置
七、构建Yarn应用程序
我们自己动手从头到尾构建一个Yarn应用程序是比较复杂的,很多时候也是不必要的,可以根据需要的不同选择一个优秀的分布式计算框架帮助我们构建应用程序,如需要DAG计算,则选择Spark、Tez;需要流式处理,则选择Spark、Samza或Storm。
也有一些开源项目帮助我们简化Yarn应用程序的构建,如Slider、Twill,目前均处于孵化器状态,暂时不讨论。Yarn本身也自带了一个例子“Distributed Shell Application”,向我们展示了如果通过Yarn Client API完成Client、Application Master与Yarn Daemons之间的交互。
构建Yarn应用程序的例子可以参阅:实现一个简单的Application框架、hadoop Yarn 编程API
参考资料:
YARN架构设计详解
YARN学习笔记——Overview and Architecture
分布式资源调度——YARN框架
Apache Hadoop YARN
Hadoop之YARN解析
Yarn 调度器Scheduler详解
Yarn 内存分配管理机制及相关参数配置
理解Hadoop YARN架构
hadoop Yarn 编程API
Hadoop学习之路(二十四)YARN的资源调度