跳转至

YARN 架构原理

作者:JiangChong | 撰写时间:2026年09月

适用场景:零基础认识 YARN;或需要理解这类问题——作业提交后到底发生了什么、Container 为什么被杀、多个团队怎么安全地共享一个集群、Spark/Flink 为什么能跑在 Hadoop 上。先读本文建立原理框架,再按需进入 Spark/Flink 系列。

阅读前先认识三个词

术语 一句话解释
ResourceManager(RM) 集群资源的「总调度者」,一个集群一个,负责审批和分配资源
NodeManager(NM) 每台机器上的「资源管家」,管本机上的资源盒子,一节点一个
Container(容器) 资源的最小单位——一个「CPU + 内存」的盒子,计算任务就跑在盒子里

「RM 管全局、NM 管单机、Container 是盒子」——全文 80% 的机制都建立在这三句话上。完整术语表见文末附录 A。

关联文章

本系列前 8 篇(01~08)全部讲 HDFS(存储层),本文是系列第一篇 计算层 文章,两半合起来才是完整的 Hadoop:

  • HDFS 架构原理 — 存储层第一篇:数据存哪、怎么存;本文回答另一半:计算在哪跑、资源怎么分
  • HDFS 读写流程与副本放置策略 — 数据如何流入流出,理解「数据本地性」的前置
  • ZooKeeper 分布式协调服务核心概念 — HDFS HA 与 YARN RM HA 都靠它选主
  • Spark 架构原理 — YARN 上最主流的计算框架
  • Spark 与 Vertica 集成最佳实践 — 大数据平台 + Vertica 数仓的典型组合:Spark on YARN 加工数据,再 COPY 进 Vertica
  • Flink 系列 — 另一个主流选择,同样能跑在 YARN 上

理解全文脉络

本文按「为什么需要 → 静态架构 → 动态机制 → 资源与调度 → 可靠性与生态」组织:第 0 节回答「YARN 解决什么问题」,第 1 节讲四个角色各管什么,第 2 节跟一次作业跑完全程,第 3、4 节深入资源怎么分、调度器怎么排,第 5、6 节讲容错与「一集群多框架」的设计价值,第 7 节对比 Spark/Flink 的另一种跑法,第 8 节用总结表收束,第 9 节给实践清单。

新手建议从头顺序读——每一节都从通俗比喻讲起,再进入机制细节。赶时间的读者可以只读第 0、1、8 节和附录 A。


0. 为什么需要 YARN:从 JobTracker 的「三宗罪」说起

Hadoop 1.x 时代,集群里管计算的进程叫 JobTracker,每台机器上跑一个 TaskTracker 听它指挥。当时的设计把「管理资源」和「管理作业」揉在同一个进程里,后果是三个致命问题:

  • 单点:JobTracker 只有一个。它一挂,全集群所有作业停摆,还没人接替它;
  • 撑不大:官方口径约 4000 节点、4 万并发任务就是它的天花板。任务一多,JobTracker 自己先被元数据压垮;
  • 只认 MapReduce:JobTracker 和 MapReduce 绑死,想跑 Spark、Flink?对不起,得另起一个集群。

YARN 的解法是一刀切的职责拆分:把「管集群资源」与「管某个作业」分开——

  • 集群资源(谁有多少 CPU/内存)由一个全局进程统一管 → 与具体计算框架无关;
  • 每个作业的执行细节由「该作业专属的管理者」负责 → 想跑什么框架都行,只要能向资源层申请资源。

这就像物业改革:以前整栋楼只有一个总物业经理,订水、修电梯、开住户大会全找他,他忙死,整楼还停摆;改革后物业公司只管分配「工位 + 电脑」,每家公司自己派项目经理来申请和安排——工位谁都能用,物业不再管你公司是做什么的。

这就是 YARN(Yet Another Resource Negotiator,「又一个资源协调者」)——Hadoop 2.0(2012 年发布,2.2 起稳定)引入的资源管理与作业调度框架,彻底取代 1.x 的 JobTracker/TaskTracker 架构。定位一句话:YARN 是 Hadoop 的计算层「资源操作系统」——HDFS 管数据存哪,YARN 管计算在哪跑、谁先用资源。


1. 整体架构:物业公司、楼栋管家与项目经理

