【YARN 权威指南】3. 组件的功能概述


在上一篇中已经介绍了 YARN 的整体架构:ResourceManager(RM)负责集群资源调度,NodeManager(NM)负责单机资源管理,ApplicationMaster(AM)负责单个应用的生命周期管理,Container 则是 YARN 分配资源的基本单位。

这一篇主要补充这些组件各自负责什么,以及它们之间如何配合完成一次应用运行。

1. 体系架构概述

YARN 将资源管理与计算引擎的执行逻辑解耦。ResourceManager 不直接管理每一种计算框架内部的任务执行细节,而是负责全局资源调度;具体任务如何拆分、如何重试、如何汇报进度,则交给各个框架自己的 ApplicationMaster 处理。

这种设计带来的结果是:

  1. 集群可以同时运行 MapReduce、Spark、Flink、Tez 等不同类型的应用。
  2. ResourceManager 的职责更集中,不需要维护所有任务的执行细节。
  3. 不同应用可以根据自己的计算模型实现不同的 ApplicationMaster。
  4. NodeManager 负责本节点上的 Container 生命周期管理,包括启动、监控和清理。

2. ResourceManager

ResourceManager 是整个 YARN 集群的中心服务,负责接收应用提交、调度资源、管理节点状态和维护应用生命周期。

ResourceManager 主要包含两类核心职责:

  1. 资源调度:由 Scheduler 负责,根据队列容量、资源使用情况、应用优先级和本地性等因素分配 Container。
  2. 应用管理:由 ApplicationsManager 负责,接收客户端提交请求,启动 ApplicationMaster,并在 ApplicationMaster 失败时根据策略重新启动。

ResourceManager 不直接启动用户任务,也不跟踪每个任务的业务执行细节。但它会为应用分配用于启动 ApplicationMaster 的第一个 Container。之后,ResourceManager 主要维护集群资源状态、节点心跳信息、应用资源请求以及已经分配出去的 Container。

2.1 客户端和 ResourceManager 的交互

客户端提交应用时,会先向 ResourceManager 申请一个新的 ApplicationId,然后上传应用运行所需的文件,最后提交应用启动上下文。启动上下文中通常包括:

  1. ApplicationMaster 启动命令。
  2. ApplicationMaster 需要的内存和 CPU。
  3. 应用依赖的 jar 包、配置文件等 LocalResource。
  4. 环境变量和安全令牌。

ResourceManager 接收应用后,会为 ApplicationMaster 分配第一个 Container,并通知对应 NodeManager 启动它。

2.2 ApplicationMaster 和 ResourceManager 的通信

ApplicationMaster 启动后会向 ResourceManager 注册。注册完成后,它就可以根据应用内部任务数量和资源需求,持续向 ResourceManager 申请 Container。

ResourceManager 返回 Container 分配结果后,ApplicationMaster 再去联系对应的 NodeManager 启动任务。任务执行结束后,ApplicationMaster 会继续向 ResourceManager 汇报状态,直到应用完成并注销。

2.3 NodeManager 和 ResourceManager 的通信

NodeManager 会周期性向 ResourceManager 发送心跳,心跳中包含本节点的健康状态、资源使用情况和 Container 运行状态。ResourceManager 根据这些心跳维护集群视图。

如果某个 NodeManager 长时间没有心跳,ResourceManager 会认为该节点不可用,并把它上面运行的 Container 标记为失败。具体是否重试任务,由对应应用的 ApplicationMaster 决定。

3. YARN 调度器组件

YARN 的 Scheduler(调度器)是可插拔的,常见调度器包括 FIFO、Capacity 和 Fair。

3.1 FIFO 调度器

FIFO 调度器按照应用提交顺序分配资源,先提交的应用优先获得资源。它实现简单,但不适合多用户共享集群,因为大任务可能长时间占用资源,导致后续小任务排队等待。

3.2 Capacity 调度器

Capacity 调度器面向多租户场景。管理员可以把集群资源划分成多个队列,每个队列配置一定的容量。不同团队或业务线提交到不同队列中,在保证队列容量的同时,也可以在资源空闲时临时使用其他队列未用完的资源。

Capacity 调度器常用于生产集群,因为它能兼顾资源隔离和集群利用率。

3.3 Fair 调度器

Fair 调度器的目标是让多个应用尽可能公平地共享集群资源。它会不断调整资源分配,使每个应用在一段时间后都能获得相对公平的资源份额。

Fair 调度器适合多用户、任务大小差异较大的环境,可以减少小任务被大任务长期阻塞的问题。

4. Container

Container 是 YARN 分配资源的基本单位。一个 Container 表示某个节点上的一组资源,例如一定数量的内存和 CPU。

需要注意的是,Container 不是一个具体的进程,而是资源和启动上下文的抽象。它通常包含 CPU、内存等资源能力,也包含启动命令、环境变量、LocalResource 等运行上下文。Container 被分配给应用后,NodeManager 会根据 ApplicationMaster 提供的启动上下文,在这个资源范围内启动具体进程。

一个 YARN 应用至少会有一个 Container 用于运行 ApplicationMaster。ApplicationMaster 启动后,可以继续申请更多 Container 来运行具体任务。

