☰
Hadoop YARN集群部署实战:核心配置、内存调优与常见问题排查
2026/10/27 11:12:13 网站建设 项目流程

1. 为什么单独拎出YARN来部署:一次踩坑后的重新理解

很多人搭Hadoop集群的习惯是“一把梭”——伪分布式跑通就上完全分布式,core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml四个文件一起改,start-all.sh一敲,看到几个进程起来就觉得完事了。我最早也是这么干的,结果后面跑一个稍微重一点的计算任务,容器疯狂报Container is running beyond physical memory limits,节点上的NodeManager隔三差五掉线,日志翻半天才定位到是yarn.nodemanager.resource.memory-mb给得比机器实际可用内存还大。那次之后我才意识到,YARN这一层其实是整个Hadoop里最容易被“顺带配一下”糊弄过去、但出问题最频繁的部分。

这篇内容就专门聊HADOOP之部署YARN集群这一件事,把YARN从HDFS里单独拎出来讲清楚。它是什么:YARN是Hadoop的资源调度层,负责把集群的CPU、内存切成容器(Container)分给各个计算任务,HDFS管存、YARN管算,两者是并列关系而不是从属关系。它能做什么:让多个计算框架(MapReduce、Spark、Flink等)共享同一批机器资源,按需申请、用完释放。解决了什么问题:把“资源管理”和“计算逻辑”解耦,避免每个框架各自抢机器、各自维护一套调度。适合谁看:已经能把HDFS单机或伪分布式跑起来、准备上多节点集群的运维和开发同学,以及那些start-yarn.sh敲下去进程起不来、或者起来了任务却一直卡在ACCEPTED状态的人。

我下面讲的部署路径,是基于“三台及以上节点、HDFS已经可用、准备接入YARN做资源调度”这个最常见的情境来展开的。如果你还在单机阶段,部分参数可以按比例缩小,但思路是一致的。整个部署我会拆成设计思路、核心配置细节、实操落地、问题排查四块,中间穿插我自己踩过的坑和实测有效的参数取值。

2. 部署前的整体设计与思路拆解

2.1 为什么YARN要独立于HDFS来规划

刚接触的人常有个误解:HDFS的DataNode在哪台机器上,YARN的NodeManager就一定要跟着放哪台。这个说法在“存算一体”的小集群里成立,但它不是硬性约束。YARN的ResourceManager和NodeManager构成的是资源视图,HDFS的NameNode和DataNode构成的是存储视图,两者通过主机名和端口各自通信,逻辑上完全独立。

我选择把YARN单独规划,主要基于两个现实考量。第一是资源隔离的清晰度:如果一台机器既跑DataNode又跑NodeManager,磁盘IO和内存会被存储和计算同时争抢,出问题时很难判断是HDFS写入慢拖累了计算,还是计算把内存吃满导致DataNode被系统杀掉。第二是扩容的灵活性:计算需求涨得快的时候,我可以只加NodeManager节点而不动HDFS的副本布局;反过来存储吃紧时也只扩DataNode。这种解耦在节点数量超过五六台之后价值非常明显。

当然,小集群(三台以内)为了省机器,存算一体是合理的,我下面实操部分也是按存算一体来演示,因为这是大多数人的起点。但你在规划阶段心里要清楚:ResourceManager是全局单点,NodeManager是可水平扩展的工作节点,这个角色划分决定了后面所有配置的归属。

2.2 ResourceManager与NodeManager的角色分工

把YARN想成一个“包工头+工头”的结构就很好理解。ResourceManager(RM)是包工头,手里握着整个集群的资源账本,谁要干活(提交任务)都得先找它申请;NodeManager(NM)是各个工地上的工头,负责盯着自己那台机器的CPU、内存、磁盘还剩多少,定期向包工头汇报,接到任务后在本机启动容器干活。

这个分工带来一个关键设计点:RM不直接管容器,它只做调度决策。真正启动、监控、杀掉容器的是NM。所以RM的负载相对轻,但它是单点,一旦挂了整个集群没法提交新任务(正在跑的任务不受影响,因为容器已经在NM上跑起来了)。这也是为什么生产环境要做RM的高可用,而本文的部署先聚焦单RM,高可用作为后续扩展点提一句。