YARN 沿用主从架构,但角色从 1.x 的两个变成四个:ResourceManager(全局 1 个,主备可多个)、NodeManager(每节点 1 个)、ApplicationMaster(每作业 1 个)、Container(运行单位,无数个)。

把集群想象成一栋写字楼:

  • ResourceManager 是物业公司总部——每家公司要用几间办公室、多少台电脑,统一审批,只看「楼里还有多少资源」,不管你家公司具体干什么;
  • NodeManager 是楼栋管理员——每人管一层楼:有人搬进来就开门(启动 Container),搬走就锁门(销毁 Container),定时向总部汇报本层还剩多少工位;
  • ApplicationMaster 是每家公司的项目经理——向总部申请工位、安排自家员工坐下干活、员工干砸了重新招人,全程只管自家这个项目;
  • Container 是一个「工位 + 电脑」的资源包——内存若干 GB + CPU 若干核的封装,员工(计算进程)坐在工位里干活。
graph TB
    RM["ResourceManager<br/>物业总部:全局资源分配"]
    AM["ApplicationMaster<br/>项目经理:本作业调度<br/>(本身也住在容器里)"]
    NM1["NodeManager<br/>楼栋管理员"]
    NM2["NodeManager<br/>楼栋管理员"]
    C1["Container<br/>工位+电脑"]
    C2["Container<br/>工位+电脑"]
    C3["Container<br/>工位+电脑"]

    AM -->|"① 申请容器"| RM
    RM -->|"② 分配:去哪台机器"| AM
    AM -->|"③ 派活到容器"| NM1
    AM -->|"③ 派活到容器"| NM2
    NM1 --> C1
    NM1 --> C2
    NM2 --> C3
    NM1 -.->|"心跳 + 本机资源"| RM
    NM2 -.->|"心跳 + 本机资源"| RM

这张图是全文总纲,下面的 1.1~1.4 逐个展开。

1.1 ResourceManager:只管资源,不管作业

RM 内部是两块分工:

子组件 职责 类比
Scheduler(调度器) 纯资源分配:按队列/优先级把空闲资源分给应用;不跟踪作业状态、不做容错 只看「工位空不空」的审批员
ApplicationsManager(应用管理器) 管 AM 的生命周期:接收新作业、启动 AM、AM 挂了重启它 物业的「公司入驻服务台」

把调度器做「纯」是 YARN 的核心设计取舍:调度器不管作业死活,只做「资源够不够、按什么规则给」这一件事——这让它身轻如燕,撑得起上万并发作业(对比 1.x 的 JobTracker 什么都要管,所以 4000 节点就封顶)。

RM 本身是单点,但它不持有作业的最终状态,所以高可用比 HDFS 的 NameNode 好做——Active/Standby 双 RM + ZooKeeper 选主,切换后客户端重试即可(第 5 节展开)。

1.2 NodeManager:楼栋管理员

NM 每台机器一个,职责四件:

  • 启动、监控、销毁本机上的 Container;
  • 向 RM 心跳上报本机资源(总量、已用、剩余)与健康状况;
  • 执行 RM 下发的指令(杀容器、清理等);
  • 辅助服务:日志聚合(把容器日志收集到 HDFS,作业结束后仍可查)、MapReduce 的 Shuffle 辅助等。

关键职责减负:1.x 的 TaskTracker 要盯着每个任务跑到哪一步、任务失败还要自己重试;YARN 的 NM 只负责「盒子」的生死,盒子里面任务干得好不好,归 AM 管。这正是 1.x 撑不大的原因被拆掉的体现——监控与重试这类「每个作业都不一样」的逻辑,下沉到了每个作业自己的 AM 里。

1.3 ApplicationMaster:每个作业的项目经理

一个运行中的应用(作业)对应一个 AM,AM 本身也跑在一个 Container 里。它的职责:

  • 向 RM 申请所需资源(按作业阶段动态申请、用完归还);
  • 把申请到的 Container 派给任务,在对应机器的 NM 上启动;
  • 跟踪任务进度,任务失败则重新申请容器重跑;
  • 全部完成后向 RM 注销,释放所有资源。

