理解 YARN 架构,不能仅用 ResourceManager、NodeManager、ApplicationMaster、Container 四个组件框图来理解。更有效的理解方式,是分析一个应用从提交到结束的生命周期:客户端把应用交给 ResourceManager,ResourceManager 通过调度器分配第一个 Container 启动 ApplicationMaster,ApplicationMaster 再继续申请资源,NodeManager 在具体节点上启动并管理 Container,最后应用完成、日志聚合、状态写回。
YARN 的核心设计体现在两个方面。第一,ResourceManager 不参与应用执行细节,它只负责集群级资源和应用生命周期。第二,ApplicationMaster 是按应用启动的应用级调度与执行协调器,它知道自己这个应用需要多少任务、如何拆分任务、如何处理失败、如何提交输出。YARN 的价值就在这里:把资源管理和计算框架拆开,让 MapReduce、Spark、Flink、Tez 等框架都可以在同一套资源管理层上运行。
本篇继续使用单机伪分布式环境,并提交了一个 MapReduce Pi 示例任务:
Application ID: application_1738138872752_0001
Job ID: job_1738138872752_0001
Application: QuasiMonteCarlo
Type: MAPREDUCE
Queue: root.default
State: FINISHED
FinalStatus: SUCCEEDED
LogAggregation: SUCCEEDED
这不是为了讨论 Pi 计算结果,而是用一个真实完成的 YARN 应用,把架构中的几个角色串起来看。
1. YARN 架构的核心角色
1.1 YARN 架构的基本分层
YARN 可以先拆成四个层次:
| 层次 | 代表对象 | 负责什么 |
|---|---|---|
| 集群管理层 | ResourceManager | 接收应用、维护节点、调度资源、管理应用状态 |
| 节点执行层 | NodeManager | 注册节点、汇报资源、启动 Container、管理本地目录和日志 |
| 应用协调层 | ApplicationMaster | 为单个应用申请资源、跟踪任务、处理失败和完成提交 |
| 资源执行层 | Container | 承载具体进程,包含内存、vCore、环境变量、本地资源和日志 |
这四层的边界非常重要。ResourceManager 是全局的,一个集群通常只有一个活动 RM;NodeManager 是每台工作节点上的代理;ApplicationMaster 不是常驻进程,而是每个应用运行时启动的应用级协调者;Container 是一次资源分配对应的运行上下文,包含资源、启动命令、环境变量和本地化资源等信息。
可以把一次应用运行简化成下面这条链路:
Client
-> ResourceManager 提交 Application
-> Scheduler 分配 AM Container
-> NodeManager 启动 ApplicationMaster
-> ApplicationMaster 向 ResourceManager 申请更多 Container
-> NodeManager 启动任务 Container
-> ApplicationMaster 跟踪任务并汇报最终状态
-> NodeManager 聚合日志,ResourceManager 记录应用结果
这里有一个容易混淆的点:ResourceManager 不直接运行 Map 任务,也不直接运行 Reduce 任务。它只决定资源分给谁,真正启动进程的是 NodeManager,真正理解 MapReduce 作业拆分逻辑的是 MapReduce ApplicationMaster。
下面是 ResourceManager 的总览页面。这个页面展示了集群指标、调度器类型、节点数量和应用列表。application_1738138872752_0001 已经处于 FINISHED / SUCCEEDED,说明一次完整的 YARN 应用生命周期已经结束。