另一个容易忽略的是ApplicationMaster(AM)。每个提交的应用都会在某个NM上启动一个AM,AM负责向RM申请资源、跟NM协商启动具体任务容器。AM本身也占一个容器,所以你在算资源的时候不能只算任务需要多少,还得给AM留一份。这个细节后面配内存参数时会再提。

2.3 端口与通信链路的预先规划

部署前把端口理清楚,能省掉后面大量“连不上”的排查时间。YARN涉及的核心端口我整理成下面这张表,实际部署时建议先确认这些端口在防火墙和机器上都没被占用。

组件默认端口作用是否需对外
ResourceManager8032ApplicationMaster 与 RM 通信集群内
ResourceManager8088Web UI 与 REST API视需要
ResourceManager8030调度器接口集群内
ResourceManager8031资源追踪接口集群内
NodeManager8042NM Web 服务与容器管理集群内
NodeManager随机容器内部通信本机

这里有个实操经验:8088这个Web UI端口建议只对内网开放,它能看到所有任务的运行状态和日志入口,暴露到公网没有意义还增加风险。而8032、8030、8031这几个是RM和AM、NM之间的RPC端口,必须保证集群内所有节点互通,配防火墙时别只放行8088忘了它们,我见过有人UI能打开但任务一直提交不上去,就是8032被拦了。

2.4 资源模型的选择:内存为主、CPU为辅

YARN默认的资源调度模型是内存主导,CPU作为辅助维度。也就是说调度器主要看内存够不够,CPU核数更多是个软约束。这个设计有历史原因,但对新手来说意味着:内存参数配错是YARN部署失败的头号原因,CPU配错通常只是任务跑得慢,不会直接起不来。

所以我的部署思路是:先把每个NM的可用内存算准、配对,再考虑CPU。具体怎么算,下一节展开。这里先建立一个原则——NM上报给RM的内存,必须是这台机器上“真正能拿出来给容器用”的内存,而不是物理内存总量。操作系统本身、DataNode、NM自己的JVM都要占内存,全报上去必然导致容器超卖、被系统OOM Killer干掉。

3. 核心配置细节与参数解析

3.1 yarn-site.xml里绕不开的几个关键项

yarn-site.xml是YARN部署的主战场,我挑几个必须理解透的项来讲,而不是把整份配置贴出来让你抄。

第一个是yarn.resourcemanager.hostname,指定RM所在机器的主机名。这里有个坑:必须用主机名而不是IP,且所有节点的/etc/hosts里都要有这个主机名到IP的映射。用IP的话,某些组件反解主机名会失败,表现为NM注册不上RM。我习惯在部署前统一检查一遍hostname和hosts,确保每台机器能互相ping 主机名通。

第二个是yarn.nodemanager.aux-services,值设为mapreduce_shuffle。这是给MapReduce的Shuffle阶段提供辅助服务的,不配的话MR任务能提交但Shuffle阶段直接失败。很多人只跑Spark觉得不需要,但Spark在某些模式下也会用到,建议一律配上。

第三个是yarn.nodemanager.resource.memory-mb,这是单个NM能分配给容器的总内存,是整个YARN部署里最关键的参数。它的计算方式是:物理内存减去系统预留、减去DataNode堆内存、减去NM自身JVM开销。举个具体例子,一台16GB内存的机器,系统留2GB,DataNode堆配1GB,NM自身约1GB,那么可分配大约12GB,保守一点配成11264MB(11GB)比较稳。宁可少报,不要多报,少报只是浪费一点资源,多报就是容器被杀的隐患。

第四个是yarn.nodemanager.resource.cpu-vcores,单NM可分配的虚拟核数。一般配成物理核数或者物理核数的1到2倍,取决于你的任务类型。计算密集型配成物理核数,IO密集型可以适当放大。我通常先配成物理核数,跑起来看实际利用率再调。

3.2 内存参数的计算过程与取值逻辑

上面提到内存要“算准”,这里把计算过程完整走一遍,因为这是最多人配错的地方。

