YARN 管理不只是查看 Web UI 状态。真正的管理对象是 Application 生命周期链路:ResourceManager 接收应用,Scheduler 分配资源,NodeManager 管理 Container 生命周期,ApplicationMaster 作为应用级协调器调度任务,日志聚合到 HDFS,JobHistoryServer 保留历史记录。任何一个环节断掉,用户看到的都可能只是一个简单的 FAILED 或长时间 ACCEPTED。
我把 YARN 管理拆成几个最小问题:
- 集群服务是否健康。
- ResourceManager 是否能看到 NodeManager。
- 调度器和队列是否按预期工作。
- 应用、Container 和日志是否能追踪。
- 配置变更后是否能在线刷新。
- JVM 和进程问题如何定位。
这些问题比某个具体监控工具更稳定。部署和监控工具会变化,但 ResourceManager、NodeManager、队列、Application、Container、日志这些管理对象相对稳定。集群管理也不是看一个页面是否能打开,而是要把进程、节点、资源、队列、作业和日志连起来看。
本文仍然使用前一篇部署的单机伪分布式环境,并提交了一个 MapReduce Pi 示例任务:
application_1737508641558_0001
job_1737508641558_0001
这个任务后面会作为 YARN 管理页面和日志命令的验证对象。
1. 管理对象和配置基础
1.1 YARN 管理到底在管什么
YARN 管理可以分成四层。
| 管理层 | 关注对象 | 常见入口 |
|---|---|---|
| 进程层 | ResourceManager、NodeManager、JobHistoryServer | jps、systemd、日志文件 |
| 节点层 | NodeManager 状态、资源、健康检查 | yarn node -list、ResourceManager Nodes 页面 |
| 调度层 | 队列、资源分配、调度器策略 | Scheduler 页面、yarn rmadmin -refreshQueues |
| 应用层 | Application、ApplicationMaster、Container、日志 | yarn application、yarn logs、JobHistoryServer |
这四层不能割裂看。比如 ResourceManager 进程存在,不代表集群能跑任务;NodeManager 处于 RUNNING,也不代表队列配置合理;MapReduce 作业显示 SUCCEEDED,也不代表日志聚合和历史服务一定正常。
因此,管理 YARN 时我会按下面的顺序检查:
进程是否存在
-> 节点是否注册
-> 资源是否可用
-> 队列是否正常
-> 应用是否能提交
-> Container 日志是否能追踪
这条检查链比单纯记住某个管理工具更重要。
这里先把几个对象边界说清楚。ResourceManager 不只是维护节点信息,它还负责应用接入、调度器交互、队列管理和 Container 分配。NodeManager 不参与全局调度决策,但负责本节点 Container 的启动、停止、监控、日志和本地资源清理。ApplicationMaster 不是通用“控制进程”,而是应用级协调器,负责向 ResourceManager 申请资源,并协调 NodeManager 启动具体任务。Container 也不是一个具体进程,它是资源、启动上下文和运行环境的组合,最终由 NodeManager 在这个上下文里启动用户进程。
1.2 脚本配置:仍然要理解配置文件
自动化脚本本身不是重点,重点是脚本最终修改了哪些配置文件、启动了哪些服务、刷新了哪些运行时状态。
YARN 管理相关配置主要仍然落在这些文件中:
| 文件 | 管理重点 |
|---|---|
| hadoop-env.sh | Java 环境、守护进程用户、JVM 参数 |
| core-site.xml | HDFS 默认入口、代理用户、通用配置 |
| hdfs-site.xml | NameNode/DataNode 目录、副本、权限 |
| yarn-site.xml | ResourceManager、NodeManager、资源、日志聚合 |
| mapred-site.xml | MapReduce on YARN、JobHistoryServer、任务内存 |
| capacity-scheduler.xml | Capacity Scheduler 队列和容量 |
前一篇已经整理过四个核心 XML 文件。本篇更关注管理过程中哪些配置可能需要刷新。
yarn rmadmin -help 中可以看到很多在线管理命令,其中最常见的是:
| 命令 | 作用 |
|---|---|
| -refreshQueues | 重新加载队列 ACL、状态和调度器配置 |
| -refreshNodes | 重新加载节点包含/排除列表,用于节点上下线 |
| -refreshNodesResources | 刷新 NodeManager 资源信息 |
| -refreshUserToGroupsMappings | 刷新用户到用户组映射 |
| -refreshSuperUserGroupsConfiguration | 刷新代理用户组配置 |
| -refreshAdminAcls | 刷新 ResourceManager 管理 ACL |
| -refreshServiceAcl | 刷新服务级授权策略 |
| -addToClusterNodeLabels | 添加集群节点标签 |
| -replaceLabelsOnNode | 给节点绑定标签 |
| -updateNodeResource | 更新指定节点的资源 |
这类命令的意义是:有些配置不需要重启整个集群就能生效。比如队列容量调整、节点下线、用户组映射刷新,如果每次都重启 ResourceManager,生产环境的影响会很大。
不过在线刷新也不是万能的。配置文件语法错误、调度器配置不一致、节点标签目录不可用,都可能导致刷新失败。管理命令执行后还要继续看 ResourceManager 日志和 Web UI,不应该只看命令是否返回 0。
这里需要区分“配置文件变更”和“运行时状态变更”。修改 capacity-scheduler.xml 只是把配置写到了磁盘上;执行 yarn rmadmin -refreshQueues 才是让 ResourceManager 尝试重新加载队列配置;刷新之后再看 Scheduler 页面和 RM 日志,才能确认配置真的被接受。很多集群事故不是因为命令不会执行,而是因为变更后没有验证运行时状态。
我更倾向于把 YARN 配置变更拆成下面四步:
修改配置文件
-> 做语法和容量关系检查
-> 执行对应的 refresh 命令
-> 用 Web UI、命令和日志确认结果
队列配置尤其不能只靠肉眼看。Capacity Scheduler 要求同一层级下的队列容量关系合理,父子队列容量不能互相矛盾,队列状态和 ACL 也要匹配业务预期。配置能被刷新,不代表策略合理;策略合理,也要通过一次真实应用提交来验证。
2. 核心组件管理
2.1 ResourceManager:YARN 管理的中心入口
ResourceManager 是 YARN 管理的中心。它负责接收应用、维护节点信息、分配 Container、调用调度器、记录应用状态。
ResourceManager 页面可以看到几个关键区域:
- Cluster Metrics
- Cluster Nodes Metrics
- Scheduler Metrics
- Applications

