前置准备
在开始搭建 Spark on YARN 集群之前,请确保以下条件已满足:
- 三台节点(
master、slave1、slave2)之间已配置 SSH 免密登录; - 三台节点的
/etc/hosts已配置主机名与 IP 的映射关系; - Hadoop 3.1.4 集群已部署完成,且 YARN 的 ResourceManager 运行在
slave1节点; - JDK 1.8 已安装并配置好
JAVA_HOME环境变量。
💡 若尚未完成 Hadoop 集群部署,请先参考 Hadoop 集群搭建文档,确保 HDFS 与 YARN 均能正常启动。
环境信息
- Spark:spark‑3.0.3‑bin‑hadoop3.2
- Hadoop:hadoop‑3.1.4
- JDK:jdk1.8.0_161
- 集群节点:
master、slave1、slave2💡说Spark on YARN 不需要启动 Spark 自身 Master、Worker 进程**,资源全部由 YARN 调仅需启动 Spark 历史服务器,用于查看已完成任务日志。。。
1. 解压 Spark 安装包(master 节点执行)))
# 进入压缩包存放目录
cd /opt/software# 解压到 /opt/modulele
tar -zxvf spark-3.0.3-bin-hadoop3.2.tgz -C /opt/module/
# 进入安装目录,重命名
cd /opt/modul
mv spark-3.0.3-bin-hadoop3.2 sparkonyarn
2. 配置全局环境变量(master 节点)))
vi /etc/profile.d/my_env.sh
写入下面内容:
export SPARK_HOME=/opt/module/sparkonyarn
export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin
保存退出,后续同步该文件到 slave 节点。
3. 修改 YARN 配置文件 yarn-site.xml(master 节点)))
vi /opt/module/hadoop-3.1.4/etc/hadoop/yarn-site.xml
在 `<configuration>` 标签内添加配置:
``<!-- YARN WebUI 绑定所有 IP,解决宿主机无法访问 8088 页面 -->->
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>slave1:8088</value>
</property>
<!-- 关闭物理内存检查 -->
<property>
<name>yarn.nodemanager.pmem-check-enabled</name>
<value>false</value>
</property>
<!-- 物理内存:虚拟内存 = 1:4 -->
<property>
<name>yarn.nodemanager.vmem-pmem-ratio</name>
<value>4</value>
</property>
<!-- 关闭虚拟内存检查,避免测试程序被yarn杀掉 -->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
⚠️提示:生产环境不建议关闭内存检查,仅测试环境使用。
4. 修改 Spark 配置文件(master 节点))
cd /opt/module/sparkonyarn/conf
5. 配置 slaves 从节点列表
mv slaves.template slaves
vi slaves
写入主机名:
master
slave1
slave2
on-yarn 任务本身不读取 slaveses,主要供历史服务器使用。
6. 修改 spark-env.sh
mv spark-env.sh.template spark-env.sh
vi spark-env.sh
追加内容:
`
bash
`# JDK 路径路径
JAVA_HOME=/opt/module/jdk1.8.0_161
# 对接 YARN 核心配置配置
HADOOP_CONF_DIR=/opt/module/hadoop-3.1.4/etc/hadoop
YARN_CONF_DIR=/opt/module/hadoop-3.1.4/etc/hadoop
# Spark 历史服务器配置配置
export SPARK_HISTORY_OPTS="
-Dspark.history.ui.port=18080
-Dspark.history.fs.logDirectory=hdfs://master:8020/directory
-Dspark.history.retainedApplications=30"
参数说明:
| 参数 | 作用 |
|---|---|
| spark.history.ui.port | 历史服务 Web 端口 18080 |
| spark.history.fs.logDirectory | 任务日志保存到 HDFS 路径 |
| spark.history.retainedApplications | 保留 30 个任务 UI 缓存 |
7.修改 spark-defaults.conf
bash
mv spark-defaults.conf.template spark-defaults.conf
vi spark-defaults.conf
写入配置:
# 开启事件日志
spark.eventLog.enabled true
# 日志 HDFS 存储路径路径
spark.eventLog.dir hdfs://master:8020/directory
# 历史服务器地址
spark.yarn.historyServer.address master:18080
spark.history.ui.port 18080
✅ 必须提前在 HDFS 创建日志目录,否则历史服务器启动失败。失败
hdfs dfs -mkdir -p /directory
hdfs dfs -chmod 777 /directory
8. 同步所有配置到 slave1、slave2(master 执行)
8.1 同步环境变量
scp -r /etc/profile.d/my_env.sh slave1:/etc/profile.d/
scp -r /etc/profile.d/my_env.sh slave2:/etc/profile.d/
📌 slave1、slave2 两台机器分别执行,使环境变量生效
bash
source /etc/profile.d/my_env.sh
8.2 同步 Spark on YARN 整个安装目录装目录
bash
scp -r /opt/module/sparkonyarn slave1:/opt/module/
scp -r /opt/module/sparkonyarn slave2:/opt/module/
8.3 同步 YARN-site.xml
bash
scp -r /opt/module/hadoop-3.1.4/etc/hadoop/yarn-site.xml slave1:/opt/module/hadoop-3.1.4/etc/hadoop/
scp -r /opt/module/hadoop-3.1.4/etc/hadoop/yarn-site.xml slave2:/opt/module/hadoop-3.1.4/etc/hadoop/
配置同步流程如下:
#mermaid-svg-wh3jx7Enc7AesRae{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wh3jx7Enc7AesRae .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wh3jx7Enc7AesRae .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wh3jx7Enc7AesRae .error-icon{fill:#552222;}#mermaid-svg-wh3jx7Enc7AesRae .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wh3jx7Enc7AesRae .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wh3jx7Enc7AesRae .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wh3jx7Enc7AesRae .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wh3jx7Enc7AesRae .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wh3jx7Enc7AesRae .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wh3jx7Enc7AesRae .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wh3jx7Enc7AesRae .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wh3jx7Enc7AesRae .marker.cross{stroke:#333333;}#mermaid-svg-wh3jx7Enc7AesRae svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wh3jx7Enc7AesRae p{margin:0;}#mermaid-svg-wh3jx7Enc7AesRae .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wh3jx7Enc7AesRae .cluster-label text{fill:#333;}#mermaid-svg-wh3jx7Enc7AesRae .cluster-label span{color:#333;}#mermaid-svg-wh3jx7Enc7AesRae .cluster-label span p{background-color:transparent;}#mermaid-svg-wh3jx7Enc7AesRae .label text,#mermaid-svg-wh3jx7Enc7AesRae span{fill:#333;color:#333;}#mermaid-svg-wh3jx7Enc7AesRae .node rect,#mermaid-svg-wh3jx7Enc7AesRae .node circle,#mermaid-svg-wh3jx7Enc7AesRae .node ellipse,#mermaid-svg-wh3jx7Enc7AesRae .node polygon,#mermaid-svg-wh3jx7Enc7AesRae .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wh3jx7Enc7AesRae .rough-node .label text,#mermaid-svg-wh3jx7Enc7AesRae .node .label text,#mermaid-svg-wh3jx7Enc7AesRae .image-shape .label,#mermaid-svg-wh3jx7Enc7AesRae .icon-shape .label{text-anchor:middle;}#mermaid-svg-wh3jx7Enc7AesRae .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wh3jx7Enc7AesRae .rough-node .label,#mermaid-svg-wh3jx7Enc7AesRae .node .label,#mermaid-svg-wh3jx7Enc7AesRae .image-shape .label,#mermaid-svg-wh3jx7Enc7AesRae .icon-shape .label{text-align:center;}#mermaid-svg-wh3jx7Enc7AesRae .node.clickable{cursor:pointer;}#mermaid-svg-wh3jx7Enc7AesRae .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wh3jx7Enc7AesRae .arrowheadPath{fill:#333333;}#mermaid-svg-wh3jx7Enc7AesRae .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wh3jx7Enc7AesRae .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wh3jx7Enc7AesRae .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wh3jx7Enc7AesRae .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wh3jx7Enc7AesRae .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wh3jx7Enc7AesRae .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wh3jx7Enc7AesRae .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wh3jx7Enc7AesRae .cluster text{fill:#333;}#mermaid-svg-wh3jx7Enc7AesRae .cluster span{color:#333;}#mermaid-svg-wh3jx7Enc7AesRae div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wh3jx7Enc7AesRae .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wh3jx7Enc7AesRae rect.text{fill:none;stroke-width:0;}#mermaid-svg-wh3jx7Enc7AesRae .icon-shape,#mermaid-svg-wh3jx7Enc7AesRae .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wh3jx7Enc7AesRae .icon-shape p,#mermaid-svg-wh3jx7Enc7AesRae .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wh3jx7Enc7AesRae .icon-shape .label rect,#mermaid-svg-wh3jx7Enc7AesRae .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wh3jx7Enc7AesRae .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wh3jx7Enc7AesRae .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wh3jx7Enc7AesRae :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} master 节点
修改配置文件
同步环境变量
my_env.sh
同步安装目录
sparkonyarn
同步 YARN 配置
yarn-site.xml
slave1 执行 source
slave2 执行 source
slave1 生效
slave2 生效
slave1 生效
slave2 生效
`
9. 启动集群服务
启动顺序:HDFS → YARN → Spark 历史服务器服务器
bash
`# master 节点启动 Hadoopoop
start-dfs.sh
start-yarn.sh
# 启动 Spark 历史服务器服务器
cd /opt/module/sparkonyarn/sbin
./start-history-server.sh
`
访问 Web 页面b页面
- HDFS:http://master:9870
- YARN:http://slave1:8088
- Spark 历史服务器:http://master:18080
`
10. 提交Spark任务
10.1 --deploy-mode client 客户端模式
Driver 运行在提交任务的客户端机器(master),适合调试,日志直接打印控制台。控制台
spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode client \
/opt/module/sparkonyarn/examples/jars/spark-examples_2.12-3.0.3.jar 10
10.2 --deploy-mode cluster 集群模式
Driver 运行在 YARN 容器内部(NodeManager 节点),生产环境推荐;控制台看不到 Driver 日志,需要去 YARN/历史服务器查看日志看日志
spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
/opt/module/sparkonyarn/examples/jars/spark-examples_2.12-3.0.3.jar 10
client 与 cluster 模式对比式对比
| 模式 | Driver 进程位置 | 适用场景 | 日志查看 |
|---|---|---|---|
| client | 提交任务的客户端节点(master) | 开发调试 | 控制台直接输出 Driver 日志 |
| cluster | YARN 容器(NodeManager) | 生产环境 | YARN UI / Spark 历史服务器查看日志 |
| 两种部署模式的任务提交流程对比如下: |
10.3 client 模式提交流程
- 客户端(master)启动
SparkSubmit进程,在本地创建 Driver; - Driver 向 YARN 的 ResourceManager 申请资源,提交 Application;
- ResourceManager 在某个 NodeManager 节点上启动 ApplicationMaster(AM);
- AM 向 ResourceManager 申请 Executor 所需的容器资源;
- ResourceManager 分配容器,AM 在对应 NodeManager 上启动 Executor;
- Executor 反向注册到客户端本地的 Driver,Driver 分发任务并收集结果;
- 任务完成后,Driver 在客户端控制台直接打印计算结果(如
Pi is roughly ...)。
10.4 cluster 模式提交流程
- 客户端(master)仅启动
SparkSubmit进程,不创建 Driver,只负责提交 Application; - SparkSubmit 向 YARN 的 ResourceManager 提交 Application;
- ResourceManager 在某个 NodeManager 节点上启动 ApplicationMaster(AM) ,Driver 运行在 AM 内部;
- AM 向 ResourceManager 申请 Executor 所需的容器资源;
- ResourceManager 分配容器,AM 在对应 NodeManager 上启动 Executor;
- Executor 反向注册到 AM 内部的 Driver,Driver 分发任务并收集结果;
- 任务完成后,客户端控制台不会打印计算结果,需通过 YARN WebUI 或 Spark 历史服务器查看日志。
两种模式的任务提交流程对比图:
#mermaid-svg-DE5tz4LPSDlNYG0v{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DE5tz4LPSDlNYG0v .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DE5tz4LPSDlNYG0v .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DE5tz4LPSDlNYG0v .error-icon{fill:#552222;}#mermaid-svg-DE5tz4LPSDlNYG0v .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DE5tz4LPSDlNYG0v .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DE5tz4LPSDlNYG0v .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DE5tz4LPSDlNYG0v .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DE5tz4LPSDlNYG0v .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DE5tz4LPSDlNYG0v .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DE5tz4LPSDlNYG0v .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DE5tz4LPSDlNYG0v .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DE5tz4LPSDlNYG0v .marker.cross{stroke:#333333;}#mermaid-svg-DE5tz4LPSDlNYG0v svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DE5tz4LPSDlNYG0v p{margin:0;}#mermaid-svg-DE5tz4LPSDlNYG0v .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DE5tz4LPSDlNYG0v .cluster-label text{fill:#333;}#mermaid-svg-DE5tz4LPSDlNYG0v .cluster-label span{color:#333;}#mermaid-svg-DE5tz4LPSDlNYG0v .cluster-label span p{background-color:transparent;}#mermaid-svg-DE5tz4LPSDlNYG0v .label text,#mermaid-svg-DE5tz4LPSDlNYG0v span{fill:#333;color:#333;}#mermaid-svg-DE5tz4LPSDlNYG0v .node rect,#mermaid-svg-DE5tz4LPSDlNYG0v .node circle,#mermaid-svg-DE5tz4LPSDlNYG0v .node ellipse,#mermaid-svg-DE5tz4LPSDlNYG0v .node polygon,#mermaid-svg-DE5tz4LPSDlNYG0v .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DE5tz4LPSDlNYG0v .rough-node .label text,#mermaid-svg-DE5tz4LPSDlNYG0v .node .label text,#mermaid-svg-DE5tz4LPSDlNYG0v .image-shape .label,#mermaid-svg-DE5tz4LPSDlNYG0v .icon-shape .label{text-anchor:middle;}#mermaid-svg-DE5tz4LPSDlNYG0v .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DE5tz4LPSDlNYG0v .rough-node .label,#mermaid-svg-DE5tz4LPSDlNYG0v .node .label,#mermaid-svg-DE5tz4LPSDlNYG0v .image-shape .label,#mermaid-svg-DE5tz4LPSDlNYG0v .icon-shape .label{text-align:center;}#mermaid-svg-DE5tz4LPSDlNYG0v .node.clickable{cursor:pointer;}#mermaid-svg-DE5tz4LPSDlNYG0v .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DE5tz4LPSDlNYG0v .arrowheadPath{fill:#333333;}#mermaid-svg-DE5tz4LPSDlNYG0v .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DE5tz4LPSDlNYG0v .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DE5tz4LPSDlNYG0v .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DE5tz4LPSDlNYG0v .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DE5tz4LPSDlNYG0v .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DE5tz4LPSDlNYG0v .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DE5tz4LPSDlNYG0v .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DE5tz4LPSDlNYG0v .cluster text{fill:#333;}#mermaid-svg-DE5tz4LPSDlNYG0v .cluster span{color:#333;}#mermaid-svg-DE5tz4LPSDlNYG0v div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DE5tz4LPSDlNYG0v .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DE5tz4LPSDlNYG0v rect.text{fill:none;stroke-width:0;}#mermaid-svg-DE5tz4LPSDlNYG0v .icon-shape,#mermaid-svg-DE5tz4LPSDlNYG0v .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DE5tz4LPSDlNYG0v .icon-shape p,#mermaid-svg-DE5tz4LPSDlNYG0v .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DE5tz4LPSDlNYG0v .icon-shape .label rect,#mermaid-svg-DE5tz4LPSDlNYG0v .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DE5tz4LPSDlNYG0v .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DE5tz4LPSDlNYG0v .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DE5tz4LPSDlNYG0v :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} cluster 模式
客户端 SparkSubmit
仅提交 Application
向 ResourceManager 提交 Application
ResourceManager 启动 ApplicationMaster
Driver 运行在 AM 内部
AM 申请容器资源
NodeManager 启动 Executor
Executor 注册到 AM 内 Driver
通过 YARN WebUI / 历史服务器查看日志
client 模式
客户端 SparkSubmit
启动本地 Driver
向 ResourceManager 提交 Application
ResourceManager 启动 ApplicationMaster
AM 申请容器资源
NodeManager 启动 Executor
Executor 注册到本地 Driver
控制台直接输出结果
📌 核心区别:client 模式 Driver 在客户端本地,cluster 模式 Driver 在 YARN 容器内 。因此 client 模式便于调试、日志直接打印;cluster 模式适合生产环境,日志需到 YARN/历史服务器查看。
对比:
🔧 常见问题排查
1. 历史服务器启动报错:HDFS 日志目录不存在
现象 :执行 ./start-history-server.sh 后,日志报错 org.apache.hadoop.ipc.RemoteException: org.apache.hadoop.hdfs.protocol.FSException: File /directory does not exist。
原因 :spark-defaults.conf 中配置的 spark.eventLog.dir 指向的 HDFS 目录尚未创建。
解决 :在 master 节点执行以下命令创建目录并授权:
bash
hdfs dfs -mkdir -p /directory
hdfs dfs -chmod 777 /directory
✅ 创建完成后重启历史服务器即可正常启动。
2. YARN 任务报虚拟内存被 kill
现象 :提交 Spark 任务后,任务运行一段时间被 YARN 强制终止,日志中出现 Container killed by YARN for exceeding memory limits。
原因:YARN 默认开启物理内存和虚拟内存检查,测试环境下容易误杀任务。
解决 :确认 yarn-site.xml 中以下两个配置均为 false:
xml
<property>
<name>yarn.nodemanager.pmem-check-enabled</name>
<value>false</value>
</property>
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
⚠️ 修改后需重启 YARN 集群使配置生效。
3. WebUI 无法访问
现象 :浏览器无法访问 YARN WebUI(http://slave1:8088)或 Spark 历史服务器(http://master:18080)。
原因 :常见原因包括防火墙未关闭、/etc/hosts 主机名映射错误、yarn-site.xml 中 yarn.resourcemanager.webapp.address 配置错误。
解决:
bash
# 关闭防火墙(三台节点均执行)
systemctl stop firewalld
systemctl disable firewalld
# 检查 /etc/hosts 是否包含三台节点的主机名与 IP 映射
cat /etc/hosts
📌 确认
yarn-site.xml中yarn.resourcemanager.webapp.address已配置为slave1:8088,且所有节点配置已同步。
4. Spark 无法连接 YARN
现象 :提交任务时报错 ApplicationMaster is not registered 或 Failed to connect to resource manager。
原因 :HADOOP_CONF_DIR、YARN_CONF_DIR 路径配置错误,或各节点配置未同步。
解决:
bash
# 确认 spark-env.sh 中路径正确
echo $HADOOP_CONF_DIR
echo $YARN_CONF_DIR
# 确认所有节点配置已同步
scp -r /opt/module/hadoop-3.1.4/etc/hadoop/yarn-site.xml slave1:/opt/module/hadoop-3.1.4/etc/hadoop/
scp -r /opt/module/hadoop-3.1.4/etc/hadoop/yarn-site.xml slave2:/opt/module/hadoop-3.1.4/etc/hadoop/
📌 修改配置后需在
master节点重启 YARN 集群,并在slave1、slave2节点执行source /etc/profile.d/my_env.sh使环境变量生效。
5. 提交任务报 ClassNotFoundException
现象 :提交 SparkPi 任务时报错 java.lang.ClassNotFoundException: org.apache.spark.examples.SparkPi。
原因 :spark-examples_2.12-3.0.3.jar 路径错误或文件不存在。
解决:
bash
# 确认示例 jar 包存在
ls -l /opt/module/sparkonyarn/examples/jars/spark-examples_2.12-3.0.3.jar
# 若不存在,检查 Spark 安装目录是否完整
ls /opt/module/sparkonyarn/examples/jars/
``
### 6. 端口被占用
**现象**:启动历史服务器或提交任务时报错 `Address already in use`,或 WebUI 无法打开。
**原因**:`18080`、`8088`、`9870` 等端口被其他进程占用,或上次异常退出后端口未释放。
**解决**:
```bash
# 查看端口占用情况
netstat -tlnp | grep 18080
netstat -tlnp | grep 8088
# 找到占用进程后,kill 掉对应 PID
kill -9 <PID>
📌 若端口被频繁占用,可在
spark-env.sh中调整spark.history.ui.port为其他可用端口(如18081)。
7. 任务提交后一直 ACCEPTED 不运行
现象 :提交 Spark 任务后,YARN WebUI 中任务状态长时间停留在 ACCEPTED,迟迟不进入 RUNNING。
原因 :常见原因包括集群资源不足(内存/CPU 被占满)、yarn-site.xml 中 yarn.scheduler.maximum-allocation-mb 配置过小、或 NodeManager 未正常启动。
解决:
bash
# 检查 NodeManager 是否全部启动(三台节点均执行)
jps
# 查看 YARN 资源使用情况
yarn node -list -all
# 查看集群可用资源
yarn application -list
📌 若资源不足,可适当调大
yarn-site.xml中的yarn.scheduler.maximum-allocation-mb和yarn.nodemanager.resource.memory-mb,并重启 YARN 集群。
8. Executor 启动失败
现象 :任务提交后,日志中出现 ExecutorLostFailure 或 Container exited with a non-zero exit code。
原因:常见原因包括 Executor 内存配置过大超出容器限制、JVM 参数错误、或节点磁盘空间不足。
解决:
bash
# 提交任务时显式指定 Executor 内存和核数
spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
--executor-memory 1g \
--executor-cores 1 \
--num-executors 2 \
/opt/module/sparkonyarn/examples/jars/spark-examples_2.12-3.0.3.jar 10
📌 确认
spark-defaults.conf中spark.executor.memory不超过yarn.nodemanager.resource.memory-mb的可用值,并检查各节点磁盘空间(df -h)。
9. 历史服务器无法访问
现象 :浏览器无法打开 Spark 历史服务器页面(http://master:18080),或页面显示无任务记录。
原因 :历史服务器未启动、spark.eventLog.dir 与 spark.history.fs.logDirectory 配置不一致、或 HDFS 日志目录权限不足。
解决:
bash
# 确认历史服务器进程已启动
jps
# 确认 spark-defaults.conf 与 spark-env.sh 中日志目录配置一致
grep -r "logDirectory\|eventLog.dir" /opt/module/sparkonyarn/conf/
# 确认 HDFS 日志目录存在且有写权限
hdfs dfs -ls /directory
hdfs dfs -chmod 777 /directory
📌 若配置不一致,统一修改后重启历史服务器;若 HDFS 目录无权限,执行
hdfs dfs -chmod 777 /directory授权。
10. 磁盘空间不足
现象 :任务运行中报错 No space left on device,或 HDFS 写入失败。
原因:Spark 事件日志、YARN 容器日志或 HDFS 数据块占满磁盘。
解决:
bash
# 查看各节点磁盘使用情况
df -h
# 清理 Spark 历史日志目录(谨慎操作)
hdfs dfs -rm -r /directory/*
# 清理 YARN 本地日志
rm -rf /opt/module/hadoop-3.1.4/logs/userlogs/*
📌 生产环境建议配置日志滚动与定期清理策略,避免日志无限增长占满磁盘。
`
📌 若 jar 包缺失,需重新解压 Spark 安装包并同步到所有节点。步完成
11. 验证集群是否可用
集群搭建完成后,建议按以下步骤验证集群是否真正可用,确保后续任务能正常提交运行。
9.1 检查关键进程(master 节点执行)
在 master 节点执行 jps,确认以下进程均已启动:
bash
jps
预期输出(关键进程):
bash
12345 NameNode
12346 DataNode
12348 NodeManager
12349 HistoryServer
📌 说明:
ResourceManager运行在slave1节点,因此master节点的jps中不会 出现ResourceManager,需到slave1节点执行jps确认;master节点应能看到NameNode、DataNode、NodeManager、HistoryServer;- 若缺少
HistoryServer,请检查spark-env.sh中SPARK_HISTORY_OPTS配置及 HDFS 日志目录是否已创建。
在 slave1、slave2 节点分别执行 jps,确认 NodeManager 已启动:
bash
jps
预期输出(slave1 节点):
bash
23456 ResourceManager
23457 NodeManager
23458 DataNode
预期输出(slave2 节点):
bash
34567 NodeManager
34568 DataNode
12347 SecondaryNameNode
9.2 提交 SparkPi 任务验证两种模式
9.2.1 client 模式验证
在 master 节点执行:
bash
spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode client \
/opt/module/sparkonyarn/examples/jars/spark-examples_2.12-3.0.3.jar 10
预期输出(关键部分):
bash
Pi is roughly 3.141592653589793
✅ 若控制台能直接打印出
Pi is roughly ...,说明 client 模式提交成功,Driver 运行在客户端节点。
9.2.2 cluster 模式验证
在 master 节点执行:
bash
spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
/opt/module/sparkonyarn/examples/jars/spark-examples_2.12-3.0.3.jar 10
预期输出(关键部分):
bash
20/09/17 07:50:01 INFO yarn.Client: Submitting application application_1699999999999_0001
20/09/17 07:50:02 INFO yarn.Client: Application report for application_1699999999999_0001 (state: ACCEPTED)
20/09/17 07:50:05 INFO yarn.Client: Application report for application_1699999999999_0001 (state: RUNNING)
20/09/17 07:50:08 INFO yarn.Client: Application report for application_1699999999999_0001 (state: FINISHED)
📌 cluster 模式下 Driver 运行在 YARN 容器内部,控制台不会 直接打印
Pi is roughly ...,需通过 YARN WebUI 或 Spark 历史服务器查看计算结果。
8.3 通过 YARN WebUI 查看任务状态和日志
- 浏览器访问 YARN WebUI:http://slave1:8088
- 在 Active Applications 或 Finished Applications 列表中,找到刚提交的
SparkPi任务; - 点击任务 Application ID ,进入任务详情页,可查看:
- 任务运行状态 :
ACCEPTED→RUNNING→FINISHED; - 日志入口 :点击 Logs 链接,查看 Driver 与 Executor 的 stdout/stderr 日志;
- 资源使用情况:查看分配的 vCores、内存等指标。
- 任务运行状态 :
💡 若任务已结束,也可通过 Spark 历史服务器 http://master:18080 查看已完成任务的执行详情与日志。
。