假设一台机器物理内存16GB,上面同时跑DataNode和NodeManager。预留项包括:操作系统和基础服务约1.5到2GB;DataNode的JVM堆,小集群配1GB足够;NodeManager自身JVM约1GB;再留0.5到1GB的缓冲应对突发。加起来预留约4GB,可分配给容器的就是12GB左右。

但这里还有个容器内存的粒度问题。YARN调度时按yarn.scheduler.minimum-allocation-mb(默认1024MB)为最小单位分配,一个申请1500MB的任务实际会占2048MB。所以你在配总内存时,最好让它是最小分配单位的整数倍,避免出现“总量够但凑不出一个容器”的尴尬。12GB配成12288MB,正好是1024的12倍,很干净。

再往下是单个容器能申请的最大内存yarn.scheduler.maximum-allocation-mb,默认8192MB。如果你的任务里有需要大内存的(比如某些Spark executor),要把它调大,否则任务申请超过8GB会直接被拒。我一般把它设成不超过单NM总内存的80%,比如总内存12GB就设成9216MB,留点余量给AM和其他小容器。

3.3 NodeManager本地目录与日志的规划

yarn.nodemanager.local-dirs指定容器本地工作目录,容器运行时的临时数据、中间结果都放这。默认是/tmp下的路径,强烈建议改掉,因为/tmp在很多系统上会被定期清理,容器跑到一半目录被删直接崩。我习惯单独挂一块盘或者指定一个独立目录,比如/data/yarn/local,并且配多个目录用逗号分隔来分摊IO压力。

yarn.nodemanager.log-dirs是容器日志目录,同理别放/tmp。日志目录会随着任务增多快速膨胀,建议单独规划空间并配好清理策略。YARN本身有日志聚合功能(yarn.log-aggregation-enable设为true),把容器日志汇总到HDFS上,本地只留短期,这个在生产环境基本必开,否则本地磁盘很快被日志撑爆。

还有一个yarn.nodemanager.disk-health-checker相关的健康检查,默认当本地目录可用空间低于阈值时NM会标记为不健康、不再接收新容器。这个机制是保护性的,但阈值默认比较激进,磁盘稍微紧张一点NM就“罢工”。我一般会把yarn.nodemanager.disk-health-checker.max-disk-utilization-per-disk-percentage适当调高到90左右,同时保证监控到位,别让它真的写满。

3.4 mapred-site.xml与YARN的衔接

虽然本文主题是YARN,但要让MapReduce任务真正跑在YARN上,mapred-site.xml里的mapreduce.framework.name必须设为yarn。这一项不配,MR会用本地模式跑,看起来任务成功了,其实根本没用到集群资源,很多人被这个“假成功”骗过。

另外mapreduce.application.classpath和yarn.app.mapreduce.am.env这类环境变量配置,在跨节点部署时容易因为路径不一致导致AM起不来。我的做法是所有节点的Hadoop安装路径保持完全一致,这样这些路径配置可以统一写死,省掉大量环境差异带来的问题。如果实在没法统一路径,就得用变量或者逐节点调整,维护成本会高很多。

4. 实操过程与核心环节落地

4.1 节点规划与基础环境准备

我按一个最小的可用集群来演示:三台机器,主机名分别规划为master、node1、node2。master上放ResourceManager和NameNode,node1、node2上放NodeManager和DataNode。这个布局是存算一体的典型小集群形态。

第一步是基础环境,三台机器都要做:统一主机名并在/etc/hosts里互相写全映射;关闭防火墙或者放行前面表格里的端口(测试环境我一般直接关防火墙省事,生产环境按端口放行);配置节点间免密登录,master要能免密ssh到node1、node2,因为启动脚本是从master分发出去的;安装一致的JDK版本,JAVA_HOME在三台机器上指向同一个路径。

这里有个细节:时间同步。三台机器时间差太大时,RM和NM之间的心跳会出问题,表现为NM频繁被标记为lost。测试环境手动date -s对齐一下,生产环境配好时间同步服务。这个坑很隐蔽,因为进程都起着,就是任务调度异常。

4.2 配置文件的分发与一致性校验

