signed

QiShunwang

“诚信为本、客户至上”

第四章 关于 YARN

2021/3/21 3:41:16   来源:

第四章 关于 YARN

Apache YARN(Yet Another Resource Negotiator)是Hadoop的集群管理系统。YARN被引入Hadoop2,最初是为了改善MapReduce的实现,但它具有足够的通用型,同样可以支持其他的分布式计算模式。

YARN 提供请求和使用集群资源的API,但这些API很少直接用于用户代码。相反,用户代码中使用的是分布式计算框架提供的更高层API,这些API建立在YARN之上且向用户屏蔽了资源管理细节。

YARN 应用运行机制

YARN 通过两类长期运行的守护进程提供自己的核心服务:

  • 管理集群上资源使用的资源管理器(resource manager)
  • 运行在集群中所有节点上且能够启动和监控容器(container)的节点管理器(node manager)
    容器用于执行特定应用程序的进程,每个容器都有资源限制(内存、CPU等)。一个容器可以是一个Unix进程,也可以是一个Linux cgroup,取决于YARN的配置。

为了在YARN上运行一个应用,首先,客户端联系资源管理器,要求它运行一个application master进程。然后,资源管理器找到一个能够在容器中启动application master的节点管理器。准确地说,application master 一旦运行起来后能做些什么依赖于应用本身。

YARN本身不会为应用的各部分(客户端、master和进程)彼此间通信提供任何手段。大多数重要的YARN 应用使用某种形式的远程通信机制(例如Hadoop的RPC层)来向客户端传递状态更新和返回结果,但是这些通信机制都是专属于各应用的。

资源请求

YARN 有一个灵活的资源请求模型。当请求多个容器时,可以指定每个容器需要的计算机资源数量(内存和CPU),还可以指定对容器的本地限制要求。

本地化对于确保分布式数据处理算法高效使用集群带宽非常重要,因此,YARN 允许一个应用为所申请的容器指定本地限制。本地限制可用于申请位于指定节点或机架,或集群中任何位置(机架外)的容器。

有时本地限制无法被满足,这种情况下要么不分配资源,或者可选择放松限制。例如,一个节点由于已经运行了别的容器而无法再启动新的容器,这时如果有应用请求该节点,则YARN 将尝试在同一机架中的其他节点上启动一个容器,如果还不行,则会尝试集群中的任何一个节点。

通常情况下,当启动一个容器用于处理HDFS 数据块(为了在MapReduce 中运行一个map任务)时,应用将会向这样的节点申请容器:存储该数据块三个复本的节点,或是存储这些复本的机架中的一个节点。如果都申请失败,则申请集群中的任意节点。

YARN 应用可以在运行中的任意时刻提出资源申请。例如,可以在最开始提出所有的请求,或者为了满足不断变化的应用需要,采取更为动态的方式在需要更多资源时提出请求。Spark 采用了上述第一种方式,在集群上启动固定数量的执行器。另一方面,MapReduce 则分两步走,在最开始时申请map任务容器,reduce任务容器的启用则放在后期。同样,如果任何任务出现失败,将会另外申请容器以重新运行失败的任务。

应用生命周期

YARN 应用的生命期差异性很大:有几秒的短期应用,也有连续运行几天甚至几个月的长期应用。与其关注应用运行多长时间,不如按照应用到用户运行的作业之间的映射关系对应用进行分类更有意义。最简单的模型就是一个用户作业对应一个应用,这也是MapReduce 采取的方式。

第二种模型是,作业的每个工作流或每个用户对话(可能并无关联性)对应一个应用。这种方法要比第一种情况效率更高,因为容器可以在作业之间重用,并且有可能缓存作业之间的中间数据。Spark采取的是这种模型。

第三种模型是,多个用户共享一个长期运行的应用。这种应用通常是作为一种协调者的角色在运行。例如,Apache Slider有一个长期运行的application master,主要用于启动集群上的其他应用。Impala 也使用这种模型提供了一个代理应用,Impala 守护进程通过该代理,请求集群资源。由于避免了启用新application master 带来的开销,一个总是开启(always on)的application master 意味着用户将获得非常低延迟的查询响应。