这张图里最值得看的是几个数字:
| 指标 | 当前值 | 含义 |
|---|---|---|
| Apps Submitted | 1 | 已提交应用数 |
| Apps Completed | 1 | 已完成应用数 |
| Apps Running | 0 | 当前没有运行中应用 |
| Active Nodes | 1 | 一个 NodeManager 正常注册 |
| Containers Running | 0 | 当前没有正在运行的 Container |
| Scheduler Type | Capacity Scheduler | 当前调度器类型 |
这里的 QuasiMonteCarlo 是 Pi 示例任务。状态为 FINISHED,FinalStatus 为 SUCCEEDED,说明应用生命周期已经完整结束。
ResourceManager 页面适合回答三个问题:
- 集群还有没有可用节点。
- 应用是否提交成功。
- 应用最终是成功、失败还是被杀掉。
如果应用提交不上来,先看 ResourceManager;如果应用提交成功但任务内部失败,再看 ApplicationMaster、Container 日志和 JobHistoryServer。
ResourceManager 页面还可以帮助判断问题发生在哪个阶段。应用一直停在 ACCEPTED,通常说明应用已经提交成功,但调度器还没有分配到 ApplicationMaster Container,常见原因是队列资源不足、AM 资源比例限制、节点标签不匹配、队列状态被停用。应用进入 RUNNING 后失败,则说明 AM 至少启动过,后续要看 AM 日志、任务日志和 JobHistory。应用直接 KILLED,则要确认是用户主动 kill、队列策略触发,还是管理员操作导致。
这里要避免两个误判。第一,ACCEPTED 不只表示“还没有分配 AM Container”,也可能是队列资源不足、AM 配额限制、节点标签不匹配或队列处于 STOPPED 状态。第二,RUNNING 只能说明 ApplicationMaster 已经启动或应用进入运行阶段,不代表 Map/Reduce Task、Spark Executor 或其他业务任务都在正常执行。
所以 ResourceManager 管理不能只盯着总览数字。应用状态、队列、用户、ApplicationType、StartTime、FinishTime 都应该一起看。尤其是在多租户环境里,同一时间可能有 Spark、MapReduce、Hive、Flink 等不同类型应用,RM 页面能先告诉我们“谁在占资源”“谁一直排队”“谁频繁失败”,再决定是否进入更细的日志排查。
2.2 NodeManager:节点管理不能只看进程
NodeManager 是 YARN 在每台机器上的代理进程。它负责向 ResourceManager 注册节点资源、启动 Container、管理本地目录和日志目录。
yarn node -list 是最直接的节点检查命令:
Total Nodes:1
Node-State: RUNNING
Node-Http-Address: lavm-bzoq5mwl1h:8042
ResourceManager 的 Nodes 页面能看到更完整的信息:

这张图里有几个管理字段比较重要:
| 字段 | 含义 |
|---|---|
| Node State | 节点状态,正常情况下为 RUNNING |
| Node Address | NodeManager RPC 地址 |
| Node HTTP Address | NodeManager Web 地址 |
| Last health-update | 最近健康检查更新时间 |
| Health-report | 健康检查报告 |
| Containers | 当前节点上的 Container 数量 |
| Mem Avail | 可用内存 |
| Vcores Used | 已使用 vCore |
NodeManager 状态异常时,不要只重启服务。更应该先判断是哪一类问题:
| 现象 | 可能原因 |
|---|---|
| 节点没有进入列表 | NodeManager 未启动、网络不通、RM 地址配置错误 |
| 节点 UNHEALTHY | 本地目录不可写、磁盘异常、健康检查脚本失败 |
| 节点 RUNNING 但不能分配 Container | 队列无资源、节点标签不匹配、资源配置过低 |
| Container 启动后很快失败 | 环境变量、Classpath、权限、本地目录问题 |
如果节点进入 UNHEALTHY,我会按优先级先查磁盘,再查权限,最后查网络和脚本。磁盘问题优先级最高,包括目录不可写、磁盘满、inode 满和坏盘;权限问题通常来自运行用户、目录属主或安全策略不一致;网络和健康检查脚本问题则更常出现在多节点环境。
单机环境中 NodeManager 和 ResourceManager 在一台机器上,所以网络问题不明显。多节点环境里,yarn.resourcemanager.hostname=localhost 这类单机配置如果没有改掉,其它节点会把 ResourceManager 当成本机,NodeManager 就无法正确注册。
NodeManager 管理里还有两个容易被低估的对象:本地目录和日志目录。
yarn.nodemanager.local-dirs 保存 Container 运行时的本地文件、缓存资源和中间数据;yarn.nodemanager.log-dirs 保存 Container 本地日志。两者生命周期不同:local-dirs 更偏运行时工作目录和中间数据,应用结束后通常可以被清理;log-dirs 保存本地日志,是否清理还取决于日志聚合和保留策略。它们通常应该放在数据盘或专门的本地目录中,并且要保证运行用户有读写权限。如果目录不可写,NodeManager 可能变成 UNHEALTHY;如果目录所在磁盘打满,Container 启动和日志聚合都会受影响。
因此节点健康检查不能只看 CPU 和内存。至少要把下面几类问题纳入巡检:
| 检查对象 | 典型风险 |
|---|---|
| 本地目录 | 不存在、不可写、磁盘满、inode 满 |
| 日志目录 | 日志持续增长、聚合失败、权限异常 |
| 环境变量 | Java、Hadoop 路径不一致 |
| 资源声明 | 声明资源超过机器可承受范围 |
| 主机名解析 | NodeManager 注册地址和 Web 地址不可达 |
单机环境里这些问题容易被“所有东西都在本机”掩盖。真正迁移到多节点时,NodeManager 是最先暴露环境差异的组件。
2.3 调度器:管理队列比管理应用更重要
YARN 的调度器决定资源怎么分配。默认使用 Capacity Scheduler。
Scheduler 页面可以看到队列树、资源容量、调度器运行时间,以及最近一次分配和释放 Container 的记录:

这张图中可以看到 root.default 队列。只有一个队列,看起来很简单,但生产环境中队列通常会拆成多个业务线或租户:
root
├── etl
├── ad_hoc
├── realtime
└── default
队列管理至少要关注这些内容:
| 管理项 | 说明 |
|---|---|
| capacity | 队列保证容量 |
| maximum-capacity | 队列最大可用容量 |
| state | 队列是否允许运行 |
| acl_submit_applications | 谁可以向队列提交应用 |
| acl_administer_queue | 谁可以管理队列 |
| maximum-applications | 队列最大应用数 |
| maximum-am-resource-percent | ApplicationMaster 最多可占队列资源比例 |
修改 capacity-scheduler.xml 后,通常不希望重启 ResourceManager,可以使用:
yarn rmadmin -refreshQueues
但刷新队列前应该先做两件事:
- 检查队列容量加起来是否为 100。
- 确认父子队列容量关系没有冲突。
刷新后再回到 Scheduler 页面确认队列树和容量是否生效。不要只看命令输出。
队列管理的难点不在创建队列,而在平衡“保障”和“共享”。capacity 表示队列的保障容量,maximum-capacity 表示队列最多可以借用多少资源。保障容量太保守,集群空闲资源会浪费;最大容量放得太宽,低优先级队列可能在高峰期挤压关键业务。YARN 调度器管理的核心,就是把这种冲突显式化。
一个常见配置冲突是同层级子队列的 capacity 加起来不是 100,或者某个队列的 maximum-capacity 小于自身 capacity。前者会导致调度器无法正确计算父队列资源,后者会让队列的保障容量和最大容量互相矛盾。队列不是目录结构,它本质上是一组资源、权限和调度策略的集合。
例如离线 ETL 队列可以有较大的最大容量,但要限制应用数量和 AM 占比,避免大量小任务把 ApplicationMaster 资源打满;临时查询队列可以限制单用户并发,避免某个用户提交过多任务;关键生产队列则需要更明确的 ACL 和容量保障。
在变更队列时,我会特别检查三件事:
- 队列容量调整是否会影响正在运行的任务。
- ACL 变更是否会导致已有用户无法提交作业。
- AM 资源比例是否会让大量小任务长期排队。
Scheduler 页面能提供一个直观确认,但真正的验收仍然应该提交一两个代表性任务,看它们是否进入预期队列、是否能拿到 Container、是否能正常完成。
2.4 节点上下线:refreshNodes 不是简单重启
集群扩容、缩容、维护机器时,会涉及节点上下线。YARN 中常见的入口是:
yarn rmadmin -refreshNodes
这个命令会让 ResourceManager 重新加载节点列表。实际使用时通常配合 include/exclude 文件,例如把某台机器加入排除列表,让 ResourceManager 不再向它分配新的 Container。
rmadmin 帮助中还能看到 graceful decommission 相关参数:
yarn rmadmin -refreshNodes -g [timeout] -client|server
它的目的不是立刻杀掉节点,而是给节点一个优雅下线窗口,让正在运行的 Container 尽量完成。
节点下线需要区分两件事:
- HDFS DataNode 下线。
- YARN NodeManager 下线。
这两个动作不是一回事。DataNode 下线关注数据块副本,NodeManager 下线关注正在运行的 Container。生产环境中如果一台机器同时承担 DataNode 和 NodeManager,维护前要同时规划 HDFS 和 YARN 两侧的下线流程。
一次比较稳妥的节点维护流程可以这样设计:
确认节点上是否有重要任务
-> 将节点加入 YARN exclude 列表
-> refreshNodes 并等待 Container 自然结束或迁移
-> 处理 HDFS DataNode 下线和副本补齐
-> 停止 NodeManager/DataNode
-> 做系统或硬件维护
-> 恢复服务并从 exclude 列表移除
-> 再次 refreshNodes 和检查节点状态
这个流程看起来比直接重启机器麻烦,但它能避免两个问题:一是正在运行的 Container 被突然杀掉,二是 HDFS 副本在维护窗口里处于不健康状态。对单机环境来说,这些步骤显得过重;对生产环境来说,这是降低维护风险的基本动作。
3. 日志、历史和运行时诊断
3.1 日志管理:先启用聚合,再谈排查
YARN 应用排查离不开日志。
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.nodemanager.remote-app-log-dir</name>
<value>/tmp/logs</value>
</property>
任务结束后,可以通过下面的命令读取聚合日志:
yarn logs -applicationId application_1737508641558_0001
这次 Pi 示例的日志输出里可以看到:
Container: container_1737508641558_0001_01_000002
LogAggregationType: AGGREGATED
LogType: directory.info
LogType: launch_container.sh
其中 launch_container.sh 很有价值。它会展示 Container 启动时的环境变量,例如:
JAVA_HOME
HADOOP_CONF_DIR
HADOOP_YARN_HOME
HADOOP_MAPRED_HOME
LOCAL_DIRS
LOG_DIRS
CONTAINER_ID
如果任务在 Container 启动阶段失败,这个脚本通常能暴露问题,比如 Java 路径不对、Classpath 缺失、本地目录权限异常、环境变量没有传进 Container。
因此,launch_container.sh 不只是“有价值”,它是排查 Container 启动环境的第一手证据。它适合用来检查环境变量、classpath、工作目录、LocalResource 展开结果,以及 MapReduce/Spark 这类框架最终传给 Container 的启动命令。
日志排查可以按下面的顺序来:
- ResourceManager 页面看应用状态、队列和调度阶段。
- ApplicationMaster 日志看应用级调度、任务重试和资源申请。
- NodeManager 日志看 Container 启动、本地目录和日志聚合。
- Container 日志看用户进程 stdout、stderr 和框架日志。
- JobHistoryServer 看 MapReduce 任务阶段和历史记录。
不要只盯着 Web 页面上的 FAILED。YARN 页面告诉我们“失败了”,日志才告诉我们“为什么失败”。
日志管理还要考虑保留周期。日志聚合把 NodeManager 本地日志汇总到 HDFS,但这不代表日志可以无限保留。任务量一大,/tmp/logs 或自定义远程日志目录会持续增长,占用 HDFS 空间。生产环境里应该明确:
- 应用日志保留多久。
- 哪些队列或用户的日志需要更长保留。
- 日志目录是否纳入容量告警。
- 是否需要把关键失败日志同步到外部日志平台。
我不建议安装阶段就把日志策略做得很复杂,但必须启用日志聚合并跑通 yarn logs。否则等任务失败时,只能登录到具体 NodeManager 机器上找本地日志,而 Container 可能已经清理,排查成本会明显上升。
3.2 JobHistoryServer:管理已完成的 MapReduce 作业
ResourceManager 更关注 YARN 应用生命周期,JobHistoryServer 更关注已完成的 MapReduce 作业。
本次示例任务可以在 JobHistoryServer 的作业列表里看到:

JobHistory 页面适合看这些信息:
| 信息 | 作用 |
|---|---|
| Submit Time | 作业提交时间 |
| Start Time | 作业真正开始运行的时间 |
| Finish Time | 作业完成时间 |
| Job ID | MapReduce 作业 ID |
| Queue | 作业所在队列 |
| State | 作业状态 |
| Maps/Reduces Completed | Map 和 Reduce 完成情况 |
它和 ResourceManager 的区别在于,ResourceManager 看到的是 YARN Application,JobHistoryServer 看到的是 MapReduce Job。JobHistory 不等同于 ResourceManager 状态,它只覆盖已完成或可被历史服务加载的 MapReduce 作业。对于 MapReduce 来说,一个 YARN Application 通常对应一个 MapReduce Job,但排查时仍然要分清这两个 ID:
Application ID: application_1737508641558_0001
Job ID: job_1737508641558_0001
使用 yarn logs 时需要 Application ID;在 JobHistoryServer 里查看 MapReduce 详情时通常使用 Job ID。
3.3 JVM 分析:从进程到 Container
Hadoop/YARN 是 JVM 进程集合,管理时不能只关注 Hadoop 命令,也要关注 JVM 层面的状态。
常见的 JVM 观察对象包括:
| 进程 | 关注点 |
|---|---|
| ResourceManager | 调度延迟、应用状态、队列计算、GC |
| NodeManager | Container 启动、日志聚合、本地目录、GC |
| NameNode | 元数据内存、GC、RPC 延迟 |
| JobHistoryServer | 历史任务加载、页面查询、GC |
| MapReduce ApplicationMaster | 作业状态机、任务重试、Container 申请 |
| Map/Reduce Task | 业务代码、Shuffle、排序、内存 |
可以先用 jps 找到进程:
jps
然后再按影响范围逐步深入。一般顺序是先用 jps 确认进程,再用 top 或 ps 判断 CPU、内存和运行时长,再用 jstack/jcmd Thread.print 看线程,最后在确实怀疑内存问题时使用 jmap 或 heap dump。
常用命令如下:
jps
top -p <pid>
jcmd <pid> VM.flags
jcmd <pid> GC.heap_info
jcmd <pid> Thread.print
jmap -histo <pid>
排查时要注意区分守护进程和任务进程。ResourceManager、NodeManager 是长期运行的守护进程;ApplicationMaster、Map Task、Reduce Task 是应用运行时创建的短生命周期进程。
如果一个任务已经结束,再去找它的 JVM 进程通常已经找不到了。此时应该看聚合日志和 JobHistory,而不是继续在机器上找进程。
JVM 排查也要分清“守护进程问题”和“应用问题”。ResourceManager GC 频繁,影响的是整个集群调度;NodeManager GC 或线程卡住,影响的是某个节点上的 Container 启动和日志聚合;ApplicationMaster 内存不足,影响的是单个应用的任务协调;Map/Reduce Task OOM,则更多是业务代码、输入数据倾斜或任务内存配置问题。
一个实用的判断方式是先看影响范围:
| 影响范围 | 优先怀疑对象 |
|---|---|
| 所有应用提交变慢 | ResourceManager、调度器、RM GC |
| 某台机器上的任务频繁失败 | NodeManager、本地目录、节点环境 |
| 某个应用的所有 Task 都失败 | ApplicationMaster、依赖包、配置 |
| 只有少数 Task 失败 | 数据倾斜、单个输入分片、业务代码 |
这比上来就 jstack 更有效。JVM 工具能提供细节,但先判断影响范围,才能知道应该抓哪个进程、哪个时间段、哪类日志。
3.4 Web UI、REST API 和外部监控的关系
外部管理和监控入口可以很多,我更倾向于把监控入口分为三类:
| 类型 | 例子 | 适合解决的问题 |
|---|---|---|
| Hadoop 内置 Web UI | RM、NM、JHS、NN 页面 | 快速查看状态和任务 |
| Hadoop 命令/REST API | yarn node、yarn logs、/ws/v1/cluster/metrics | 自动化巡检和脚本排查 |
| 外部监控系统 | Prometheus、Grafana、告警平台 | 长期趋势、告警、容量分析 |
内置 Web UI 适合现场排查,但不适合做长期监控。外部监控系统适合看趋势和告警,但不一定能直接回答某个 Container 为什么失败。
所以管理 YARN 时,不应该只选择一个工具。更合理的组合是:
- Web UI 用于快速定位。
- 命令行用于确认状态和拉日志。
- REST API 用于巡检脚本。
- 外部监控用于趋势和告警。
例如 /ws/v1/cluster/metrics 可以返回应用数量、节点数量、内存、vCore、Container 等指标。这个接口适合被巡检系统采集,但它不会替代 yarn logs。
监控指标还要有层次,也要区分“告警”和“分析”。告警指标用于快速发现服务不可用、节点丢失、队列堆积和日志聚合失败;分析指标用于看容量趋势、调度延迟、队列使用结构和应用失败模式。
集群层指标适合判断整体容量,例如 Active Nodes、Available Memory、Allocated Memory、Running Containers。队列层指标适合判断资源是否被某个队列占满。应用层指标适合判断任务是否失败、是否长期排队。节点层指标适合发现某台机器是否异常。
如果只采集集群层指标,会漏掉某个队列被打满的问题;如果只看应用失败数,又很难判断是不是节点故障导致的集中失败。比较合理的监控角度应该至少包含:
- ResourceManager 是否存活,HA 状态是否正常。
- Active/Lost/Unhealthy NodeManager 数量。
- 队列资源使用率、Pending 应用数、Pending Containers、Running 应用数。
- 应用失败率、AM 失败率、平均排队时间、平均运行时间。
- Scheduler Delay 或调度分配延迟。
- HDFS 日志目录容量和日志聚合失败数。
这些指标不一定都来自 YARN 自己的页面,但它们共同描述了 YARN 能不能持续稳定地接收和运行应用。
4. 一组实用的 YARN 管理命令
把本章内容落到命令上,我会先记住下面这些。
4.1 查看节点
yarn node -list
yarn node -list -all
yarn node -list -showDetails
yarn node -status <NodeId>
-states 可以按节点状态过滤:
yarn node -list -states RUNNING
yarn node -list -states UNHEALTHY,LOST
节点管理时最常见的误判是:只看 NodeManager 进程存在,却不看它有没有注册到 ResourceManager。最终要以 ResourceManager 看到的节点状态为准。
4.2 查看应用
yarn application -list
yarn application -list -appStates ALL
yarn application -status <ApplicationId>
应用状态至少要区分:
| State | FinalStatus | 含义 |
|---|---|---|
| RUNNING | UNDEFINED | 应用仍在运行 |
| FINISHED | SUCCEEDED | 应用正常完成 |
| FINISHED | FAILED | 应用运行失败 |
| FINISHED | KILLED | 应用被终止 |
State 是生命周期状态,FinalStatus 是最终结果。排查时两个都要看。
4.3 查看日志
yarn logs -applicationId <ApplicationId>
yarn logs -applicationId <ApplicationId> -containerId <ContainerId>
如果日志命令拿不到内容,先检查三件事:
- 是否启用了 yarn.log-aggregation-enable。
- HDFS 上的远程日志目录是否存在。
- 应用是否已经结束并完成日志聚合。
4.4 刷新管理配置
yarn rmadmin -refreshQueues
yarn rmadmin -refreshNodes
yarn rmadmin -refreshNodesResources
yarn rmadmin -refreshUserToGroupsMappings
yarn rmadmin -refreshSuperUserGroupsConfiguration
yarn rmadmin -refreshAdminAcls
这些命令是运维动作,不是普通查询。执行前要确认配置文件已经同步到 ResourceManager 所在节点,并且语法正确。
我会把管理命令分成两类:查询命令和变更命令。查询命令可以频繁执行,用于定位问题;变更命令会影响集群运行状态,必须有明确目标和回滚方案。
| 类型 | 命令例子 | 使用原则 |
|---|---|---|
| 查询 | yarn node -list、yarn application -status、yarn logs | 可以作为日常巡检和排查入口 |
| 变更 | refreshQueues、refreshNodes、updateNodeResource | 执行前确认配置,执行后验证效果 |
这个分类很重要。把 refreshQueues 当成普通查询随手执行,可能会把未完成的队列配置加载到线上;把 refreshNodes 当成无害命令执行,可能会触发节点下线流程。YARN 管理命令看起来都在 yarn 下面,但风险等级并不一样。
如果按风险再细分,refreshUserToGroupsMappings 这类用户组缓存刷新通常是低风险;refreshQueues 会改变调度策略,属于中风险;refreshNodes、refreshNodesResources 和 updateNodeResource 会影响节点可用性或容量判断,属于高风险操作。风险越高,越需要提前确认配置、保留回滚方案,并在执行后观察 RM 日志、Scheduler 页面和应用排队情况。
4.5 管理节点标签和资源
yarn rmadmin -addToClusterNodeLabels "gpu(exclusive=true)"
yarn rmadmin -replaceLabelsOnNode "node1:1234=gpu"
yarn rmadmin -updateNodeResource <NodeId> <MemSize> <vCores>
节点标签适合做资源隔离,比如 GPU 节点、SSD 节点、大内存节点。单机环境不需要展开,但生产环境里它是多租户资源管理的重要工具。
5. 环境边界
5.1 单机环境和生产环境的差异
本篇截图来自单机伪分布式环境,所以有几个限制要说明清楚。
第一,所有角色都在一台机器上,节点状态很简单。生产环境中 ResourceManager、NodeManager、DataNode 分布在多台机器上,网络、DNS、防火墙和主机名解析都会影响管理结果。
第二,测试环境没有 Kerberos。生产环境启用 Kerberos 后,命令行管理还会涉及 keytab、principal、代理用户和服务 ACL。
第三,测试环境只有 root.default 队列。生产环境往往有多个队列、多个用户组和多个资源池,capacity-scheduler.xml 的复杂度会明显提高。
第四,测试环境日志量很小。生产环境需要考虑日志保留周期、HDFS 空间、日志聚合延迟,以及日志查询带来的压力。
第五,测试环境没有 HA。生产环境中 ResourceManager HA、NameNode HA 和自动故障转移都会影响管理命令的执行方式。
尤其是 ResourceManager HA 场景,管理命令必须打到当前 Active ResourceManager,或者通过 HA 配置让客户端自动解析 Active RM。RM failover 期间,短时间内可能出现命令超时、应用状态查询不一致或刷新命令失败。生产脚本需要把重试、Active RM 识别和执行后校验一起设计进去。
因此,单机环境的价值不是模拟生产复杂度,而是把管理链路跑通:
NodeManager 注册
-> ResourceManager 调度
-> ApplicationMaster 申请 Container
-> Container 执行任务
-> 日志聚合到 HDFS
-> JobHistoryServer 展示历史
这条链路理解清楚之后,再看多节点、高可用、多队列、多租户,才不会迷失在工具细节里。
还有一个差异是安全模型。单机环境用 root 运行服务和提交任务,确实省事,但它会掩盖很多生产问题。生产环境通常需要独立的 Hadoop 服务用户、业务提交用户、用户组映射、代理用户配置、队列 ACL,启用 Kerberos 后还会引入 principal 和 keytab。很多“本机能跑”的命令,到了生产环境会因为身份和权限失败。
因此,测试环境里的管理结论要有边界:它适合验证 YARN 的对象关系和命令链路,不适合直接推导生产权限设计。真正上线前,还要把下面这些内容补齐:
- 服务运行用户和目录权限。
- 队列 ACL 和用户组映射。
- Kerberos 认证和 keytab 分发。
- ResourceManager、NameNode 的 HA。
- 节点维护、扩容、缩容流程。
- 日志保留和审计要求。
这些内容不影响单机环境跑通,但会决定生产集群能不能长期可管理。
6. 小结
YARN 管理的核心是建立一条排查链路:从进程到节点,从节点到队列,从队列到应用,从应用到 Container,再从 Container 回到日志和指标。
这篇文章最有价值的内容可以压缩成几句话:
- ResourceManager 是 YARN 管理入口,但不能只看 ResourceManager。
- NodeManager 是否 RUNNING,决定集群有没有地方运行 Container。
- Scheduler 页面和队列配置决定资源如何分配。
- JobHistoryServer 和 yarn logs 决定任务完成后能不能追踪。
- rmadmin 的刷新命令是生产管理的重要入口,但执行后必须验证结果。
- JVM 分析要区分守护进程和应用 Container。
管理 YARN 的核心不是记住某个监控页面,而是知道每个页面、命令和日志对应哪一个管理对象。对象关系清楚后,面对 ACCEPTED、FAILED、UNHEALTHY、日志缺失、队列拥塞这些问题,才能沿着 RM、NM、AM、Container 和日志链路逐层定位。