配置我集中在master上改,改完用scp分发到node1、node2。需要改的文件是core-site.xml、hdfs-site.xml(HDFS部分,本文假设已可用)、yarn-site.xml、mapred-site.xml,以及hadoop-env.sh里的JAVA_HOME。

yarn-site.xml的核心内容我按前面讲的参数填好,重点确认yarn.resourcemanager.hostname写的是master,yarn.nodemanager.aux-services是mapreduce_shuffle,内存和CPU参数按机器实际情况填。分发完成后,一定要在三台机器上分别diff一下配置文件,确认完全一致。我遇到过scp漏传一个文件、导致某台NM用的是默认配置、内存报了个超大值把RM搞懵的情况,一致性校验这一步别省。

hadoop-env.sh里除了JAVA_HOME,建议显式设置YARN_RESOURCEMANAGER_OPTS和YARN_NODEMANAGER_OPTS的堆大小。默认值在小集群够用,但机器多、任务多时RM的堆会吃紧,我一般给RM配2GB、NM配1GB起步,根据规模再调。

4.3 启动顺序与进程验证

启动顺序有讲究:先起HDFS(start-dfs.sh在master上执行),确认NameNode和DataNode都正常,再起YARN(start-yarn.sh在master上执行)。YARN依赖HDFS的地方不多,但日志聚合等功能需要HDFS可用,先起HDFS能避免一些初始化报错。

start-yarn.sh执行后,master上应该有ResourceManager进程,node1、node2上各有NodeManager进程。用jps逐个确认。然后打开http://master:8088看RM的Web UI,重点看左侧的Nodes页面,确认所有NM都处于RUNNING状态,且上报的内存、核数和你在配置文件里写的一致。如果某个NM没出现或者状态不对,先看它本地的NM日志,通常是连不上RM(端口或主机名问题)或者本地目录权限问题。

我习惯在启动后立刻提交一个最简单的MapReduce示例任务(Hadoop自带的wordcount或者pi估算),观察它从ACCEPTED到RUNNING再到FINISHED的完整流转。这一步能一次性验证RM调度、NM启动容器、AM申请资源、Shuffle服务这一整条链路是否通畅。任务卡在ACCEPTED通常是资源不够(内存参数配小了或者被其他任务占着),卡在RUNNING很久则是容器内部的问题,得去看具体容器的日志。

4.4 一个可复现的最小配置样例

为了让你有个直接能对照的起点,我把yarn-site.xml的关键片段按一台16GB、8核的存算一体节点写出来。注意这只是起点,实际要按你的机器调整。

<configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>master</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.nodemanager.resource.memory-mb</name> <value>12288</value> </property> <property> <name>yarn.nodemanager.resource.cpu-vcores</name> <value>8</value> </property> <property> <name>yarn.scheduler.minimum-allocation-mb</name> <value>1024</value> </property> <property> <name>yarn.scheduler.maximum-allocation-mb</name> <value>9216</value> </property> <property> <name>yarn.nodemanager.local-dirs</name> <value>/data/yarn/local</value> </property> <property> <name>yarn.nodemanager.log-dirs</name> <value>/data/yarn/log</value> </property> <property> <name>yarn.log-aggregation-enable</name> <value>true</value> </property> </configuration>

配套的mapred-site.xml至少要有mapreduce.framework.name为yarn,以及yarn.app.mapreduce.am.env里把HADOOP_MAPRED_HOME指到Hadoop安装目录。这两项配好,MR任务才会真正走YARN。

5. 常见问题与排查技巧实录

5.1 任务一直卡在ACCEPTED不动

这是YARN部署后最高频的问题。ACCEPTED意味着RM收到了应用、但还没分配到资源启动AM。排查顺序我总结成三步:先看RM的Web UI里集群总资源和已用资源,如果总资源本身就很小或者已用接近总量,那就是资源不够,回头检查NM上报的内存是不是配小了、或者有僵尸任务占着资源;再看调度器类型,默认Capacity Scheduler有队列容量限制,单队列用满后新任务排队,可以调队列容量或者换队列;最后看是不是AM所需资源超过了单节点能提供的上限,比如AM要2GB但maximum-allocation-mb配得比这还小,那永远分配不出来。