1.2 ResourceManager:集群级资源和生命周期入口
ResourceManager 是 YARN 的中心入口,但它不是所有事情都管。它的职责可以拆成几类:
| 职责 | 说明 |
|---|---|
| 接收应用 | 客户端通过 YARN Client 提交应用,RM 创建 Application 记录 |
| 分配资源 | 调度器根据队列、资源、优先级、本地性等条件分配 Container |
| 维护节点 | 通过 NodeManager 心跳感知节点状态、资源和健康情况 |
| 管理 AM | 分配第一个 Container 给 ApplicationMaster,并接收 AM 注册 |
| 记录状态 | 跟踪 Application 的状态、最终结果、诊断信息和资源消耗 |
| 提供接口 | Web UI、REST API、命令行都围绕 RM 状态展开 |
在应用详情 REST 返回中,这次任务的关键字段如下:
{
"id": "application_1738138872752_0001",
"user": "root",
"name": "QuasiMonteCarlo",
"queue": "root.default",
"state": "FINISHED",
"finalStatus": "SUCCEEDED",
"applicationType": "MAPREDUCE",
"logAggregationStatus": "SUCCEEDED",
"amHostHttpAddress": "lavm-bzoq5mwl1h:8042",
"masterNodeId": "lavm-bzoq5mwl1h:40331"
}
这些字段正好对应架构里的几个对象。queue 说明应用进入了哪个调度队列;applicationType 说明这是 MapReduce 应用;amHostHttpAddress 是 AM 所在 NodeManager 的 Web 地址,通常也是查看 AM Container 日志的入口;masterNodeId 是 ResourceManager 记录的 AM 所在 NodeManager 节点标识;logAggregationStatus 说明应用结束后日志聚合完成。
ResourceManager 最重要的设计取舍,是它不把应用逻辑塞到自己内部。RM 可以知道某个应用需要资源,也可以知道它成功或失败,但它不理解 MapReduce 有多少个 split,不理解 Spark 有多少个 executor,也不理解 Flink 的 job graph。这些都交给对应框架自己的 ApplicationMaster 或等价组件处理。
这种拆分带来两个好处。第一,ResourceManager 的全局职责更稳定,不会随着计算框架变化而频繁变化。第二,不同计算框架可以在 YARN 上独立演进,只要遵守 YARN 的资源申请和 Container 启动协议即可。
但它也带来一个排查要求:看到应用失败时,不能只看 RM 页面。RM 只能告诉我们应用生命周期状态,真正的失败原因通常在 ApplicationMaster 日志、Container 日志或框架自己的日志中。
1.3 调度器:资源分配发生在队列和节点之间
ResourceManager 内部最容易影响业务体验的是调度器。测试环境使用 Capacity Scheduler,只有 root.default 一个队列,所以页面很简单。但在生产环境中,调度器决定了资源如何在用户、队列和节点之间流动。
调度器至少要处理这些问题:
| 问题 | 调度器需要判断什么 |
|---|---|
| 谁能提交 | 队列 ACL、用户组、应用状态 |
| 谁先拿资源 | 队列容量、优先级、提交顺序、公平性 |
| 拿多少资源 | Container 内存、vCore、AM 资源比例、最大应用数 |
| 在哪里运行 | 节点可用资源、数据本地性、节点标签、健康状态 |
| 是否继续等待 | 队列是否有可用资源,节点是否满足申请条件 |
| 是否抢占资源 | 是否启用 preemption,是否需要从低优先级队列或应用回收资源 |
下面的 Scheduler 页面展示了 root.default 队列和应用记录。虽然只有一个队列,但仍然能看到 Capacity Scheduler 的基本信息:队列容量、最大容量、应用状态、AM 资源、已用资源和应用列表。

在 YARN 架构里,调度器不是简单地“找一台空机器”。ApplicationMaster 向 RM 提交的是资源请求,里面可能包含 memory、vCore、优先级、节点本地性、机架本地性、资源名称等信息。调度器要在队列策略和节点资源之间做匹配,匹配成功后返回 Container 分配结果。如果启用了抢占机制,调度器还可能根据队列保障容量和优先级回收部分资源。
这解释了一个常见现象:应用已经提交成功,但状态长期停在 ACCEPTED。这通常不是客户端提交失败,而是 ApplicationMaster 的第一个 Container 还没有分配到。可能原因包括队列排队、AM 资源不足、AM 资源比例受限、本地性限制、节点标签不匹配、单个 Container 申请资源超过节点上限。排查这类问题,要先看 Scheduler 和 Nodes 页面,而不是直接去找任务日志。
Capacity Scheduler 里还要区分 capacity 和 maximum-capacity。capacity 是队列的保障容量,表示队列在资源竞争时应该获得的份额;maximum-capacity 是队列最多可以借用到的上限。前者影响保障,后者影响弹性,两者配置冲突会直接影响应用排队和资源借用。
1.4 NodeManager:每台机器上的执行代理
NodeManager 是节点层的核心。它不会决定全局资源策略,但它决定某台机器能不能可靠地运行 Container。
NodeManager 的职责包括:
- 向 ResourceManager 注册节点。
- 周期性发送心跳,汇报节点健康状态和可用资源。
- 根据 RM/AM 的指令启动 Container。
- 准备 Container 本地运行目录、依赖资源和环境变量。
- 管理 Container 日志目录和日志聚合。
- 在 Container 结束后清理本地资源。
下面的 Nodes 页面显示单节点测试环境里 lavm-bzoq5mwl1h 处于 RUNNING,ResourceManager 能看到节点的 HTTP 地址、资源、Container 数量和健康状态。