Container 的生命周期大致如下:

  1. ApplicationMaster 向 ResourceManager 申请资源。
  2. ResourceManager 分配某个节点上的 Container。
  3. ApplicationMaster 请求该节点的 NodeManager 启动 Container。
  4. NodeManager 准备运行环境,启动用户进程。
  5. Container 运行结束后,NodeManager 汇报状态并清理本地资源。

5. NodeManager

NodeManager 是每个计算节点上的代理服务,负责管理本节点资源和 Container。

NodeManager 的主要功能包括:

  1. 向 ResourceManager 注册并周期性发送心跳。
  2. 接收 ApplicationMaster 的请求,启动或停止 Container。
  3. 监控 Container 的内存、CPU 等资源使用情况。
  4. 管理应用依赖文件的本地化。
  5. 收集和聚合 Container 日志。
  6. 清理应用结束后的本地临时文件。

NodeManager 不决定哪个应用可以获得资源,也不决定应用内部任务如何调度。它不参与全局调度决策,只负责执行 ResourceManager 和 ApplicationMaster 分配到本节点上的 Container 生命周期管理工作。

6. ApplicationMaster

ApplicationMaster 是每个 YARN 应用的协调进程(coordinator)。不同计算框架会实现自己的 ApplicationMaster,例如 MapReduce 有 MapReduce ApplicationMaster,Spark on YARN 中也会启动对应的 ApplicationMaster。

ApplicationMaster 的主要职责包括:

  1. 向 ResourceManager 注册应用。
  2. 根据任务需求向 ResourceManager 申请 Container。
  3. 和 NodeManager 通信,启动具体任务。
  4. 跟踪任务运行状态、处理失败重试。
  5. 向客户端提供应用进度。
  6. 应用结束后向 ResourceManager 注销并清理资源。

ApplicationMaster 是 YARN 的核心协调组件之一。它让 ResourceManager 不需要理解每种计算框架的内部逻辑,也让不同框架可以根据自己的执行模型管理任务。

ResourceManager 和 ApplicationMaster 的职责边界可以简单对比如下:

组件 关注范围 主要职责 不负责的事情
ResourceManager 整个集群 维护资源状态、接收应用提交、调度 Container、启动 ApplicationMaster 不直接执行用户任务,不理解具体计算框架的任务逻辑
ApplicationMaster 单个应用 申请 Container、协调 NodeManager 启动任务、跟踪任务进度和失败重试 不做全局资源调度,不管理其他应用

7. YARN 资源模型

YARN 使用 ResourceRequest 表达应用对资源的需求。一个资源请求通常包含以下信息:

  1. 资源位置:可以是某个节点、某个机架,也可以是不指定位置。
  2. 优先级:同一个应用内部不同请求之间的优先级。
  3. 资源能力:每个 Container 需要多少内存和 CPU。
  4. Container 数量:需要多少个满足条件的 Container。

ResourceManager 会根据这些请求,在集群可用资源范围内尽量满足应用需求。如果应用请求了特定节点或机架,调度器会优先考虑数据本地性;如果本地资源不足,也可能退化为机架本地或任意节点。

把前面的组件串起来,一次典型的应用提交和资源申请流程如下:

  1. Client 向 ResourceManager 提交应用,并携带 ApplicationMaster 启动上下文。
  2. ResourceManager 为 ApplicationMaster 分配第一个 Container。
  3. NodeManager 在对应节点上启动 ApplicationMaster。
  4. ApplicationMaster 向 ResourceManager 注册,并根据任务需求申请更多 Container。
  5. ResourceManager 通过 Scheduler(调度器)分配 Container。
  6. ApplicationMaster 联系对应 NodeManager,要求其启动具体任务。
  7. NodeManager 管理 Container 生命周期,并通过心跳向 ResourceManager 汇报状态。

8. 管理应用程序的依赖文件

YARN 在启动 Container 前,需要先把应用依赖的文件准备到运行节点上,这个过程叫资源本地化。被本地化的文件称为 LocalResource。

LocalResource 通常包含应用 jar 包、配置文件、归档文件或脚本。它有几个重要属性:

  1. 类型:文件、归档包或模式匹配资源。
  2. 可见性:PUBLIC、PRIVATE 或 APPLICATION。
  3. 时间戳:用于判断资源是否发生变化。
  4. 大小:用于校验和资源管理。

NodeManager 会负责下载这些资源,并放到 Container 的工作目录中。这样用户任务启动时,就可以直接读取本地文件,而不需要每个任务自己去 HDFS 或其他存储系统拉取依赖。

9. 小结

YARN 的核心思想是把集群资源管理拆成几个明确的角色:

  1. ResourceManager 管全局资源和应用入口。
  2. NodeManager 管单个节点上的资源和 Container。
  3. ApplicationMaster 管单个应用的生命周期。
  4. Container 表示一次具体的资源分配。

理解 YARN 的核心在于理解职责边界,而不只是记住组件名称。理解这些边界后,再看 Spark、Flink、MapReduce 等框架运行在 YARN 上的流程,就会清楚很多:YARN 只提供资源管理和调度能力,真正的计算逻辑仍然由上层计算框架自己完成。


文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
  目录