我踩过最隐蔽的一次是:NM上报的内存正常,但yarn.scheduler.maximum-allocation-mb配成了512MB,而AM默认要1536MB,结果所有任务都卡在ACCEPTED。这个参数和NM总内存是两回事,别混淆。

5.2 NodeManager频繁掉线或显示UNHEALTHY

NM掉线先看它和RM之间的心跳。常见原因有三个:网络或端口不通(8032、8031被拦)、时间不同步导致心跳超时判断异常、本地磁盘健康检查不通过。前两个前面提过,重点说第三个。当local-dirs或log-dirs所在磁盘可用空间低于阈值,NM会主动标记自己不健康。去NM日志里搜disk相关的WARN,能看到具体是哪个目录、剩余多少。解决办法要么清理磁盘,要么调整健康检查阈值,但调阈值只是缓解,根子上还是要保证磁盘空间,否则容器写到一半磁盘满了更麻烦。

还有一种掉线是内存超卖导致的。如果NM上报的内存比实际可用多,容器一多系统就OOM,NM进程被系统杀掉,表现就是“莫名其妙掉线”。这种去系统日志(dmesg或/var/log/messages)里能看到OOM Killer的记录,对上时间点就能确认。

5.3 容器报“beyond physical memory limits”被 kill

这个报错的意思是容器实际用的物理内存超过了申请值。YARN默认会监控容器内存,超了直接杀。原因通常是任务本身内存估算不足,或者JVM堆外内存(比如直接内存、线程栈)没算进去。解决思路:调大任务申请的内存,或者给JVM配好-Xmx让它别无限涨。如果是MapReduce任务,调mapreduce.map.memory.mb和对应的JVM堆参数;Spark任务则调executor内存和spark.memory.overhead。别简单地把监控关掉(yarn.nodemanager.pmem-check-enabled设为false),那只是把问题藏起来,机器该OOM还是OOM。

5.4 常见问题速查表

现象最可能原因快速定位处理方向
任务卡ACCEPTED资源不足或AM超上限看8088集群资源页调内存参数或队列容量
NM不出现/掉线端口不通或时间不同步NM日志、jps、dmesg放行端口、同步时间
NM UNHEALTHY磁盘空间不足NM日志搜disk清磁盘或调阈值
容器被kill内存超申请值容器日志、系统OOM记录调大申请内存、配JVM堆
Shuffle失败aux-services没配任务日志搜shuffle配mapreduce_shuffle
UI打不开8088未放行或RM没起jps看RM进程起RM、放行端口

5.5 几条压箱底的实操心得

第一条,部署完先别急着跑业务任务,用自带示例把链路走通。Hadoop自带的pi估算或者wordcount,资源需求小、逻辑简单,跑通了说明RM、NM、AM、容器、Shuffle整条链路没问题,再上业务任务排查范围就小很多。

第二条,所有参数改动都记下来,改一个测一个。YARN参数之间有关联,一次改五六个,出问题根本不知道是哪个引起的。我习惯维护一个变更记录,写清楚改了什么、为什么改、改完现象如何,这个习惯在集群规模变大后救过我好几次。

第三条,日志目录和本地目录一定单独规划、别放系统盘。容器临时数据和日志的写入量比想象中大,放系统盘很容易把根分区写满,根分区一满整个机器各种服务都出问题,排查起来非常痛苦。

第四条,小集群别过度追求参数最优。刚部署时用保守参数(内存少报一点、CPU按物理核配),跑稳定了再根据监控数据逐步调优。一上来就追求“榨干每一滴资源”,往往换来的是频繁的容器被杀和NM掉线,得不偿失。

这套部署路径我在几套不同规模的环境里都走过,三台的小集群和十几台的稍大规模,核心逻辑是一样的:把资源账算清楚、把通信链路打通、用示例任务验证、再逐步调优。YARN本身不复杂,复杂的是它和机器实际资源、和上层计算框架之间的那层“账”,账算明白了,部署就顺了。后面如果要往生产走,RM高可用和更细的队列规划是自然的下一步,但那是建立在这套单RM集群已经稳稳跑起来的基础之上的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询