NodeManager 的架构价值,在于把“节点细节”从 ResourceManager 中隔离出去。RM 不需要直接登录某台机器启动进程,也不需要管理某个 Container 的本地目录。RM 只需要知道节点还活着、资源还有多少、是否健康;具体的进程启动、资源本地化(localization)、环境准备、日志写入和本地清理由 NodeManager 执行。
这也是为什么 YARN 排查要重视 NodeManager。RM 页面显示节点 RUNNING,只说明节点注册正常;Container 是否能启动,还要看本地目录、权限、Classpath、环境变量和日志目录。比如下面这些问题,大多发生在 NodeManager 这一层:
| 现象 | 更可能的问题层 |
|---|---|
| 节点没有显示于 RM Nodes 页面 | NM 未启动、RM 地址错误、网络或主机名问题 |
| 节点显示 UNHEALTHY | 本地目录不可写、磁盘异常、健康检查失败 |
| AM Container 启动失败 | Java 路径、Classpath、资源本地化、权限问题 |
| 任务日志缺失 | 日志目录、日志聚合、HDFS 远程日志目录问题 |
| 某台机器任务集中失败 | 节点环境差异、本地磁盘或依赖问题 |
单机环境不容易暴露多节点差异,因为所有服务都在一台机器上。多节点环境里,NodeManager 是最容易体现机器差异的组件。某台机器 JVM 版本不一致、目录权限不一致、磁盘满、磁盘 IO 抖动、hostname/DNS 解析异常,都可能表现为 Container 启动失败。
1.5 ApplicationMaster:每个应用自己的协调者
ApplicationMaster 是 YARN 架构里最关键的解耦点。它不是集群级服务,而是每个应用运行时启动的应用级调度与执行协调器。MapReduce 有自己的 MRAppMaster,负责 Map/Reduce 任务编排;Spark on YARN 通常由 AM 承载 Driver 或协调 Driver 运行;Flink on YARN 则由 AM 启动和管理 Flink 集群入口,例如 JobManager/TaskManager 相关进程。
ApplicationMaster 的典型职责包括:
| 职责 | 说明 |
|---|---|
| 注册自己 | 启动后向 ResourceManager 注册,表示应用协调者已经可用 |
| 申请资源 | 根据应用计划向 RM 申请 Container |
| 处理分配 | 接收 RM 返回的 Container 分配结果 |
| 启动任务 | 联系 NodeManager,在指定 Container 中启动任务进程 |
| 跟踪状态 | 记录任务成功、失败、重试和进度 |
| 完成应用 | 应用结束后向 RM 注销并提交最终状态 |
在 MapReduce Pi 示例里,MRAppMaster 会先读取输入 split,再申请 Map Task Container 和 Reduce Task Container。任务日志中可以看到这次作业启动了 8 个 Map Task 和 1 个 Reduce Task:
Launched map tasks=8
Launched reduce tasks=1
Data-local map tasks=8
Failed Shuffles=0
Merged Map outputs=8
这些信息不是 ResourceManager 计算出来的,而是 MapReduce 框架自己的运行结果。RM 负责把资源分出去,MRAppMaster 负责把这些资源组织成 MapReduce 作业。
从排查角度看,ApplicationMaster 是应用层和资源层的分界点。如果应用一直没有 AM,通常要看调度器和队列;如果 AM 已经启动但后续任务失败,就要看 AM 日志和具体 Container 日志;如果 AM 自己失败,则应用可能被重试或直接失败。
下面的应用详情页面展示了 application_1738138872752_0001 的完整状态。这里能看到 Application Type、Queue、FinalStatus、StartedTime、ElapsedTime、ApplicationMaster、Allocated Containers 等信息。它比总览页更适合解释“一个应用在 YARN 里到底有哪些元数据”。