用不同框架代入一下就明白了:

  • MapReduce on YARN:AM 先申请 Map 容器,Map 跑完再申请 Reduce 容器;
  • Spark on YARN(cluster 模式):AM 里住着 Driver,executor 是它申请来的 Container;
  • Flink on YARN:AM 协调 JobManager 与 TaskManager 的容器布局。

「每个作业一个管理者」让多框架共存成为可能——框架只需实现「AM 怎么向 RM 要资源、怎么安排自己的任务」,资源分配本身由 YARN 统一完成。第 7 节再展开。

1.4 Container:CPU + 内存的「盒子」

Container 不是进程,而是资源封装:一份内存(MB)+ 若干 vCore(虚拟核),外加运行环境(环境变量、依赖、启动命令)。AM 申请到后,NM 按规格拉起进程放进盒子;进程退出或被杀,盒子即被回收。

对比 1.x 的 slot(槽位)看 Container 的进步:

维度 1.x Slot YARN Container
划分方式 静态:每节点按固定个数切分,Map/Reduce 槽位分开 动态:按需申请,Map/Reduce(或任何框架的任务)通用
利用率 槽位空着也不能借给另一种任务 用多少申请多少,归还即复用
扩展性 只能跑 MapReduce 任何实现 AM 协议的框架都能跑

本节要点:RM 管全局资源(纯调度,不管作业)、NM 管单机盒子、AM 管单个作业(申请→派活→重试→注销)、Container 是可动态伸缩的资源盒子。四个角色各管一摊,谁也不越界——这就是 YARN 能撑大、能多框架共存的根基。


2. 一次作业的完整旅程

跟着一个 MapReduce 作业从头走到尾,看四个角色如何接力:

graph TB
    A["① Client 提交作业<br/>(含 jar、配置、输入路径)"] --> B["RM 的 ApplicationsManager<br/>登记作业,分配 AM 容器"]
    B --> C["② 某台 NM 启动 AM<br/>(AM 也是容器)"]
    C --> D["③ AM 向 RM 申请<br/>Map 任务所需容器"]
    D --> E["④ RM 返回容器位置<br/>(哪台机器有多少资源)"]
    E --> F["⑤ AM 通知对应 NM<br/>启动任务容器"]
    F --> G["⑥ 任务运行,进度汇报给 AM;<br/>NM 心跳把资源占用报给 RM"]
    G --> H["⑦ 全部完成,AM 注销,<br/>RM 回收所有资源"]

七个步骤里值得强调三点:

  • ② ③:AM 的启动是「先申请一个容器,把自己装进去」——RM 不亲自跑任何作业逻辑,连 AM 本身都只是「帮第一个容器选了个位置」。这也是「资源管理层与作业执行层彻底分离」的最直观体现;
  • ⑤ ⑥:任务的数据流在 AM 与 NM 之间直通,RM 不参与——和 HDFS 里「NameNode 不碰数据」是同一设计哲学:控制平面与数据平面分离;
  • ① 里的「作业」概念:对 YARN 来说,提交的只是一个「应用」(application)——一个 jar、一个 spark-submit 脚本、一个 Flink 程序,语义相同。

MapReduce 的独特之处:M 阶段和 R 阶段的容器是先后两批申请的,中间还要跨节点搬运中间结果(shuffle)。因此「Map 全跑完、Reduce 等容器」阶段经常出现集群资源利用率波动——这也是后面 Spark 用「申请一批容器、流水线执行」替代它的原因之一(详见 Spark 架构原理)。

本节要点:作业旅程 = 提交 → RM 启动 AM(AM 也是容器)→ AM 申请容器 → NM 启动任务 → 任务向 AM 汇报 → 完成注销。RM 全程只做「分资源」,不碰作业逻辑。


3. 资源模型:内存 + vCore 怎么分

3.1 三组参数决定「能分多少、最小给多少」

参数(yarn-site.xml) 默认值 含义
yarn.nodemanager.resource.memory-mb 8192 每台 NM 可分配给 YARN 的内存总量
yarn.nodemanager.resource.cpu-vcores 8 每台 NM 可分配的虚拟核数
yarn.scheduler.minimum-allocation-mb 1024 单个容器最少申请量(分配按它的整数倍)
yarn.scheduler.maximum-allocation-mb 8192 单个容器最多申请量

