Yarn 设计理念
Yarn 产生背景
Yarn 是在 MRv1 的基础上演化而来,解决了一些 MRv1 中的各种局限性。首先了解一下 MRv1 的一些局限性:
扩展性差,在 MRv1 中,JobTracker 同时兼备了资源管理和作业控制两个功能,这称为系统的一个最大瓶颈,严重制约了 Hadoop 集群扩展性
可靠性差,MRv1 采用了 Master/Slave 结构,Master 存在单点故障的问题,一旦出现故障将导致整个集群不可用
资源利用率低,MRv1 采用了基于任务槽(slot)的资源分配模型,是一种粗粒度的资源划分单位。通常一个任务不会耗尽一个 slot 对应的资源,而其他任务也无法使用空闲资源。此外,slot 分为 Map slot 和 Task slot 两种,互相不能共享,会导致一种资源耗尽而另一种资源闲置。
无法支持多计算框架,随着计算量增大和计算速度要求,MapReduce 这种基于磁盘的离线计算框架已经不能满足应用要求。一些新的基于内存、流式计算框架出现,MRv1 不能支持多种计算框架
为了解决以上几个缺点,MRv2 将资源管理功能抽象成了一个独立的通用系统 YARN。在以 MapReduce 为核心的软件栈中,资源管理系统 YARN 是可插拔替换的(比如选择 Mesos 替换 YARN),一旦 MapReduce 接口改变,所有的资源管理系统的实现均需要跟着改变;而以 YARN 为核心的软件栈则不同,所有框架都需要实现 YARN 定义的对外接口以运行在 YARN 之上,从而打造一个以 YARN 为核心的生态系统。
轻量级弹性计算框架
随着互联网的高速发展,基于数据密集型应用的计算框架不断出现,从支持离线处理的 MapReduce,到支持在线处理的 Storm,从迭代式计算框架 Spark 到流式处理框架 S4 等, 各种框架各有所长,各自解决了某一类应用问题。在大部分业务中,这几种框架可能同时被采用。考虑到资源利用率、运维成本、数据共享等因素,一般会选择将所有这些都部署到 一个公共的集群中,共享集群的资源,并对资源进行统一使用,同时采用某种资源隔离方案(如轻量级 cgroups)对各个任务进行隔离,这样便诞生了轻量级弹性计算平台,YARN 便是弹性计算平台的典型代表。
YARN 的目标已经不再局限于支持 MapReduce 一种计算框架,而是朝着对多种框架进行统一管理的方向发展。相比于“一种计算框架一个集群”的模式,共享集群的模式的好处:
资源利用率高。如果每个框架一个集群,往往由于应用程序数量和资源需求的不均衡性,使得在某段时间内,有些集群资源紧张,而另外一些集群资源空闲。共享集群模式则通过多种框架共享资源,使得集群中的资源得到更加充分的利用。当然也会造成业务集中处理时资源紧张。
运维成本低。只需要对共享的集群进行维护。
数据共享。随着数据量的快速增长,跨集群间的数据移动不仅需花费更长的时间,且成本也会大大增加,而共享集群模式可让多种框架共享数据和硬件资源。
Yarn 编程模型
Yarn 基本架构
YARN 基本设计思想是将 MRv1 中的 JobTracker 拆分成两个独立的服务:一个全局的资源管理器 ResourceManager 和每个应用程序特有的 ApplicationMaster。其中 ResourceManager 负责整个系统的资源管理和分配,ApplicationMaster 负责单个应用程序的管理。
YARN 总体上仍然是 Master/Slave 结构,ResourceManager(后面简称为 RM)为 Master,NodeManager(后面简称为 NM)为 Slave,RM 负责对各个 NM 上的资源进行统一管理和调度。当提交一个应用程序时,会创建一个用以跟踪和管理这个程序的 ApplicationMaster(后面简称为 AppMaster),负责向 RM 申请资源,并要求 NM 启动可以占用一定资源的任务。由于不同的 AppMaster 被分布到不同的节点上,互相之间不会影响。
ResourceManager(RM)
RM 是一个全局的资源管理器,负责整个系统的资源管理和分配。主要由两个组件构成:调度器(Scheduler)和应用程序管理器(Applications Manager,ASM)
- 调度器(Scheduler),根据容量、队列等限制条件(如每个队列分配一定的资源,最多执行一定数量的作业等),将系统中的资源分配给各个正在运行的应用程序。不从事任何与具体应用程序相关的工作(比如负责监控或者跟踪应用的执行状态等),也不负责重新启动失败的任务,这些均由应用程序相关的 ApplicationMaster 完成。
调度器是一个可插拔的组件, 用户可根据自己的需要设计新的调度器,YARN 提供了多种直接可用的调度器,比如 Fair Scheduler 和 Capacity Scheduler 等。
- 应用程序管理器(ASM),负责管理整个系统中所有应用程序,包括应用程序提交、与调度器协商资源以启动 AppMaster、监控 AppMaster 运行状态并在失败时重新启动等。
ApplicationMaster(AppMaster)
用户提交的每个应用程序均包含一个 AppMaster,主要功能包括:
- 与 RM 调度器协商以获取资源
- 将得到的任务进一步分配给内部的任务
- 与 NM 通信以启动/停止任务
- 监控所有任务运行状态,并在任务运行失败时重新为任务申请资源以重启任务。
NodeManager(NM)
NM 是每个节点上的资源和任务管理器,一方面,它会定时地向 RM 汇报本节点上的资源使用情况和各个 Container 的运行状态;另一方面,它接收并处理来自 AppMaster 的 Container 启动/停止等各种请求。
Container
Container 是 YARN 中的资源抽象,封装了某个节点上的多维度资源,如内存、 CPU、磁盘、网络等,当 AppMaster 向 RM 申请资源时,RM 为 AppMaster 返回的资源便是用 Container 表示的。YARN 会为每个任务分配一个 Container,且该任务只能使用该 Container 中描述的资源。
Container 不同于 MRv1 中的 slot,它是一个动态资源划分单位,是根据应用程序的需求动态生成的。目前,YARN 仅支持 CPU 和内存两种资源, 使用了轻量级资源隔离机制 Cgroups 进行资源隔离 。
Yarn 通信协议
RPC 协议负责连接各个组件,在 YARN 中,任何两个需相互通信的组件之间仅有一个 RPC 协议,而对于任何一个 RPC 协议,通信双方有一端是 Client,另一端为 Server,且 Client 总是主动连接 Server。因此,YARN 实际上采用的是拉式(pull-based)通信模型。如下图,箭头指向的组件是 RPC Server,而箭头尾部的组件是 RPC Client:
YARN 主要由以下几个 RPC 协议组成:
JobClient(作业提交客户端)与 RM 之间的协议 — ApplicationClientProtocol:JobClient 通过该 RPC 协议提交应用程序、查询应用程序状态等。
Admin(管理员)与 RM 之间的通信协议 — ResourceManagerAdministrationProtocol:Admin 通过该 RPC 协议更新系统配置文件,比如节点黑白名单、用户队列权限等。
AM 与 RM 之间的协议 — ApplicationMasterProtocol:AM 通过该 RPC 协议向 RM 注册和撤销自己,并为各个任务申请资源。
AM 与 NM 之间的协议 — ContainerManagementProtocol:AM 通过该 RPC 要求 NM 启动或者停止 Container,获取各个 Container 的使用状态等信息。
NM 与 RM 之间的协议 — ResourceTracker:NM 通过该 RPC 协议向 RM 注册,并定时发送心跳信息汇报当前节点的资源使用情况和 Container 运行情况。
Yarn 工作流程
当用户向 YARN 中提交一个应用程序后,YARN 将分两个阶段运行该应用程序:第一个阶段是启动 AppMaster;第二个阶段是由 AppMaster 创建应用程序,为它申请资源,并监控它的整个运行过程,直到运行完成:
YARN 的工作流程分为以下几个步骤:
步骤 1 用户向 YARN 中提交应用程序,其中包括 ApplicationMaster 程序、启动 ApplicationMaster 的命令、用户程序等。
步骤 2 ResourceManager 为该应用程序分配第一个 Container,并与对应的 NodeManager 通信,要求它在这个 Container 中启动应用程序的 ApplicationMaster。
步骤 3 ApplicationMaster 首先向 ResourceManager 注册,这样用户可以直接通过 ResourceManage 查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复步骤 4~7。
步骤 4 ApplicationMaster 采用轮询的方式通过 RPC 协议向 ResourceManager 申请和领取资源。
步骤 5 一旦 ApplicationMaster 申请到资源后,便与对应的 NodeManager 通信,要求它启动任务。
步骤 6 NodeManager 为任务设置好运行环境(包括环境变量、JAR 包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务。
步骤 7 各个任务通过某个 RPC 协议向 ApplicationMaster 汇报自己的状态和进度,以让 ApplicationMaster 随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。在应用程序运行过程中,用户可随时通过 RPC 向 ApplicationMaster 查询应用程序的当前运行状态。
步骤 8 应用程序运行完成后,ApplicationMaster 向 ResourceManager 注销并关闭自己。
推荐书籍
《Hadoop技术内幕:深入解析YARN架构设计与实现原理》