什么是 YARN 以及 YARN 的架构
什么是 YARN
YARN的基本思想是将资源管理和作业调度/监视的功能拆分为单独的守护程序。这个想法是拥有一个全局ResourceManager(RM)和对每个应用程序拥有一个ApplicationMaster(AM)。
应用程序可以是单个作业(e.g. MapReduce Job),也可以是作业的DAG。
什么是 DAG
在数学,尤其是图论和计算机科学中,有向无环图是没有有向环的有向图。
这听起来跟没解释一样,没办法,我的数学基础为零。
先看下维基百科上对于DAG(directed acyclic graph)的解释:
也就是说,它由顶点(vertices)和边(edge)(也称为圆弧)组成,每个边都从一个顶点指向另一个顶点,并且在这个图(graph)内不存在从一个顶点出发最终会回到这个顶点的情况,也就是不存在环(cycle)。
等效地,DAG是有向图,它具有拓扑顺序,即一系列顶点,使得每个边缘从该序列的较早方向到最后位置。
听起来稍微有点理解,但还是比较模糊。还是看看图片帮助自己理解一下。
图例 1 - 链表、树和图
上图是图论中的几个基本概念 – 链表、树和图。图片来自知乎专栏 – 有向无环图 DAG。
再来看一个维基百科上的DAG的图例:
图例 2 - 一个DAG示例图
圆圈就是顶点,箭头就是边。
最后看一下环是什么:
图例 3 - 一个环状图的示例图
由此可见上面图例 1中的“图”也是一个DAG。
那么归纳一下,在YARN中,可以理解为:
一个DAG job集中的job位于一个整体的工作流中,且经过job-j这个阶段后,此工作流不会再经过job-j。
YARN 的架构
YARN属于典型的“一主多从”架构。“主”为资源管理器(ResourceManager),“从”为节点管理器(NodeManager)。
资源管理器负责整个集群的资源调度管理;节点管理器负责具体服务器上的资源和任务管理。因为Hadoop是将存储与计算放在一起来进行分布式计算的,这是基本思想,所以节点管理器通常是与HDFS的DataNode一起出现。
整体架构图如下:
具体说来,资源管理器又包括两个主要组件:调度器和应用程序管理器。
调度器其实就是一个资源分配算法,根据应用程序(Client)提交的资源申请和当前服务器集群的资源状况进行资源分配。
Yarn 内置了几种资源调度算法,包括 Fair Scheduler、Capacity Scheduler 等,你也可以开发自己的资源调度算法供 Yarn 调用。
Yarn 进行资源分配的单位是容器(Container),每个容器包含了一定量的内存、CPU 等计算资源,默认配置下,每个容器包含一个 CPU 核心。
容器由 NodeManager 进程启动和管理,NodeManger 进程会监控本节点上容器的运行状况并向 ResourceManger 进程汇报。
应用程序管理器负责应用程序的提交、监控应用程序运行状态等。应用程序启动后需要在集群中运行一个 ApplicationMaster,ApplicationMaster 也需要运行在容器里面。
每个应用程序启动后都会先启动自己的 ApplicationMaster,由 ApplicationMaster 根据应用程序的资源需求进一步向 ResourceManager 进程申请容器资源,得到容器以后就会分发自己的应用程序代码到容器上启动,进而开始分布式计算。
我们以一个 MapReduce 程序为例,来看一下 Yarn 的整个工作流程。
我们向 Yarn 提交应用程序,包括 MapReduce ApplicationMaster、
我们的 MapReduce 程序,以及 MapReduce Application 启动命令。
ResourceManager 进程和 NodeManager 进程通信,根据集群资源,为用户程序分配第一个容器,
并将 MapReduce ApplicationMaster 分发到这个容器上面,并在容器里面启动 MapReduce ApplicationMaster。
MapReduce ApplicationMaster 启动后立即向 ResourceManager 进程注册,并为自己的应用程序申请容器资源。
MapReduce ApplicationMaster 申请到需要的容器后,立即和相应的 NodeManager 进程通信,将用户 MapReduce
程序分发到 NodeManager 进程所在服务器,并在容器中运行,运行的就是 Map 或者 Reduce 任务。Map 或者 Reduce 任务在运行期和 MapReduce ApplicationMaster 通信,汇报自己的运行状态,如果运行结束,
MapReduce ApplicationMaster 向 ResourceManager 进程注销并释放所有的容器资源。
MapReduce 如果想在 Yarn 上运行,就需要开发遵循 Yarn 规范的 MapReduce ApplicationMaster,
相应地,其他大数据计算框架也可以开发遵循 Yarn 规范的 ApplicationMaster,这样在一个 Yarn 集群中就可以同时并发执行各种不同的大数据计算框架,实现资源的统一调度管理。
YARN 组件之间的交互
上面我提到了资源管理负责整个集群的资源调度管理,那么具体来看下有哪些逻辑单元呢?
资源管理器在内部保存着2种状态,一个是对于集群整体,另一个是对于应用程序。
集群状态
通过节点管理器默认地每秒钟发送心跳到资源管理器,来创建集群状态。
如果有一个节点超过10分钟没有心跳,资源管理器则会将此节点从调度中剥离。
另外除了心跳机制以外,一个节点还有可能变得“不健康”,如果如此,资源管理器也会将此节点拉黑并从调度观点中摘除。
那么节点管理器是否健康取决于什么呢?
基本上有2个原因会导致节点管理器不健康:
节点的健康状况通过一个health-check脚本来检查,用户可以自定义此脚本,这是在多数后台进程中常见的方式。
磁盘验证器发现节点上超过75%的磁盘使用率已经达到90%。一般来说,我们不应该将高水位线和低水位线设置为相同的阈值。
例如,如果我们为容器配置了1个磁盘,并且该磁盘已满90%,则我们有100%的磁盘状况不佳,因为我们达到了90%的高水位线。
这将导致NodeManager异常。 如果将低水位线配置为85%,则只有当我们在此节点上至少有15%的可用空间时,磁盘才会被视为正常,并且NodeManager会被标记为HEALTHY,并且可再次用于调度目的。
应用状态
当应用程序的Application Master开始运行时,将设置应用程序状态。 节点管理器跟踪其内存中所有正在运行的应用程序,最多10,000个应用程序。
YARN 应用程序提交
在本文先前的架构总览部分中介绍过YARN的“工作流程”,现在对此展开详细一点的介绍。如果看了上面的部分无法解决问题,可以看看下面这段描述。这对于分析YARN作业出问题的部位会有帮助。
Step 1: 客户端应用程序请求
YARN应用程序从客户端应用程序请求开始。 上图说明了客户端与资源管理器的ApplicationManager组件进行通信以启动此过程的初始步骤。 客户端必须首先通知资源管理器它要提交应用程序。
资源管理器使用ApplicationID和有关集群功能的信息进行响应,该信息将帮助客户端请求资源。
Step 2: ApplicationMaster 容器分配
接下来,客户端以“应用程序提交上下文”进行响应。 应用程序提交上下文包含应用程序ID,用户,队列和其他启动ApplicationMaster所需的信息。
另外,“容器启动上下文”(CLC)被发送到ResourceManager。 CLC提供了资源要求(内存/ CPU),作业文件,安全令牌以及在节点上启动ApplicationMaster所需的其他信息。
当资源管理器从客户端接收到应用程序提交上下文时,它将为ApplicationMaster计划可用的容器。
该容器通常被称为“容器0”,因为它是ApplicationMaster,它必须请求其他容器。
如果没有适用的容器,则请求必须等待。如果可以找到合适的容器,则资源管理器与合适的NodeManager联系并启动ApplicationMaster。
作为此步骤的一部分,将建立ApplicationMaster RPC端口和用于监视应用程序状态的跟踪URL。
YARN 组件
资源管理器中的服务
Client Service
此组件(监听8032端口)处理从客户端到ResourceManager的所有远程过程调用(RPC)通信,包括以下操作:
- 应用提交
- 应用终止
- 暴露有关应用程序,队列,集群统计信息,用户ACL等的信息
Admin Service
此组件(监听8033端口)处理到客户端的其他RPC端口(默认情况下为8033)上的Admin操作调用,以便普通用户的请求不会占用admin请求的资源带宽。
它处理如下请求:- 添加新队列,删除现有队列以及重新配置队列以更改其某些属性(例如容量,限制等)
- 添加新安装的节点或停用现有节点
- 添加新的“用户与组”的映射,添加/更新管理员ACL,修改超级用户列表等等
Web Server
这是显而易见的。 它是Web应用程序,它公开有关群集指标,应用程序列表,应用程序状态等的信息。在非SSL群集中,它运行在端口8088上,在SSL群集中运行在端口8090上。
ApplicationACLsManager
资源管理器需要控制诸如客户端和管理请求之类的面向用户的API,以便仅让授权的用户才能访问它们。 该组件维护每个应用程序的ACL并执行它们。
ApplicationsManager
- 这是RM中已提交应用程序的应用程序“仓库”。
它会验证应用程序的规范,并拒绝一些应用程序的请求,这些请求将导致该应用程序的ApplicationMaster资源不够用(也就是说这个情况是集群中没有足够的资源来运行该应用的ApplicationMaster本身)。 - 然后,它可以确保没有其他应用程序以相同的应用程序ID提交(这种情况可能是由错误或恶意的客户端引起的)。 最后,它将已接受的应用程序转发给scheduler。
- 在应用程序结束后,为了支持用户对应用程序数据的请求(通过Web UI或命令行),它还能保留已完成的应用程序的缓存。
- 这是RM中已提交应用程序的应用程序“仓库”。
ApplicationMasters Service
此组件在端口8030响应来自所有ApplicationMaster的请求。它实现ApplicationMasterProtocol,
这是ApplicationMaster用来与ResourceManager通信的唯一协议。 它负责以下任务:- 注册新的ApplicationMaster
- 终止/注销任何完成的ApplicationMaster的请求
- 授权来自各种ApplicationMaster的所有请求以确保仅有效的ApplicationMaster将请求发送到驻留在ResourceManager中的相应Application实体
- 从所有正在运行的ApplicationMaster获得容器分配和释放请求,并将它们异步转发到YarnScheduler
ApplicationMastersService具有其他逻辑,以确保在任何时间点,任何ApplicationMaster中只有一个线程可以将请求发送到ResourceManager。
来自ApplicationMaster的所有RPC都在ResourceManager上序列化,因此可以预期ApplicationMaster中只有一个线程会发出这些请求。AM LivelinessMonitor
为了帮助管理活动的ApplicationMaster和死的/未响应的ApplicationMaster列表,此监视器跟踪每个ApplicationMaster及其最后的心跳时间。
在所配置的时间间隔(默认为10分钟)内未产生心跳的任何ApplicationMaster都被视为已死,并且被ResourceManager处理为过期。
当前正在运行/已分配给到期的ApplicationMaster的所有容器都标记为已失效。
ResourceManager重新计划了同一应用程序,以便在新容器上运行新的“应用程序尝试”,默认情况下最多允许两次此类尝试。ContainerAllocationExpirer
该组件负责确保所有分配的容器最终由ApplicationMaster使用,并随后在相应的NodeManager上启动。
ApplicationMaster是不受信任的用户代码,它们可能在获得了资源分配后而不实际使用它(也就是启动具体任务)。因此,它们可能导致群集资源的利用率不足和滥用。
为了解决这个问题,ContainerAllocationExpirer维护了已分配但尚未在相应的NodeManager上使用的容器列表。
对于任何容器,如果相应的NodeManager均未在配置的时间间隔(默认为10分钟)内向ResourceManager报告该容器已开始运行,则该容器被视为已失效,并且被ResourceManager处理为过期。此外,NodeManager会独立查看此到期时间,该到期时间编码在与容器绑定的ContainerToken中,并拒绝在到期时间过后提交启动的容器。
Scheduler (Fair)
它负责根据容量,队列等的约束将资源分配给各种正在运行的应用程序。
Resource Tracker Service
默认情况下,NodeManager会定期在端口8031上将心跳信号发送到资源管理器,并且资源管理器的此组件负责响应来自所有节点的此类RPC。
具体来说,它负责以下任务:- 注册新节点/取消注册现有节点,
- 接受来自先前注册的节点的节点心跳
- 确保只有“有效”节点才能与ResourceManager交互,并拒绝任何其他节点
NodeManagers Liveliness Monitor
为了跟踪活动的节点并明确标识任何死的节点,此组件跟踪每个节点的标识符(ID)及其最后的心跳时间。
在配置的时间间隔内(默认情况下为10分钟)未发送心跳的任何节点都被视为已死,并且被ResourceManager过期。当前在过期节点上运行的所有容器都标记为已失效,并且在该节点上不会安排任何新容器。
一旦此类节点重新启动(自动或通过管理员的干预)并重新注册,将再次考虑对其进行调度。Nodes-List Manager
节点列表管理器是资源管理器内存中有效节点和排除节点的集合。它负责读取通过
yarn.resourcemanager.nodes.include-path
和yarn.resourcemanager.nodes.exclude-path
配置属性指定的主机配置文件,并基于这些文件在节点上做种文件的初始列表。
它还会随着时间的推移跟踪被管理员明确停用的节点。注:此处的做种为peer-to-peer文件共享领域中的seeding的意思。
在这里,我不会过多地讨论安全层面,而只是说资源管理器负责为YARN组件生成令牌以及更新委托令牌,以防止各个容器访问KDC来验证自己的身份以访问服务。
有关更多讨论,请参见博客https://blog.cloudera.com/blog/2017/12/hadoop-delegation-tokens-explained/。
节点管理器中的服务
从高层角度来看节点管理器的职责:
1.跟踪节点运行状况,
2.容器生命周期管理;监视各个容器的资源使用情况(例如内存,CPU),
3.资源本地化,
4.管理容器生成的日志,包括日志聚合,
5.允许可插拔的辅助服务,例如 ShuffleHandler,
6.与资源管理器通讯并保持最新状态(通过心跳到资源管理器)
NodeStatusUpdater
在启动时,此组件向资源管理器注册。 它发送有关此节点上可用资源的信息,并标识节点管理器的Web服务器和RPC服务器正在侦听的端口。
向资源管理器注册后,此服务将启动一个线程,用于每1秒对资源管理器进行心跳。
节点管理器至资源管理器心跳间隔是通过以下设置配置的:yarn.resourcemanager.nodemanagers.heartbeat-interval-ms
。
后续的NodeManager–ResourceManager通信为ResourceManager提供有关现有容器状态的任何更新,包括由ApplicationMaster在节点上启动的新容器,已完成的容器等等。
此外,ResourceManager可能会通过此组件向NodeManager发出信号,使其可能杀死当前正在运行的容器,例如,由于调度策略会在运维人员显式停用或在发生网络问题时重新同步NodeManager等情况下关闭NodeManager。
最后,当任何应用程序在ResourceManager上完成时,ResourceManager会向NodeManager发出信号,以清理NodeManager上的各种特定于应用程序的实体(例如,内部的每个应用程序的数据结构和应用程序级别的本地资源),然后启动并完成每个应用程序的日志聚合,并记录到文件系统上。Container Manager
该组件是NodeManager的核心。 它由以下子组件组成,每个子组件执行管理节点上运行的容器所需的功能子集:
RPC Server
ContainerManager接受来自AM的请求以启动新容器或停止运行它们。它与NMToken SecretManager和
ContainerToken SecretManager一起使用以对所有请求进行身份验证和授权。Resource Localization Service
它负责安全地下载和组织容器所需的各种文件资源。它会尽力在所有可用磁盘上分发文件。它还对下载的文件强制执行访问控制限制,并对它们施加适当的使用限制。
Auxiliary Services
NodeManager提供了一个通过配置这些服务来扩展其功能的框架。此功能允许特定(计算)框架(例如Spark等)可能需要的以节点为单位的自定义服务,但将它们放置在与NodeManager其余部分分开的本地“沙盒”中。
必须在NodeManager启动之前配置这些服务。当应用程序的第一个容器在节点上启动时,每当容器启动或完成时,以及最终在应用程序被视为完成时,都会通知辅助服务。Container Launcher
Containers Launcher维护一个线程池,以尽快准备和启动容器。当ResourceManager通过NodeStatusUpdater发送此类请求或ApplicationMaster通过RPC服务器发送请求时,它还会清理容器进程。
Container Monitor
ContainersMonitor持续监视每个容器的使用情况。如果容器超出其分配范围,则此组件会发信号通知容器被杀死。进行此检查是为了防止任何失控的容器对在同一节点上运行的其他行为良好的容器产生不利影响。
Log Handler
使用YARN,可将属于单个应用程序且在给定NodeManager上运行的所有容器的日志汇总并写到指定文件系统中配置位置的单个(可能是压缩的)日志文件中。在当前的实现中,一个应用程序完成后,将拥有一个应用程序级别的日志目录和一个每个节点的日志文件,该文件由在该节点上运行的应用程序所有容器的日志组成。LogAggregationService实现LogHandler。
Container Executor
这本身就是一个话题。简而言之,此组件与基础操作系统进行交互,以安全地放置容器所需的文件和目录,并随后以安全的方式启动和清理与容器相对应的进程。
Node Health Checker Service
NodeHealthCheckerService通过频繁运行配置的脚本来检查节点的运行状况。 它还经常通过在磁盘上创建临时文件来监视磁盘的运行状况。
系统运行状况的任何更改都将发送到NodeStatusUpdater(如前所述),后者将信息传递给ResourceManager。Web Server
此组件提供以下信息:应用程序列表、在给定时间点在节点上正在运行的容器、与节点运行状况相关的信息以及容器产生的日志。
Deletion Service
在NodeManager内运行并根据指示删除本地路径的服务。
YARN 应用程序的声明周期
这些图详细介绍了应用程序生命周期,尤其是应用程序的不同状态类型,应用程序任务尝试,容器状态等。
建议在控制台和NodeManager进程上启用DEBUG日志,以更好地了解上述事件的顺序。
小结
本文主要参考:
极客时间专栏 - 李智慧 - 从0开始学大数据
Cloudera培训资料
Cloudera Blog:
YARN是一个集群资源调度框架,对于大数据应用程序开发者来说,虽然几乎不需要自定义YARN本身的程序,但是由于计算框架需要实现Application Master,以及我们要使用这些计算框架集成的YARN模块,所以对YARN的实现原理有所了解是很有帮助的。
另外,YARN对于管理员来说,还需要管理员熟悉如何查看日志、如何配置队列、用户ACL等操作,这些实操性比较强的工作,最好结合管理套件一齐操作,这也是Cloudera产品的核心价值所在。