内存分配受三条规则约束(按默认值举例:最小 1024MB、最大 8192MB、单机总量 8192MB):

  1. 申请量按最小值向上取整——内存按 1024MB 的整块切分,不够一块的向上凑成一块:申请 1500MB 实际拿到 2048MB(2 块)、申请 3000MB 拿到 3072MB(3 块)。就像工位只按整间出租:要 1.5 间的量也得租 2 间,凑整多出的部分调度器照常记账,别的作业用不到;
  2. 单个容器不能超过最大值——maximum-allocation-mb(默认 8192MB)规定了容器的尺寸上限:单个容器最多只能申请 8GB,超过直接失败、作业起不来。而且容器必须完整落在一台机器上、不能跨机器拼装,默认配置下根本不存在 100GB 大小的容器——大内存需求要拆成多个容器并行跑,而不是要一个大容器;
  3. 所有容器总量不能超过 NM 上限——一台机器给 YARN 的内存总共就 8192MB,所有容器加起来不能超出——「楼里总共就这么多工位」,这是总量层面的常识性约束。

由此得出一个实操点:申请值如果不是 1024 的整数倍,凑整的差额就白付了——你大概率用不上,别的作业也用不了,等于白白占用集群容量。所以生产上申请内存(如 Spark 的 --executor-memory)尽量取整到最小单位的整数倍(2048 / 3072 / 4096…)。

以上默认值以 Apache Hadoop 官方文档为准,不同发行版(CDH/HDP 等)可能覆盖;拿不准的版本差异请查官方文档。

两个高频坑:

  1. 把物理内存全给 YARN。NM 的 memory-mb 设为整机内存时,OS、HDFS 的 DataNode、RM/NM 自身、以及容器进程的页表开销没有余量,机器直接进 swap 或触发 OOM。经验值:YARN 只分配物理内存的约 80%,留 20% 给系统与 HDFS 等常驻进程(小内存机器比例要更保守)。
  2. 容器实际内存超限被 NM 强杀。NM 会监控每个容器的真实内存占用(cgroup 开启时最准确),超过申请量阈值即杀进程,作业报错形如 Container [pid=...] is running beyond physical memory limits... Killing container。这不是「配置调小点」能绕过的——要么给足容器内存,要么减小每个任务实际占用的内存(如 Spark 的 --executor-memory 与 spark.memory.offHeap 体系要小于容器大小)。

3.2 vCore 与 CPU 的关系

vCore(虚拟核)是逻辑概念,不等于物理核——一台 32 物理核机器可以配 32 或 64 个 vCore,超配(over-commit)时靠内核调度抢时间片,适合 CPU 平均使用率不高的批处理负载;但两个 CPU 密集型框架同时超配,互相拖慢,需要靠队列限流(见第 4 节)。

容器规格要和任务内存模型匹配:容器只是「盒子」,盒子大小由框架侧的内存参数决定(MapReduce 的 mapreduce.map.memory.mb、Spark 的 executor 内存、Flink 的 TaskManager 内存)。框架侧内存 + 容器侧规格是同一件事的两半——只调一边,要么内存浪费,要么被杀。

本节要点:内存分配 = 总量(NM)× 最小/最大粒度(调度器)的「切盒子」过程;vCore 是逻辑资源可以超配;容器被杀十有八九是「任务真实内存 > 申请内存」,要从框架侧内存参数解决。


4. 调度器:多个作业挤一台集群,谁先谁后

RM 的 Scheduler 有两个主流实现,选哪个由 yarn.resourcemanager.scheduler.class 决定:

Capacity Scheduler(默认) Fair Scheduler
核心思想 队列预设容量(如 A 队 50%、B 队 30%),容量内各取所需 所有应用平分资源,按需再分配
弹性 队列资源用不满时借给别的队列,还回来优先 应用按权重共享,权重高者拿得多
典型场景 多团队固定预算的共享生产集群 交互式 + 批处理混合、追求公平
配置位置 capacity-scheduler.xml fair-scheduler.xml

三级调度结构(以 Capacity 为例):队列(queue)→ 队列内应用(application)→ 应用内容器(container)。RM 先看资源该进哪个队列(容量/ACL),再看队列里哪个应用(优先级/提交时间/FIFO),最后按应用申请分配容器。

