三、Spark 运行环境部署:全面掌握四种核心模式
作者:IvanCodes
日期:2025年7月25日
专栏:Spark教程
Apache Spark 作为统一的大数据分析引擎,以其高性能和灵活性著称。要充分利用Spark的强大能力,首先需要根据不同的应用场景和资源环境,正确地部署其运行环境。本教程将详细指导您如何下载 Spark,并逐步解析和部署其四种核心运行模式。
一、下载 Apache Spark
在进行任何部署之前,我们首先需要获取 Spark 的安装包。
- 访问 Spark 官方网站
- 打开您的浏览器,访问 Apache Spark 官方网站:
https://spark.apache.org/
- 在网站的导航栏中,您会看到一个醒目的 “Download” 链接。
- 打开您的浏览器,访问 Apache Spark 官方网站:
- 在下载页面选择版本和包类型
- 点击 “Download” 链接后,您将进入下载配置页面。
- 步骤 1 (Choose a Spark release): 选择您需要的 Spark 版本。根据您的截图,我们选择 3.5.6 (请以官网实际为准)。
- 步骤 2 (Choose a package type): 选择包类型。对于大多数情况,特别是与Hadoop集成的环境,选择预编译好的版本是最方便的。例如,选择
Pre-built for Apache Hadoop 3.3 and later
。 - 步骤 3 (Download Spark): 点击生成的下载链接。
- 从镜像站点下载二进制包
- 点击上一步的链接后,您会被引导至一个包含多个下载镜像的页面。
- 选择页面顶部建议的主下载链接进行下载。
- 将下载好的二进制包 (例如
spark-3.5.6-bin-hadoop3.tgz
) 上传到您的操作服务器 (例如hadoop01
) 的/export/software
目录下。
- 解压安装包 (在 hadoop01 操作)
- 目标安装路径为
/export/server
,并重命名为spark
。
- 目标安装路径为
mkdir -p /export/server
cd /export/softwares
tar -zxvf spark-3.5.6-bin-hadoop3.tgz -C /export/server/
cd /export/server
mv spark-3.5.6-bin-hadoop3 spark
二、Spark 四种核心运行模式详解与部署
2.1 Local 模式 (本地模式)
特点与用途:
所谓的 Local 模式,就是不需要任何集群节点资源,仅在单台机器上就能执行 Spark 代码的环境。它非常适合用于教学、快速原型开发、调试和单元测试。在此模式下,所有Spark组件 (Driver, Executor) 都在同一个JVM进程中以多线程的方式运行。
部署与运行步骤:
- 启动 Local 环境 (Spark Shell)
- 进入解压并重命名后的 Spark 目录,执行
spark-shell
启动一个交互式的Scala环境。
- 进入解压并重命名后的 Spark 目录,执行
cd /export/server/spark
bin/spark-shell
- 启动成功后,您会看到 Spark 的欢迎信息,并进入 Scala 提示符
scala>
。
- 访问 Web UI 监控页面
- 当
spark-shell
或任何Spark应用在 Local 模式下运行时,它会启动一个内嵌的 Web UI 用于监控任务执行情况。 - 默认端口是
4040
。在浏览器中访问:http://hadoop01:4040
(请将hadoop01
替换为您的实际主机名或IP)。
- 当
- 在命令行工具中执行代码
- 在
spark-shell
中,可以直接执行 Spark 代码。例如,我们可以对一个文本文件进行词频统计。首先,在data
目录下创建一个word.txt
文件。
- 在
cd /export/server/spark
mkdir Data
echo "hello spark hello world" > Data/wordcount.txt
- 然后在已启动的
spark-shell
中执行:
sc.textFile("data/word.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect
-
退出 Local 模式
- 在
spark-shell
中,按Ctrl+C
组合键,或输入Scala命令:quit
。
- 在
-
通过
spark-submit
提交应用- 除了交互式运行,也可以提交打包好的应用程序。
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master local[2] \
./examples/jars/spark-examples_*.jar \
5
- 参数解析:
--class
: 指定要执行的主类。--master local[2]
: 明确指定使用Local模式,并分配2
个CPU核心。local[*]
表示使用所有可用核心。./examples/jars/spark-examples_*.jar
: 应用程序所在的JAR包。5
: 传递给应用程序主函数的参数。
2.2 Standalone 模式 (独立部署模式)
特点与用途:
Standalone 模式是 Spark 自带的、完整的集群资源管理框架,采用经典的 Master-Slave 架构。它独立于其他资源管理器 (如YARN),部署简单,非常适合搭建专门用于运行 Spark 应用的中小型集群。
部署步骤:
- 集群规划:
hadoop01
: Master, Workerhadoop02
: Workerhadoop03
: Worker
(为了充分利用资源,Master节点通常也兼作一个Worker节点)
- 修改配置文件 (在 Master 节点
hadoop01
上操作)- 配置 Worker 节点列表 (
workers
或slaves
):
- 配置 Worker 节点列表 (
cd /export/server/spark/conf
cp workers.template workers
vim workers
编辑 workers
文件,清除原有内容,并添加所有Worker节点的主机名,每行一个:
hadoop01
hadoop02
hadoop03
- 配置环境变量 (
spark-env.sh
):
cp spark-env.sh.template spark-env.sh
vim spark-env.sh
在文件末尾添加以下内容:
export JAVA_HOME=/export/server/jdk1.8.0_361
export SPARK_MASTER_HOST=hadoop01
JAVA_HOME
: 指定JDK的安装路径。SPARK_MASTER_HOST
: 明确告知集群Master节点的主机名或IP地址。
- 分发 Spark 目录
- 将
hadoop01
上配置好的/export/server/spark
目录完整同步到所有Worker节点。
- 将
cd /export/server
scp -r spark/ root@hadoop02:/export/server/
scp -r spark/ root@hadoop03:/export/server/
- 启动 Standalone 集群
- 在 Master 节点 (
hadoop01
) 上执行一键启动脚本。
- 在 Master 节点 (
cd /export/server/spark
sbin/start-all.sh
- 此脚本会启动
hadoop01
上的 Master 进程,并根据workers
文件的内容,通过SSH远程启动所有Worker节点上的 Worker 进程。
- 验证集群状态
- 在所有节点上执行
jps
命令。hadoop01
应有Master
和Worker
进程,hadoop02
和hadoop03
应有Worker
进程。 - 访问 Master Web UI: 在浏览器中打开
http://hadoop01:8080
(默认端口)。
- 在所有节点上执行
- 提交应用到 Standalone 集群
cd /export/server/spark
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop01:7077 \
./examples/jars/spark-examples_*.jar \
10
--master spark://hadoop01:7077
: 指定连接到 Standalone Master 的地址。7077
是Master接收客户端连接的默认端口。
Standalone 模式高级配置:
- 配置历史服务 (History Server)
- 问题: Spark 应用运行结束后,其在
4040
端口的UI会随之关闭,无法查看历史任务的执行详情。 - 解决方案: 配置历史服务器,将应用运行日志持久化到HDFS,并通过一个常驻服务来展示这些历史记录。
- 步骤:
- 启动 HDFS。
- 创建 HDFS 日志目录:
hadoop fs -mkdir /spark-logs
- 修改
spark-defaults.conf
(在conf
目录下创建):
- 问题: Spark 应用运行结束后,其在
cp spark-defaults.conf.template spark-defaults.conf
hdfs dfs -mkdir /spark-logs
vim spark-defaults.conf
添加:
spark.eventLog.enabled true
spark.eventLog.dir hdfs://hadoop01:9000/spark-logs
spark.history.fs.logDirectory hdfs://hadoop01:9000/spark-logs
- 修改
spark-env.sh
:
添加:
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=18080 -Dspark.history.fs.logDirectory=hdfs://hadoop01:9000/spark-logs -Dspark.history.retainedApplications=50"
- 分发配置文件到所有节点。
cd /export/server/spark/
scp -r conf/ root@hadoop02:/export/server/spark/conf/
scp -r conf/ root@hadoop03:/export/server/spark/conf/
- 启动历史服务 (在
hadoop01
上):
sbin/start-history-server.sh
- 访问历史服务 Web UI:
http://hadoop01:18080
高可用部署步骤:
- 集群规划:
hadoop01
: Spark Master (主), ZooKeeper Server, Worker
hadoop02
: Spark Master (备), ZooKeeper Server, Worker
hadoop03
: ZooKeeper Server, Worker
1. 确保 ZooKeeper 集群正常运行
在进行 Spark HA 配置前,您必须拥有一个正在稳定运行的 ZooKeeper 集群。请确保在 hadoop01
, hadoop02
, hadoop03
上的 ZooKeeper 服务已经启动(如果还没有配置,可以查看往期文章《二、ZooKeeper 集群部署搭建》)
- 可以通过在每个节点执行
zkServer.sh status
来验证 ZooKeeper 集群的状态。
2. 停止现有的 Standalone 集群
- 如果在进行此配置前,您已经启动了普通的 Standalone 集群,请务必先停止它。
cd /export/server/spark
sbin/stop-all.sh
3. 修改 spark-env.sh
配置文件 (在所有Spark节点)
- 这是配置 HA 的核心步骤。我们需要修改所有 Spark 节点 (
hadoop01
,hadoop02
,hadoop03
) 上的/export/server/spark/conf/spark-env.sh
文件。 - 首先,注释掉或删除 之前为普通 Standalone 模式配置的
SPARK_MASTER_HOST
和SPARK_MASTER_PORT
(如果存在)。
# SPARK_MASTER_HOST=hadoop01
# SPARK_MASTER_PORT=7077
- 然后,添加以下 用于启用 ZooKeeper 恢复模式的配置:
export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=hadoop01:2181,hadoop02:2181,hadoop03:2181 -Dspark.deploy.zookeeper.dir=/spark"
4. 分发配置文件
- 将在
hadoop01
上修改好的spark-env.sh
同步到hadoop02
和hadoop03
,确保所有节点的配置完全一致。
cd /export/server/spark/conf
scp spark-env.sh root@hadoop02:/export/server/spark/conf/
scp spark-env.sh root@hadoop03:/export/server/spark/conf/
5. 启动 HA 集群
- 与普通 Standalone 不同,HA 模式下我们不能简单地使用
start-all.sh
来启动所有 Master。我们需要手动在规划为 Master 的每个节点上分别启动 Master 进程。 - 在
hadoop01
上启动第一个 Master:
zkServer.sh start
cd /export/server/spark
sbin/start-master.sh
- 在
hadoop02
上启动第二个 Master:
# 首先登录到 hadoop02
ssh hadoop02
zkServer.sh start
cd /export/server/spark
sbin/start-master.sh
- 启动后,这两个 Master 会通过 ZooKeeper 进行Leader选举,其中一个会成为 Active,另一个则成为 Standby。
- 最后,在任意一个 Master 节点 (例如
hadoop01
) 上启动所有 Worker 节点:
# 确保 workers 文件中包含了所有 Worker 节点 (hadoop01, hadoop02, hadoop03)
cd /export/server/spark
sbin/start-workers.sh # 或者 sbin/start-all.sh 也可以,它会智能地只启动workers
6. 验证 HA 集群状态
- 查看进程:在
hadoop01
和hadoop02
上执行jps
,都应该看到Master
进程。在所有三个节点上都应该看到Worker
进程。 - 访问 Web UI:
- 分别访问两个 Master 的 Web UI:
http://hadoop01:8081
和http://hadoop02:8081
。 - 你会发现其中一个页面的状态 (Status) 显示为
ALIVE
,这是 Active Master。 - 另一个页面的状态显示为
STANDBY
,这是 Standby Master。 - 两个页面上都应该能看到所有活跃的 Worker 节点。
- 分别访问两个 Master 的 Web UI:
7. 提交应用到 HA 集群
- 提交应用时,
--master
参数需要指定所有 Master 节点的地址,用逗号分隔。
cd /export/server/spark
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop01:7077,hadoop02:7077 \
./examples/jars/spark-examples_*.jar \
5
- 客户端会首先尝试连接列表中的第一个 Master (
hadoop01:7077
)。如果它不是 Active Master,客户端会被重定向到当前真正的 Active Master。如果第一个 Master 挂了,客户端会自动尝试连接列表中的下一个 Master (hadoop02:7077
)。
2.3 YARN 模式 (推荐)
特点与用途:
YARN 模式是将 Spark 作为一个应用程序运行在现有的 Hadoop YARN 集群之上。YARN 负责统一的资源分配和调度。这是生产环境中最主流、最健壮的部署模式,因为它实现了与Hadoop生态中其他计算框架 (如MapReduce) 的资源共享、统一权限管理和高可用性。
部署与配置步骤:
第一步:配置 YARN 核心文件
这是最关键的一步。我们需要一次性完成对 YARN 的资源定义和基础服务配置。
在 hadoop01
上,编辑 yarn-site.xml
文件:
vim /export/server/hadoop/etc/hadoop/yarn-site.xml
在 <configuration>
和 </configuration>
标签之间,确保包含以下所有属性:
<!-- 定义每个NodeManager节点可用于分配给容器的总物理内存 (单位MB) -->
<!-- 这个值应该根据你机器的实际物理内存来设置,通常是物理内存的70%-80% -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>8192</value> <!-- 示例值: 8GB -->
</property><!-- 定义每个NodeManager节点可用于分配给容器的总虚拟CPU核心数 -->
<!-- 通常设置为机器的CPU核心数或超线程数 -->
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>8</value> <!-- 示例值: 8核 -->
</property><!-- 启用YARN的辅助服务 (aux-service) 功能,为Spark Shuffle Service做准备 -->
<!-- 保留 mapreduce_shuffle 以兼容MapReduce作业 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property><!-- (推荐) 关闭YARN对物理内存和虚拟内存的严格检查 -->
<!-- Spark有自己的内存管理机制,YARN的严格检查可能误杀正常运行的Spark Executor -->
<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 “植入” Spark 依赖
这是我们解决 ClassNotFoundException
的最终方案,远比修改环境变量更可靠。
- 在
hadoop01
上,找到 Spark for YARN 的核心 Jar 包:
ls /export/server/spark/jars/spark-yarn_*.jar
- 将这个 Jar 包物理复制到所有节点的 YARN 核心库目录中:
# (请将下面的文件名替换为您上一步找到的真实文件名, 如 spark-yarn_2.12-3.5.6.jar)
# 复制到 hadoop01
cp /export/server/spark/jars/spark-yarn_*.jar /export/server/hadoop/share/hadoop/yarn/lib/# 复制到 hadoop02
scp /export/server/spark/jars/spark-yarn_*.jar root@hadoop02:/export/server/hadoop/share/hadoop/yarn/lib/# 复制到 hadoop03
scp /export/server/spark/jars/spark-yarn_*.jar root@hadoop03:/export/server/hadoop/share/hadoop/yarn/lib/
为什么这么做?
将 spark-yarn
Jar 包直接放入 YARN 的 classpath
中,可以确保 YARN NodeManager 在启动 Spark 的 Shuffle Service
或其他 Spark 组件时,总能找到所需的类,从根本上解决类加载问题。
第三步:配置 Spark 客户端
现在轮到 Spark 了,我们只需要告诉它 Hadoop 的配置文件在哪里。
在 hadoop01
上,编辑 spark-env.sh
文件:
vim /export/server/spark/conf/spark-env.sh
在文件末尾添加 (如果不存在的话):
export HADOOP_CONF_DIR=/export/server/hadoop/etc/hadoop
第四步:分发配置并重启 YARN
- 精确分发
yarn-site.xml
:
scp /export/server/hadoop/etc/hadoop/yarn-site.xml root@hadoop02:/export/server/hadoop/etc/hadoop/
scp /export/server/hadoop/etc/hadoop/yarn-site.xml root@hadoop03:/export/server/hadoop/etc/hadoop/
- 重启 YARN 服务:
cd /export/server/hadoop/sbin/
./stop-yarn.sh
./start-yarn.sh
第五步:验证与排错指南 (核心)
- 验证所有进程:
jps
ssh hadoop02 "jps"
ssh hadoop03 "jps"
确保 ResourceManager
在主节点上运行,并且所有节点上都有 NodeManager
进程。
- 排错指南:如果 NodeManager 没有启动
- 立即登录 到启动失败的那个节点 (例如
ssh hadoop02
)。 - 立刻查看 该节点的 NodeManager 日志文件,查找 ERROR 信息。这是定位问题的唯一途径。
- 立即登录 到启动失败的那个节点 (例如
# (请根据ls的真实文件名调整)
tail -n 200 /export/server/hadoop/logs/yarn-root-nodemanager-hadoop02.log
- 常见错误包括:
yarn-site.xml
配置语法错误、spark_shuffle
服务类找不到 (说明第二步Jar包没放对位置或没分发)、端口冲突等。
第六步:提交应用到 YARN
(这部分与之前版本相同,仅作展示)
- YARN-Client 模式 (
--deploy-mode client
)
cd /export/server/spark
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode client \
./examples/jars/spark-examples_*.jar \
5
- YARN-Cluster 模式 (
--deploy-mode cluster
)
cd /export/server/spark
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
./examples/jars/spark-examples_*.jar \
5
监控与验证:
提交应用后,访问 YARN ResourceManager 的 Web UI: http://hadoop01:8088
。
2.4 Windows 模式 (本地开发)
特点与用途:
这本质上就是在Windows操作系统上运行Spark的Local模式。它的初衷是方便开发者在不启动虚拟机的情况下,进行本地开发和功能测试。然而,这条看似便捷的道路,实际上充满了挑战,极易遇到各种匪夷所思的环境兼容性问题。
纯 PowerShell 配置
网上的许多教程会指导您通过图形界面 (GUI) 点击“我的电脑”->“属性”->“高级系统设置”来手动添加环境变量。这种方法不仅繁琐,而且极易出错 (比如,在Path
变量中漏掉分号,或者路径复制错误)。
本教程将完全摒弃这种原始方式,采用纯 PowerShell 代码来完成所有环境配置。
部署步骤:
第一步:准备一个纯净的Java 环境
Java 是 Spark 的生命之基,它的配置正确与否,决定了我们能否打赢这场战争。
- 安装 Java (JDK):
- Spark 3.5.x 与 Java 8, 11, 17 兼容。为避免任何兼容性问题,推荐使用命令行安装一个纯净的、久经考验的 Eclipse Temurin 8 (LTS) 版本。
- 以管理员身份打开 PowerShell,执行:
winget install -e --id EclipseAdoptium.Temurin.8.JDK
- 配置环境变量 (纯 PowerShell 方式):
- 安装后,必须 关闭并重新打开一个新的管理员 PowerShell 窗口,以加载系统路径。
- 在新窗口中,执行以下命令,完成
JAVA_HOME
和Path
的配置(请根据您机器上实际的安装路径和版本号进行修改):
# 设置 JAVA_HOME (请 double check 这个路径是否存在)
# 'Machine' 表示这是一个系统级别的环境变量,对所有用户生效
[System.Environment]::SetEnvironmentVariable('JAVA_HOME', 'C:\Program Files\Eclipse Adoptium\jdk-8.0.422.8-hotspot', 'Machine')# 将 JAVA_HOME\bin 添加到系统 Path
$javaBinPath = [System.Environment]::GetEnvironmentVariable('JAVA_HOME', 'Machine') + '\bin'
$oldPath = [System.Environment]::GetEnvironmentVariable('Path', 'Machine')
[System.Environment]::SetEnvironmentVariable('Path', "$oldPath;$javaBinPath", 'Machine')
- 最终验证: 再次关闭并重新打开一个普通的 PowerShell 窗口,执行
java -version
。如果成功显示版本,说明地基已打好。
第二步:部署 Spark 与 Hadoop“辅助工具”
本方法的详细步骤,请参考《二、Spark 开发环境搭建 IDEA + Maven 及 WordCount 案例实战》里面的第三部分
-
解压 Spark:
- 将 Spark 二进制包 (例如
spark-3.5.6-bin-hadoop3.tgz
) 解压到一个绝对不能包含中文、空格或特殊字符的纯英文路径,例如E:\spark
。
- 将 Spark 二进制包 (例如
-
配置
winutils.exe
(决战的开始):- Spark 依赖 Hadoop 的代码,而 Hadoop 在 Windows 上需要
winutils.exe
和hadoop.dll
这两个“翻译官”来模拟 Linux 的文件权限和操作。 - 在 这个 GitHub 仓库 (例如
cdarlint/winutils
) 中,找到与您的 Spark 预编译时所用的 Hadoop 版本相匹配的winutils.exe
和hadoop.dll
。例如,spark-3.5.6-bin-hadoop3
意味着您需要 Hadoop 3.x 的版本。 - 创建一个目录,例如
E:\hadoop\bin
。 - 将下载的
winutils.exe
和hadoop.dll
放入E:\hadoop\bin
目录下。
- Spark 依赖 Hadoop 的代码,而 Hadoop 在 Windows 上需要
-
配置
HADOOP_HOME
环境变量 (纯 PowerShell 方式):- 打开一个新的管理员 PowerShell 窗口。
第三步:迎接最终的考验 —— 启动 Spark
-
重启 PowerShell:
- 为了加载刚刚设置的
HADOOP_HOME
,请再次打开一个全新的 PowerShell 窗口。
- 为了加载刚刚设置的
-
进入
bin
目录:
cd E:\spark\bin
- 执行启动命令:
.\spark-shell.cmd
- 必须使用
.\
,这是 PowerShell 的安全规则,表示执行当前目录下的脚本。
此时,您将直面命运的审判。如果一切顺利 (Java配置无误,winutils.exe
版本匹配且路径正确),Spark Shell 将成功启动,不会出现 NullPointerException
, FileNotFoundException
或找不到 winutils
的红色错误信息。
如果失败了怎么办?
- 仔细阅读错误信息,99% 的问题都与
JAVA_HOME
路径错误、HADOOP_HOME
未设置或winutils.exe
版本不匹配有关。 - 回到前面的步骤,逐一检查每个路径和环境变量是否完全正确。
- 最终,考虑“郑重警告”中的建议。
总结
- Local: 学习、开发、测试的最佳选择,简单快捷。
- Standalone: 快速搭建专用的Spark集群,独立性强。
- YARN: 与Hadoop生态深度集成,是企业级生产环境的标准部署模式。
- Windows: 方便Windows用户进行本地开发,核心是正确配置
winutils
。