1.6 Container:资源分配的最终执行单元
Container 是 YARN 里的资源执行单元。它可以理解成一次资源分配结果,但不能简单等同于 Docker 容器。YARN Container 描述的是一组资源和运行上下文,典型内容包括:
- 内存和 vCore。
- Container ID。
- 运行命令。
- 环境变量。
- 本地化资源。
- 标准输出和错误日志。
- 所在 NodeManager。
从日志角度看,Container 通常会产生 stdout、stderr 和 syslog 等日志。stdout 更适合看用户程序主动输出,stderr 常见于异常堆栈和错误输出,syslog 则经常包含 YARN 框架、启动脚本和运行环境相关信息。排查时不要只看其中一个文件。
ApplicationMaster 本身运行在一个 Container 中,Map Task 和 Reduce Task 也运行在各自的 Container 中。对于 ResourceManager 来说,Container 是可调度的资源单位;对于 NodeManager 来说,Container 是需要启动、监控和清理的本地进程;对于 ApplicationMaster 来说,Container 是执行任务的承载单元。
这次应用详情里能看到 AM 日志地址指向 NodeManager:
amHostHttpAddress: lavm-bzoq5mwl1h:8042
amContainerLogs: http://lavm-bzoq5mwl1h:8042/node/containerlogs/...
这说明 AM Container 的日志不是从 ResourceManager 机器上读取的,而是由运行该 Container 的 NodeManager 提供入口,并在应用结束后通过日志聚合写入 HDFS。前一篇文章里已经强调过日志聚合,这里可以从架构上再确认一次:日志属于 Container 运行现场,最终需要 NodeManager 和 HDFS 把它保存下来。
Container 失败时,也要按边界排查。RM 负责分配资源,但不负责解释业务进程为什么退出;NM 负责启动进程,但不一定知道业务代码为什么抛异常;AM 负责应用逻辑,才最接近框架层失败原因。因此排查路径通常是:
RM 应用状态
-> AM 是否启动
-> Container 分配记录
-> NodeManager 日志
-> Container stdout/stderr/syslog
-> 框架自己的错误信息
如果直接从 RM 页面跳到“重启 YARN”,很容易把应用层错误误判成集群层错误。
2. 运行链路和排查边界
2.1 一次 MapReduce 应用在 YARN 中的完整过程
把前面的组件串起来,MapReduce Pi 示例在 YARN 中大致经历下面这些步骤:
1. 客户端提交作业到 ResourceManager。
2. ResourceManager 创建 Application 记录。
3. Scheduler 为 ApplicationMaster 分配第一个 Container。
4. NodeManager 启动 MRAppMaster。
5. MRAppMaster 向 ResourceManager 注册。
6. MRAppMaster 根据输入 split 申请 Map Container。
7. ResourceManager 根据队列、资源和本地性返回 Container。
8. NodeManager 启动 Map Task Container。
9. Map 输出完成后,Reduce Task 拉取 Map 输出,完成 fetch、merge、sort 后执行 Reduce 聚合。
10. MRAppMaster 汇总任务状态,向 ResourceManager 汇报完成。
11. NodeManager 聚合日志,ResourceManager 将应用标记为 FINISHED/SUCCEEDED。
如果启用了推测执行(speculative execution),MapReduce 还可能为慢任务启动额外尝试。最终只采用最先成功的 attempt,其他 attempt 会被杀掉。这样可以缓解个别慢节点或慢任务拖慢整体作业的问题,但也会增加额外资源消耗。
这条流程解释了很多 YARN 状态的含义:
| 状态或现象 | 架构含义 |
|---|---|
| SUBMITTED | 客户端已经提交,RM 收到应用 |
| ACCEPTED | 应用已进入队列,等待 AM Container |
| RUNNING | AM 已启动,应用正在协调任务 |
| FINISHED / SUCCEEDED | AM 正常完成并向 RM 提交成功状态 |
| FINISHED / FAILED | 应用结束,但最终结果失败 |
| KILLED | 应用被用户、管理员或策略终止 |
这比单纯记状态名更有用。比如 ACCEPTED 长时间不动,应该优先看调度器和队列;RUNNING 后失败,应该优先看 AM 和 Container 日志;SUCCEEDED 但看不到历史详情,则要看 JobHistoryServer 或日志聚合链路。
还要注意,FINISHED 只是生命周期状态,不等于成功。是否成功要看 finalStatus,例如 SUCCEEDED、FAILED 或 KILLED。KILLED 的原因也不只有用户主动 kill,还可能来自超时、队列策略、管理员操作或 AM 重试超过限制。
2.2 架构边界对排查很重要
YARN 的组件边界越清楚,排查越不容易乱。
第一,RM 问题通常表现为所有应用都受影响。比如提交变慢、队列不调度、节点全部丢失、RM Web UI 不可用。这类问题要看 ResourceManager 日志、调度器、状态存储和 RM HA。
第二,NM 问题通常表现为某些节点上的 Container 失败。比如某台机器 UNHEALTHY、某些 Container 启动失败、日志目录不可写、本地磁盘满。这类问题要看 NodeManager 日志、节点健康报告、本地目录和机器环境。
第三,AM 问题通常表现为某个应用无法推进。比如 AM 启动后退出、任务重试过多、资源申请不合理、应用最终失败。这类问题要看 ApplicationMaster 日志和框架自己的诊断信息。
第四,Container 问题通常更接近具体任务。比如 Map Task OOM、Reduce Shuffle 失败、Classpath 缺失、业务代码异常。这类问题要看 Container 的 stdout、stderr、syslog,以及框架生成的错误。
可以把排查入口整理成一张表:
| 入口 | 适合回答的问题 |
|---|---|
| ResourceManager 总览 | 应用是否提交、节点是否可用、队列是否有资源 |
| Scheduler 页面 | 队列容量、AM 资源、应用是否排队 |
| Nodes 页面 | NodeManager 是否 RUNNING,节点是否健康 |
| Application 详情 | AM、状态、队列、诊断信息、资源消耗 |
| yarn logs | AM 和 Container 的实际运行日志 |
| NodeManager 本地日志 | Container 启动和本地目录问题 |
如果把日志入口按层次拆开,可以这样理解:
| 日志入口 | 主要内容 | 常见用途 |
|---|---|---|
| ResourceManager 日志 | 调度、队列、ACL、AM 分配 | 判断是否是集群级或调度问题 |
| ApplicationMaster 日志 | 资源申请、任务调度、失败重试 | 判断单个应用为什么无法推进 |
| NodeManager 日志 | Container 启动、本地化、目录和聚合 | 判断某个节点为什么启动失败 |
| Container 日志 | stdout、stderr、syslog | 判断用户进程或框架任务为什么失败 |
实际排查时可以按 RM -> AM -> NM -> Container 的顺序收敛问题。先判断是否是全局调度问题,再看应用级协调,再看节点执行,最后进入具体任务日志。
这也是写架构文章时最应该留下的内容:组件名不是重点,组件之间的责任边界才是重点。
3. 架构细节和扩展能力
3.1 几个容易被忽略的架构细节
除了四个核心角色,还有几个细节会直接影响 YARN 的稳定性和可排查性。
第一个细节是 ResourceManager 状态。RM 不是只在内存里维护应用列表,它还需要记录应用状态、尝试次数、队列状态和恢复信息。单机环境没有启用 RM HA,看不出状态存储的重要性;生产环境里如果要支持 RM 故障恢复,就必须考虑状态存储、ZooKeeper、恢复策略和应用重试行为。否则 RM 重启后,应用是否还能恢复、AM 是否需要重新启动、客户端看到什么状态,都会变成不确定问题。
第二个细节是心跳。NodeManager 和 ApplicationMaster 都不是被 RM 持续远程控制的。NodeManager 通过心跳把节点状态、Container 状态和资源情况上报给 RM;ApplicationMaster 也通过协议向 RM 申请资源、释放资源、接收分配结果。心跳间隔决定了状态变化被 RM 感知的速度。节点已经故障但 RM 还没标记 LOST、Container 已经结束但页面上仍显示运行中,很多时候都和心跳、超时、状态同步有关。
第三个细节是资源本地化。Container 启动前,NodeManager 要把应用依赖、配置文件、jar 包、缓存资源放到本地目录,并设置好环境变量。很多应用失败并不是因为资源不够,而是资源本地化失败,例如 HDFS 上的依赖不存在、本地目录不可写、权限不匹配、Classpath 拼错。这个阶段发生在 NodeManager 上,但错误通常会反映到 Container 日志里。
第四个细节是失败恢复。YARN 的失败恢复不是一个统一动作,而是分层发生的。Container 失败,ApplicationMaster 可以决定是否重试任务;ApplicationMaster 失败,ResourceManager 可以按配置重新拉起 AM attempt;NodeManager 丢失,RM 会把该节点上的 Container 标记为失败;ResourceManager 故障,则依赖 RM HA 和状态恢复。排查失败时要先判断是哪一层失败,不能把所有失败都理解成“作业失败”。
第五个细节是安全边界。客户端提交应用、AM 访问 HDFS、用户查看日志、队列限制提交权限,这些都不是同一个权限问题。单机环境为了方便使用 root 用户,但生产环境通常要配合 Kerberos、队列 ACL、代理用户、服务级授权和日志访问控制。YARN 架构把应用运行拆成多个进程和多个用户动作,安全配置也必须覆盖这些边界。
这些细节说明,YARN 架构不是一张静态图,而是一组状态机、RPC 协议和心跳机制共同组成的运行系统。只看 RM、NM、AM、Container 四个名词,很容易低估本地化、心跳、恢复和安全配置的复杂度。
3.2 还需要补充看的点
早期 YARN 资料通常会围绕 MapReduce on YARN 展开,这对理解 YARN 起点很有帮助。但在实际使用场景里,架构理解还要补充几个点。
第一,YARN 不只服务 MapReduce。MapReduce 是最容易验证的示例,但 YARN 的核心目标是让不同计算框架共享资源层。文章里用 Pi 示例,是因为它能稳定展示 AM、Container、Shuffle、日志聚合和应用状态,不代表 YARN 只适合 MapReduce。
第二,资源不只内存和 CPU。Hadoop 3.x 支持更丰富的资源模型,节点标签、自定义资源、GPU 等能力都围绕同一个思想展开:NodeManager 上报资源,ResourceManager 负责调度,ApplicationMaster 按需申请。单机环境不展开这些能力,但架构上要知道它们仍然落在 RM、NM、AM 的交互里。
第三,安全和多租户不是附加功能。队列 ACL、代理用户、Kerberos、服务级授权会影响客户端能不能提交、AM 能不能访问 HDFS、用户能不能查看日志。测试环境用 root 用户简化了这些问题,生产环境不能这样处理。
第四,历史和日志是架构闭环的一部分。应用完成不代表管理结束。没有日志聚合、没有历史记录、没有诊断信息,应用失败后就很难复盘。YARN 架构把运行时状态、日志和历史入口拆在不同组件上,管理时必须把它们连起来。
第五,Web UI 只是架构状态的一个投影。RM 页面能看到应用和节点,Scheduler 页面能看到队列,NodeManager 页面能看到节点本地信息,但这些页面都不是完整事实本身。更可靠的做法是把 Web UI、REST API、命令输出和日志放在一起看。比如应用详情里 state=FINISHED、finalStatus=SUCCEEDED、logAggregationStatus=SUCCEEDED 同时成立,才说明这个应用在资源、运行和日志三个层面都完成了闭环。
第六,YARN 的抽象会把问题延后暴露。客户端提交应用时,只是把运行计划交给 RM;AM 启动后,才会申请更多资源;任务 Container 启动后,才会暴露依赖和运行环境问题。因此应用提交成功不代表整体成功,AM 启动成功也不代表任务成功。架构上每推进一层,才会验证下一层的条件。
4. 小结
YARN 架构可以概括成一句话:四个核心角色、调度器和心跳机制共同驱动应用生命周期。ResourceManager 管全局资源,NodeManager 管节点执行,ApplicationMaster 管单个应用,Container 承载具体任务。
但这句话还不够。更准确的理解是:
- ResourceManager 只做集群级资源和生命周期管理,不理解应用内部细节。
- NodeManager 是节点代理,负责启动、监控、清理 Container,并处理本地目录和日志。
- ApplicationMaster 是每个应用自己的协调者,是 YARN 解耦计算框架的关键。
- Container 是资源分配和任务运行的交汇点,不是某个固定服务。
- 调度器连接队列策略和节点资源,决定应用什么时候、在哪里拿到资源。
- 日志聚合和应用详情决定任务完成后还能不能复盘。
通过 application_1738138872752_0001 这次验证,可以看到 YARN 架构不是静态组件图,而是一条由状态机、RPC 和心跳机制串起来的运行链路。只要沿着客户端、ResourceManager、ApplicationMaster、NodeManager、Container、日志这条线看,很多状态和故障就能定位到具体层次,而不是把所有问题都归到“YARN 出问题了”。