队列的价值就是「多租户隔离」:没有队列时,A 团队一个跑满内存的作业能饿死全集群所有人;有了队列,B 团队的容量被「圈」住,A 再怎么疯跑,B 的配额内照常运行。同时队列支持弹性借还——A 忙时用 B 的空闲容量,B 一有需求立刻归还。生产集群普遍按「部门 × 作业优先级(生产/测试/临时)」划分队列,并配合 ACL 控制谁能提交到哪个队列。

看调度器状态去哪看:RM Web UI(默认 http://<rm-host>:8088)的 Active Applications、Queue 指标,以及 yarn application -list / yarn queue -status <queue> 命令行——排查「作业一直 ACCEPTED 不跑」先看这里(多半是队列容量满了在排队)。

本节要点:默认 Capacity Scheduler 按「队列 → 应用 → 容器」三级调度;队列 = 多团队共享集群时的资源隔离与容量保障机制;作业排队不报错、只是等资源——先查队列使用率再查别的。


5. 高可用与容错:三道防线

YARN 的故障处理分三个层次,从「集群级」到「任务级」逐级兜底:

第一道:RM 层(集群级)。RM 是主备部署,Active/Standby + ZooKeeper 选主(与 HDFS HA 的 ZKFC 选主是同一套路,见 HDFS 高可用(QJM、ZKFC、Federation))。Active 宕机后 ZK 触发切换,数秒内恢复服务;客户端和 AM 会重试与新区建立连接。相比 HDFS 的 NameNode,RM 没有「重放日志 + 块报告」的恢复过程,切换更快。

第二道:AM 层(作业级)。AM 崩溃后,RM 的 ApplicationsManager 负责重新拉起一个 AM 接管该作业。新 AM 需要重新申请容器、重新调度未完成任务——现代 Hadoop 支持 work-preserving(保留已完成工作) 的 AM 重启,Spark/Flink 的 AM 都实现了这套恢复协议,AM 挂掉后作业不白跑。注意:NM 故障则是另一回事——NM 上的容器全部丢失,由 AM 感知后重新申请容器补跑,这正是「任务状态归 AM 管」的意义。

第三道:任务级。单个任务失败由 AM 直接重试(MapReduce 默认 4 次,mapreduce.map.maxattempts);AM 本身也可配置重试次数(yarn.resourcemanager.am.max-attempts)。重试到上限仍失败,作业才整体失败。Spark 没有「任务重试」概念,它靠 RDD 血缘从失败分区重算——殊途同归,都是「失败重来」,只是重来的粒度不同。

一句话串起三层防线:RM 挂了换主、AM 挂了重拉、任务挂了重跑——每一层只管自己这一层,上层不需要知道下层的细节。 这正是 YARN 把「作业状态管理」下放给 AM 的红利:集群级故障只影响调度入口,作业级容错完全自治。

本节要点:YARN 容错 = RM 主备(ZK 选主)+ AM 重启(work-preserving)+ 任务重试,三层各自独立、逐级兜底。RM HA 与 HDFS HA 思路同源,都依赖 ZooKeeper。


6. 数据本地性:计算为什么要追着数据跑

第 5 节讲了 YARN 如何「跑得稳」,这一节讲它如何「跑得快」——答案和 HDFS 的数据本地性(HDFS 架构原理 第 7 节)是同一件事的两面。

数据不会自己跑,但计算可以搬家。 HDFS 上文件按 128MB 块散布在集群各节点,YARN 调度容器时按「离数据多远」排优先级:

  1. node-local(节点本地):容器所在机器上就有数据块——最优,数据零搬运;
  2. rack-local(机架本地):同一机架的另一台机器上有数据——走机架内交换机;
  3. off-switch(跨机架):数据在其他机架——过核心交换机,最贵。

调度器会优先选 node-local,其次 rack-local,只有等不到时才退而求其次(等待时长由 yarn.locality.wait 等参数控制)。本地性差的代价是实打实的网络搬运:1TB 任务若全部跨机架读,光传输就多走一趟核心交换机。

所以生产上 YARN 与 HDFS 必须同集群部署——数据本地性依赖「计算节点和存储节点是同一批机器」。这也是 Hadoop 生态与「存储与计算分离」的云原生架构(如 Spark on K8s + 对象存储)最大的哲学差异:前者省网络、后者省机器,各有取舍。

本节要点:YARN 调度按 node-local → rack-local → off-switch 三级就近优先,让计算「追着数据跑」;因此 YARN 与 HDFS 同集群部署是数据本地性的前提。


7. 一集群多框架:YARN 最值钱的设计

回到第 0 节的问题——「只能跑 MapReduce」是怎么被解决的?答案是:任何框架只要实现「AM 向 RM 申请容器」的协议,就能跑在 YARN 上,与存储、与调度彻底解耦:

框架 跑在 YARN 上的形态 一句话
MapReduce AM 分两阶段申请 M/R 容器 亲儿子,MRv2 即「跑在 YARN 上的 MR」
Spark client 模式:Driver 在提交端;cluster 模式:Driver 住在 AM 里 申请一批 executor 容器,流水线执行
Flink yarn-session / yarn-application 模式 AM 协调 JobManager/TaskManager 容器布局
Tez 有向无环图(DAG)任务,按需申请 主要作为 Hive on Tez 的执行引擎

多框架共享集群的价值是资源利用率:白天跑 Spark 批处理、夜间跑 Flink 流作业、临时跑点 MapReduce——不同负载错峰挤进同一批机器,单框架集群各自的空闲时段被互相填满。这也是 YARN 对比「每个框架各起一套独立集群」的核心优势:

维度 各框架独立集群 统一跑在 YARN 上
资源利用 每套集群都要按峰值配置,多数时间空闲 全局按需分配,错峰共享
运维成本 N 套集群 N 套监控 一套资源层统一管理
隔离性 物理隔离,天然互不影响 靠队列隔离(第 4 节)
适用 框架少、负载稳定 框架多、负载波动

Vertica 用户的现实关联:主流的大数据平台组合往往是「HDFS 存明细 + Spark on YARN 做加工 + COPY 进 Vertica 供分析」——YARN 是这条流水线的「调度中枢」,Vertica 本身不依赖 YARN,但加工链路的前半段跑在它上面(实操见 Spark 与 Vertica 集成最佳实践)。

本节要点:YARN 把「资源层」做成通用底座,MapReduce/Spark/Flink/Tez 都是插上去的「计算插件」;多框架共享集群的核心收益是资源利用率与运维统一。


8. 组件职责总结表

组件 职责 故障影响
ResourceManager 全局资源分配:Scheduler 纯调度 + ApplicationsManager 管 AM 生命周期;不执行作业逻辑 主备部署(ZK 选主),Active 宕机数秒切换;切换期间新作业提交短暂失败
NodeManager 本机容器启停/监控;心跳上报资源;日志聚合等辅助服务 宕机后其上容器全部丢失,由对应 AM 感知后重新调度补跑
ApplicationMaster 单作业专属:申请容器、派活、跟踪进度、失败重试、完成注销(自身也是容器) 崩溃由 RM 重新拉起(work-preserving 保留已完成工作);反复崩溃达上限则作业失败
Container 「CPU + 内存」资源盒子,任务进程的运行载体 被杀 = 该任务失败,由 AM 重试;不涉及全局影响
ZooKeeper(HA 用) RM 主备选主 多数派存活即可,与 HDFS HA 共用一套

一句话记忆:RM 管资源、NM 管机器、AM 管作业、Container 是盒子——RM 分完资源就不管闲事,作业死活全靠 AM 自治。


9. 最佳实践清单

按投入产出比排序,每条附「为什么」:

  1. YARN 内存预算留 20% 给系统(yarn.nodemanager.resource.memory-mb ≈ 物理内存 × 80%)——为什么:整机内存全给 YARN,OS 与 DataNode 会被挤到 swap/OOM,表现是「集群莫名变慢」而非明确报错,最难排查。
  2. 容器规格与框架侧内存参数联动配置——为什么:Spark --executor-memory、MR mapreduce.map.memory.mb 与容器大小是同一件事的两半;只调一边必然导致「内存浪费」或「Container killed by NodeManager」。
  3. 多团队共享集群必上队列 + 容量规划 + ACL——为什么:没有队列,一个跑满资源的作业能饿死全集群;队列 + ACL 是生产环境多租户的底线。
  4. 先把 RM Web UI 与 yarn queue -status 看明白再排查作业问题——为什么:作业 ACCEPTED 不跑 = 排队等资源,不查队列使用率就去查代码/网络,方向就错了。
  5. 记住「NM 宕机 = 容器全丢、AM 重拉补跑」,不要恐慌——为什么:YARN 三层容错(RM 换主 / AM 重拉 / 任务重试)天然兜底;看到 AM 重启日志先确认是否在 work-preserving 恢复,通常无需人工干预。
  6. 本地性优先:保持 YARN 与 HDFS 同集群部署——为什么:计算追着数据跑是省网络流量的根本机制;一旦拆分部署(远程 HDFS),任务吞吐立刻被跨机房带宽锁死。
  7. 监控容器日志聚合与队列指标,而非只盯节点存活——为什么:作业级问题(内存被杀、队列积压)几乎都先于节点问题出现;yarn logs -applicationId <id> 是排查的第一工具。
  8. 框架选型时想清楚「共享 vs 隔离」——为什么:YARN 集群追求利用率靠队列隔离;若框架间干扰不可接受(如超大流作业与批处理混跑),独立集群仍是合理选项,不是所有负载都适合挤在一起。

附录 A:术语速查表

术语 一句话解释 详见
YARN Hadoop 的资源管理与作业调度层:「计算在哪跑、谁先用资源」 第 0 节
ResourceManager(RM) 全局资源调度者;Scheduler 纯调度 + ApplicationsManager 管 AM 1.1
NodeManager(NM) 每台机器上的容器管家;心跳上报资源、启停容器 1.2
ApplicationMaster(AM) 每个作业专属的管理者:申请容器、派活、重试、注销 1.3
Container CPU + 内存的资源盒子,任务进程的载体 1.4
vCore 虚拟核,逻辑 CPU 资源,可超配 3.2
Capacity Scheduler 默认调度器:按队列预设容量分配,支持弹性借还 第 4 节
Fair Scheduler 公平调度器:应用间平分资源 第 4 节
队列(Queue) 多租户资源隔离单元,三级调度第一层 第 4 节
Work-preserving AM 重启时保留已完成工作的恢复机制 第 5 节
Data Locality node-local → rack-local → off-switch 的就近调度优先级 第 6 节
MRv2 跑在 YARN 上的 MapReduce(Hadoop 2.x 起) 第 7 节

附录 B:新手常见疑问(FAQ)

Q1:YARN 和 HDFS 是什么关系? 分工关系:HDFS 管「数据存哪」(存储层),YARN 管「计算在哪跑」(资源与调度层)。两者独立演进(YARN 可以不给 HDFS 用,HDFS 也不依赖 YARN),但组合起来才是完整的 Hadoop 平台,且数据本地性要求它们同集群部署。

Q2:不装 YARN 能跑 Spark / Flink 吗? 能。Spark 支持 standalone(自带资源管理)、YARN、Mesos、Kubernetes 四种模式;Flink 也支持 standalone/YARN/K8s。区别是:用 YARN/K8s 时资源统一管理、多框架共享集群,standalone 则是各跑各的、利用率低。

Q3:Container 被杀(killed)一定是代码 bug 吗? 大概率是内存问题:任务真实内存超过申请量被 NM 强杀。先 yarn logs 看容器日志确认是内存超限,再从框架侧调内存参数或代码(数据倾斜、缓存过量),而不是简单调大容器——调大只是把问题推迟。

Q4:作业一直「ACCEPTED」不执行,是卡住了吗? 不是卡住,是在排队——队列容量用满、等待资源。用 yarn queue -status <queue> 或 RM Web UI 看队列积压与资源使用率;等不到资源通常说明队列容量规划偏小或有人在跑大作业。

Q5:Kubernetes 会取代 YARN 吗? 部分重叠但不会简单取代。K8s 擅长容器编排与微服务,YARN 深耕大数据作业语义(队列、AM、本地性、框架协议);现实中两者并存——新负载上 K8s、存量 Hadoop 生态继续用 YARN,也有 YuniKorn 等项目尝试在 K8s 上提供类 YARN 的调度能力。选型看团队生态:大数据栈重就 YARN,容器栈重就 K8s。

扩展阅读