YARN 中的调度

理想情况下,YARN 应用发出的资源请求应该立刻给予满足。然而现实中资源是有限的,在一个繁忙的集群上,一个应用经常需要等待才能获取所需的资源。YARN 调度器的工作就是根据既定策略为应用分配资源。调度通常是一个难题,并且没有一个所谓“最好”的策略,这也是为什么YARN 提供了多种调度器和可配置策略供我们选择的原因。

调度选项

YARN 中有三种调度器可用:FIFO 调度器(FIFO Scheduler),容量调度器 (Capacity Scheduler)和公平调度器(Fair Scheduler)。FIFO 调度器将应用放置在一个队列中,然后按照提交的顺序运行应用。首先为队列中第一个应用的请求分配资源,第一个应用的请求被满足后再依次为队列中下一个应用服务。

FIFO 调度器的优点是,简单易懂,不需要任何配置,但是不适合共享集群。大的应用会占用集群中所有的资源,所以每个应用必须等待直到轮到自己运行。在一个共享集群中,更适合使用容量调度器或公平调度器。这两种调度器都允许长时间运行的作业能及时完成,同时也允许正在进行较小临时查询的用户能够在合理时间内返回结果。

使用容量调度器时,一个独立的专门队列保证小作业一提交就可以启动,由于队列容量是为那个队列中的作业所保留的,因此这种策略是以整个集群的利用率为代价的。这意味着与使用FIFO调度器相比,大作业执行时间要更长。容量调度器允许“弹性队列”,即当某一队列中的资源不够用时,这时如果集群仍有可用的空闲资源,那么容量调度器可能会将空余的资源分配给该队列中的作业,尽管这会超出队列容量但不超出队列最大容量(即配置文件中的容量属性和最大容量属性)。

使用公平调度器时,不需要预留一定量的资源,因为调度器会在所有运行的作业之间动态平衡资源。第一个作业启动时,它也是唯一运行的作业,因而获得集群中的所有资源。当第二个作业启动时,它被分配到集群的一半资源,这样每个作业都能公平共享资源。

注意,从第二个作业的启动到获得公平共享资源之间会有时间滞后,因为它必须等待第一个作业使用的容器用完并释放出资源。当第二个作业结束且不再申请资源后,第一个作业将回去再次使用全部的集群资源。最终的效果是:既得到了较高的集群利用率,又能保证小作业能及时完成。

容量调度器不支持抢占,公平调度器支持抢占。所谓抢占,就是允许调度器终止那些占用资源超过了其公平共享份额的队列的容器,这些容器资源释放后可以分配给资源数量低于应得份额的队列。注意,抢占会降低整个集群的效率,因为被终止的containers需要重新执行。

延迟调度

所有的 YARN 调度器都试图以本地请求为重。在一个繁忙的集群上,如果一个应用请求某个节点,那么极有可能此时有其他容器正在该节点上运行。显而易见的处理是,立刻放宽本地性需求,在同一机架中分配一个容器。然而,通过实践发现,此时如果等待一小段时间(不超过几秒),能够戏剧性的增加在所请求的节点上分配到一个容器的机会,从而可以提高集群的效率。这个特性称之为延迟调度。容量调度器和公平调度器都支持延迟调度。

YARN 中的每个节点管理器周期性的(默认每秒一次)向资源管理器发送心跳请求。心跳中携带了节点管理器中正运行的容器、新容器可用的资源等信息,这样对于一个计划运行一个容器的应用而言,每个心跳就是一个潜在的调度机会。

当使用延迟调度时,调度器不会简单的使用它收到的第一个调度机会,而是等待设定的最大数目的调度机会发生,然后才放松本地性限制并接收下一个调度机会。

主导资源公平性

主导资源公平性(Dominant Resource Fairness,DRF):观察每个用户的主导资源,并将其作为对集群资源使用的一个度量。例如,应用A请求的CPU资源和内存资源在集群中的占比分别为3%和2%,那么CPU 是应用A的主导资源。

默认情况不开启DRF,因此在资源计算期间,只需要考虑内存,不必考虑CPU。DRF可通过配置文件开启。