本文是大数据系列第 71 篇,介绍 Spark 集群的核心架构组成、四种部署模式的选型对比,以及静态/动态资源管理策略。
核心架构组件
Spark 集群由三类关键角色构成:Driver Program、Cluster Manager 和 Executor。
Driver Program
Driver 是 Spark 应用的入口和控制中心,负责以下三项核心工作:
- SparkContext 管理:创建并维护 SparkContext,提供与集群的连接、RDD 操作接口和作业调度能力
- 任务调度:将用户代码转换为 DAG(有向无环图)执行计划,再拆分为 Stage 和 Task 分发给 Executor
- 执行监控:追踪任务成功/失败状态,负责失败重试和资源释放
Driver 的完整生命周期包括:初始化 → 执行 → 结果处理 → 资源清理。
Cluster Manager
Cluster Manager 负责整个集群的资源分配与任务协调。Spark 支持四种主流资源管理器:
| Manager | 适用场景 | 核心特性 |
|---|---|---|
| Standalone | 开发/测试环境 | 部署简单,无额外依赖 |
| YARN | 企业大数据平台 | 深度集成 Hadoop,支持多租户 |
| Mesos | 混合负载集群 | 细粒度调度,水平扩展性强 |
| Kubernetes | 云原生应用 | 容器编排,支持弹性伸缩 |
生产环境中,与 Hadoop 共存的集群通常选择 YARN;云原生场景优先选择 Kubernetes。
Executor
Executor 是运行在 Worker 节点上的 JVM 进程,负责:
- 执行 Driver 分配的 Task
- 将中间计算结果缓存在内存中以加速迭代计算
- 将最终结果写回 HDFS 或返回给 Driver
部署模式
Local 模式
在单台机器上运行,无需集群,适合本地开发和调试:
spark-shell --master local[*] # 使用所有 CPU 核心
spark-shell --master local[4] # 使用 4 个线程
Cluster 模式(Client vs Cluster)
提交到真实集群时,有两种子模式:
- Client 模式:Driver 运行在提交任务的客户端节点,日志直接输出到终端,适合交互式调试
- Cluster 模式:Driver 运行在集群内部节点,客户端断连不影响作业执行,适合生产环境
# Client 模式提交
spark-submit --master yarn --deploy-mode client --class icu.wzk.App app.jar
# Cluster 模式提交
spark-submit --master yarn --deploy-mode cluster --class icu.wzk.App app.jar
集群启动流程
启动 Hadoop 集群
start-all.sh
启动 Spark Standalone 集群
cd /opt/servers/spark-2.4.5/sbin
./start-all.sh
启动后访问 http://<master-ip>:8080 查看 Spark Master Web UI。
验证集群状态
# 运行内置 Pi 示例,验证集群正常
run-example SparkPi 10
资源管理策略
静态资源分配
在配置文件或提交命令中预先指定固定资源量:
spark-submit \
--executor-memory 4g \
--executor-cores 2 \
--num-executors 10 \
--class icu.wzk.App app.jar
适合资源独占、负载稳定的批处理场景。
动态资源分配
根据实际工作负载自动伸缩 Executor 数量,在 spark-defaults.conf 中开启:
spark.dynamicAllocation.enabled=true
spark.dynamicAllocation.minExecutors=2
spark.dynamicAllocation.maxExecutors=20
spark.dynamicAllocation.executorIdleTimeout=60s
适合资源共享、负载波动的交互式或流处理场景,避免资源空闲浪费。
监控与调优
- Spark UI(端口 4040):查看 Job、Stage、Task 执行状态和数据倾斜情况
- History Server:持久化已完成作业的执行日志,方便事后分析
- Ganglia/Prometheus:集群级别的 CPU、内存、网络监控
合理配置并行度(spark.default.parallelism)和序列化方式(Kryo vs Java)是常见的两个调优入口。