【YARN 权威指南】5. YARN 管理


YARN 管理不只是查看 Web UI 状态。真正的管理对象是 Application 生命周期链路:ResourceManager 接收应用,Scheduler 分配资源,NodeManager 管理 Container 生命周期,ApplicationMaster 作为应用级协调器调度任务,日志聚合到 HDFS,JobHistoryServer 保留历史记录。任何一个环节断掉,用户看到的都可能只是一个简单的 FAILED 或长时间 ACCEPTED。

我把 YARN 管理拆成几个最小问题:

  1. 集群服务是否健康。
  2. ResourceManager 是否能看到 NodeManager。
  3. 调度器和队列是否按预期工作。
  4. 应用、Container 和日志是否能追踪。
  5. 配置变更后是否能在线刷新。
  6. 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 页面可以看到几个关键区域:

  1. Cluster Metrics
  2. Cluster Nodes Metrics
  3. Scheduler Metrics
  4. Applications

ResourceManager 页面,展示集群指标和 MapReduce 应用状态

这张图里最值得看的是几个数字:

指标 当前值 含义
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 页面适合回答三个问题:

  1. 集群还有没有可用节点。
  2. 应用是否提交成功。
  3. 应用最终是成功、失败还是被杀掉。

如果应用提交不上来,先看 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 页面能看到更完整的信息:

ResourceManager Nodes 页面,显示单节点 NodeManager 处于 RUNNING 状态

这张图里有几个管理字段比较重要:

字段 含义
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 的记录:

Capacity Scheduler 页面,展示 root.default 队列和 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

但刷新队列前应该先做两件事:

  1. 检查队列容量加起来是否为 100。
  2. 确认父子队列容量关系没有冲突。

刷新后再回到 Scheduler 页面确认队列树和容量是否生效。不要只看命令输出。

队列管理的难点不在创建队列,而在平衡“保障”和“共享”。capacity 表示队列的保障容量,maximum-capacity 表示队列最多可以借用多少资源。保障容量太保守,集群空闲资源会浪费;最大容量放得太宽,低优先级队列可能在高峰期挤压关键业务。YARN 调度器管理的核心,就是把这种冲突显式化。

一个常见配置冲突是同层级子队列的 capacity 加起来不是 100,或者某个队列的 maximum-capacity 小于自身 capacity。前者会导致调度器无法正确计算父队列资源,后者会让队列的保障容量和最大容量互相矛盾。队列不是目录结构,它本质上是一组资源、权限和调度策略的集合。

例如离线 ETL 队列可以有较大的最大容量,但要限制应用数量和 AM 占比,避免大量小任务把 ApplicationMaster 资源打满;临时查询队列可以限制单用户并发,避免某个用户提交过多任务;关键生产队列则需要更明确的 ACL 和容量保障。

在变更队列时,我会特别检查三件事:

  1. 队列容量调整是否会影响正在运行的任务。
  2. ACL 变更是否会导致已有用户无法提交作业。
  3. 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 尽量完成。

节点下线需要区分两件事:

  1. HDFS DataNode 下线。
  2. 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 的启动命令。

日志排查可以按下面的顺序来:

  1. ResourceManager 页面看应用状态、队列和调度阶段。
  2. ApplicationMaster 日志看应用级调度、任务重试和资源申请。
  3. NodeManager 日志看 Container 启动、本地目录和日志聚合。
  4. Container 日志看用户进程 stdout、stderr 和框架日志。
  5. JobHistoryServer 看 MapReduce 任务阶段和历史记录。

不要只盯着 Web 页面上的 FAILED。YARN 页面告诉我们“失败了”,日志才告诉我们“为什么失败”。

日志管理还要考虑保留周期。日志聚合把 NodeManager 本地日志汇总到 HDFS,但这不代表日志可以无限保留。任务量一大,/tmp/logs 或自定义远程日志目录会持续增长,占用 HDFS 空间。生产环境里应该明确:

  1. 应用日志保留多久。
  2. 哪些队列或用户的日志需要更长保留。
  3. 日志目录是否纳入容量告警。
  4. 是否需要把关键失败日志同步到外部日志平台。

我不建议安装阶段就把日志策略做得很复杂,但必须启用日志聚合并跑通 yarn logs。否则等任务失败时,只能登录到具体 NodeManager 机器上找本地日志,而 Container 可能已经清理,排查成本会明显上升。

3.2 JobHistoryServer:管理已完成的 MapReduce 作业

ResourceManager 更关注 YARN 应用生命周期,JobHistoryServer 更关注已完成的 MapReduce 作业。

本次示例任务可以在 JobHistoryServer 的作业列表里看到:

JobHistory 作业列表,展示 MapReduce 示例任务记录

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 时,不应该只选择一个工具。更合理的组合是:

  1. Web UI 用于快速定位。
  2. 命令行用于确认状态和拉日志。
  3. REST API 用于巡检脚本。
  4. 外部监控用于趋势和告警。

例如 /ws/v1/cluster/metrics 可以返回应用数量、节点数量、内存、vCore、Container 等指标。这个接口适合被巡检系统采集,但它不会替代 yarn logs。

监控指标还要有层次,也要区分“告警”和“分析”。告警指标用于快速发现服务不可用、节点丢失、队列堆积和日志聚合失败;分析指标用于看容量趋势、调度延迟、队列使用结构和应用失败模式。

集群层指标适合判断整体容量,例如 Active Nodes、Available Memory、Allocated Memory、Running Containers。队列层指标适合判断资源是否被某个队列占满。应用层指标适合判断任务是否失败、是否长期排队。节点层指标适合发现某台机器是否异常。

如果只采集集群层指标,会漏掉某个队列被打满的问题;如果只看应用失败数,又很难判断是不是节点故障导致的集中失败。比较合理的监控角度应该至少包含:

  1. ResourceManager 是否存活,HA 状态是否正常。
  2. Active/Lost/Unhealthy NodeManager 数量。
  3. 队列资源使用率、Pending 应用数、Pending Containers、Running 应用数。
  4. 应用失败率、AM 失败率、平均排队时间、平均运行时间。
  5. Scheduler Delay 或调度分配延迟。
  6. 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>

如果日志命令拿不到内容,先检查三件事:

  1. 是否启用了 yarn.log-aggregation-enable。
  2. HDFS 上的远程日志目录是否存在。
  3. 应用是否已经结束并完成日志聚合。

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 的对象关系和命令链路,不适合直接推导生产权限设计。真正上线前,还要把下面这些内容补齐:

  1. 服务运行用户和目录权限。
  2. 队列 ACL 和用户组映射。
  3. Kerberos 认证和 keytab 分发。
  4. ResourceManager、NameNode 的 HA。
  5. 节点维护、扩容、缩容流程。
  6. 日志保留和审计要求。

这些内容不影响单机环境跑通,但会决定生产集群能不能长期可管理。

6. 小结

YARN 管理的核心是建立一条排查链路:从进程到节点,从节点到队列,从队列到应用,从应用到 Container,再从 Container 回到日志和指标。

这篇文章最有价值的内容可以压缩成几句话:

  1. ResourceManager 是 YARN 管理入口,但不能只看 ResourceManager。
  2. NodeManager 是否 RUNNING,决定集群有没有地方运行 Container。
  3. Scheduler 页面和队列配置决定资源如何分配。
  4. JobHistoryServer 和 yarn logs 决定任务完成后能不能追踪。
  5. rmadmin 的刷新命令是生产管理的重要入口,但执行后必须验证结果。
  6. JVM 分析要区分守护进程和应用 Container。

管理 YARN 的核心不是记住某个监控页面,而是知道每个页面、命令和日志对应哪一个管理对象。对象关系清楚后,面对 ACCEPTED、FAILED、UNHEALTHY、日志缺失、队列拥塞这些问题,才能沿着 RM、NM、AM、Container 和日志链路逐层定位。


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