☰
CDH6.2 Spark on YARN 三节点集群搭建与调优实战
2026/10/27 11:24:57 网站建设 项目流程

1. 先定版本和角色,别上来就埋头装

CDH6.2 装 Spark 集群基础环境这件事,我在不同规模的项目里搭过五六遍,每次最耗时间的都不是敲命令,而是装之前的规划。原因很实在:CDH 这套东西把 Hadoop 生态几十个组件用 Parcel 包统一管起来,CM(Cloudera Manager)负责部署、监控、配置下发,本身是个重型平台。规划错了,后面拆集群比装集群还贵。所以我习惯先把版本基本盘和角色分布钉死,再动手。

先说版本。CDH 6.2 对应的大数据底座是 Hadoop 3.0.0、Spark 2.4.0、Hive 2.1.1、ZooKeeper 3.4.5、HBase 2.1.0,CM 版本是 6.2.x。Spark 2.4 走的是 Scala 2.11 编译,执行引擎还是基于内存的 DAG 调度,没到 3.x 那一套自适应执行和动态合并的层次。这些细节看着偏门,但你在后面挑 jar 包、写--packages依赖、决定用 Python 2.7 还是 Python 3 的时候,全用得上。CDH 6.2 的 PySpark 默认绑定 Python 2.7,想换 3.x 得在 CM 里单独配spark.pyspark.python和PYSPARK_PYTHON环境变量。

1.1 这套组合解决的是什么问题

很多人问:既然可以自己拉 Apache 二进制包手撸 Spark on YARN,为什么还要上 CDH?答案取决于你的团队规模和使用场景。手撸适合一两个人维护、跑单一业务任务的场景;而 CDH 这类平台真正省事的地方在于统一了配置源、角色生命周期和监控告警。一个几十个节点的集群,节点坏了、角色迁移、配置批量下发、日志集中检索,靠人肉 ssh 是撑不住的。

从能力边界看,这套环境落成之后能覆盖的很明确:离线批量计算(Spark SQL、DataFrame 作业)、Spark Streaming 微批处理、Spark on YARN 的多种提交模式、以及与 Hive 元数据打通的数仓查询。它不适合的场景也很明确:毫秒级延迟的在线服务、超大规模参数服务器训练、需要 GPU 调度的场景。想清楚这层,你对"装完能干什么"就有底了,也不会在后期被业务方追着问为什么延迟下不去。

1.2 三节点起步的角色分配

我把最小可用集群的角色分布列成表,这是我在多个测试环境里反复验证过的组合,能跑通全流程又不至于资源打架。注意这里说的"最小可用"是指能完整走完 CM 部署、Parcel 分发、Spark 提交、History Server 查看的全链路,不是生产建议。

主机角色节点A(管理+主)节点B(工作)节点C(工作)
CM Server是否否
CM Agent是是是
NameNode / JournalNode是是是
DataNode是是是
ResourceManager是是(备)否
NodeManager是是是
ZooKeeper是是是
Hive Metastore是否否
Spark History Server是否否
MySQL(元数据库)是否否

内存分配上我踩过一个坑:节点A同时扛 CM Server、NameNode、ResourceManager、MySQL,8G 内存会非常吃力,CM 的服务端进程本身就是 Java 应用,堆内存 4G 起步比较稳。节点A给 16G,节点B/C 各给 16G,磁盘每节点至少两块(系统盘 + 数据盘),数据盘挂/data并单独给 DataNode 目录用。三节点加起来 48G 内存、6T 左右的盘,跑一个中小规模的验证环境足够了。

提示:节点数量的边界取决于 ZooKeeper 的 quorum 和 HDFS 副本数。ZK 至少 3 个才能容忍 1 个节点故障;HDFS 默认 3 副本,节点数低于 3 时副本永远处于 under-replicated 状态,虽然不影响跑作业,但你会天天看到告警。

2. 操作系统这一层,绝大多数坑都埋在这里

我见过太多人把 CM 装完、集群起来,结果 Spark 作业跑到一半 OOM 或者卡在 shuffle 阶段,最后发现是操作系统层面vm.swappiness没调、透明大页没关、文件句柄数没放开。这些东西在文档里都是一行命令,但漏一个就够你排查一整晚。所以这一章我按"必须做"和"建议做"分层写,别跳。

系统我选 CentOS 7.x,这是 CDH 6.2 支持最稳的发行版。7.9 也可以用,内核 3.10 那一套,透明大页和 cgroup 的行为都经过大量验证。别用更新的发行版,repo 里的依赖版本对不上,后面你会被 glibc 和 systemd 的差异折磨。

2.1 主机名、hosts 与时钟的联动

主机名这件事有两个硬要求:每台机器用完全限定域名(FQDN)风格命名,比如node-a.example.lab,并且在/etc/hosts里所有节点互相能解析到。CM 的角色分配、Agent 注册、Kerberos 后面的 principal 命名,全都依赖主机名的一致性。主机名改了又没重启,或者 hosts 里写的是短名而机器名是 FQDN,Agent 就会出现注册到 CM 时显示成另一个节点的情况,非常隐蔽。

三台机器统一执行:

hostnamectl set-hostname node-a.example.lab cat >> /etc/hosts <<'EOF' 10.0.0.11 node-a.example.lab node-a 10.0.0.12 node-b.example.lab node-b 10.0.0.13 node-c.example.lab node-c EOF

时钟同步用 chronyd,CDH 对时间漂移敏感,Kerberos 默认允许的时钟偏差只有 5 分钟,Spark 的 event log 时间戳错乱也会让 History Server 的事件顺序看着莫名其妙。配置一个内网时间源:

yum install -y chrony sed -i 's/^server .*/server 10.0.0.1 iburst/' /etc/chrony.conf systemctl enable --now chronyd chronyc sources -v

实测下来,集群运行一段时间后,节点间偏差控制在 100ms 以内是没问题的。我建议把chronyc tracking的结果也纳入日常巡检,遇到过磁盘 IO 打满导致时间同步进程被挤掉的情况,偏差一旦超过阈值,YARN 的 container 认证会直接失败。

2.2 内核参数、透明大页与服务裁剪

这一段是重点。透明大页(THP)对 JVM 是灾难,它会把内存分配延迟从微秒级拉到毫秒级,表现出来就是 Spark 作业 GC 时间异常长、Task 长尾严重。必须关掉,且要保证重启后依然生效。网上一堆教程只写了echo never,结果机器一重启又变回always,作业又开始抖动。

echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag cat >> /etc/rc.d/rc.local <<'EOF' echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag EOF chmod +x /etc/rc.d/rc.local

/etc/rc.d/rc.local需要chmod +x才会被执行,很多人漏了这一步,等于白配。sysctl 和 limits 一起改:

cat >> /etc/sysctl.conf <<'EOF' vm.swappiness = 1 vm.overcommit_memory = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_keepalive_time = 600 net.core.somaxconn = 32768 EOF sysctl -p cat > /etc/security/limits.d/99-cloudera.conf <<'EOF' * soft nofile 65536 * hard nofile 65536 * soft nproc 65536 * hard nproc 65536 EOF

vm.swappiness=1而不是 0,这是我个人的取舍:完全禁用 swap 在一些内存吃紧的节点上会触发 OOM Killer 直接杀进程,留一点点交换余量能让系统在极端情况下撑住,代价是可接受的。vm.overcommit_memory=1是为了让 JVM 申请堆内存时不被内核拒绝,Spark executor 启动失败的报错里有一大半和这个有关。

SELinux 和 firewalld 直接关掉,内网环境没必要折腾策略:

setenforce 0 sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config systemctl disable --now firewalld

注意:setenforce 0只对当前生效,/etc/selinux/config才是永久配置。两个都得改,我见过只改前者,重启后 SELinux 恢复 Enforcing,CM Agent 起不来,日志里只有一行 permission denied,排查半天。

2.3 JDK、用户与目录规划

CDH 6.2 支持 Oracle JDK 8 和 OpenJDK 8,我一般用 OpenJDK 8u 的最新小版本,省去授权麻烦。装完确认java -version输出 1.8.0_2xx 以上,并且JAVA_HOME在/etc/profile.d/里统一配好。所有节点必须路径一致,因为 CM 下发的角色配置里写的是绝对路径。

目录规划我习惯这样分:/opt/cloudera放 CM 和 Parcel,/data/dfs放 DataNode,/data/yarn放 NodeManager,/data/log放各角色日志。数据盘独立挂载有个好处,磁盘满了不会连带把系统盘撑爆,而且做快照、扩容都方便。用cloudera-scm系统用户跑服务,这个用户由 CM 的 rpm 包自动创建,不需要手工建。

还有一项容易被忽略:Python。Spark 2.4 的 PySpark 依赖 Python 2.7,CentOS 7 自带,但要确认python -V能输出 2.7.5。如果团队用的是 Python 3 为主,后面在 CM 里给 Spark 单独配spark.pyspark.python和spark.pyspark.driver.python,不要试图改系统默认的 python 软链,会连带影响 yum。

3. 元数据库与 CM 平台落地

CM 的所有状态都存在关系型数据库里,集群的角色、配置、审计日志、监控指标,全在里头。这个库挂了,整个管理平台就失忆。所以这一步的配置要有冗余意识,虽然小规模环境用单实例 MySQL 也行,但至少把参数调对、定期备份。

3.1 MySQL 的初始化脚本与必改参数

我选 MySQL 5.7,兼容性最稳。装完之后第一件事是改my.cnf,下面这几项直接决定后面集群跑不跑得顺:

[mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock transaction-isolation = READ-COMMITTED max_connections = 550 max_allowed_packet = 64M innodb_flush_log_at_trx_commit = 2 innodb_log_buffer_size = 16M innodb_buffer_pool_size = 2G innodb_flush_method = O_DIRECT binlog_format = ROW log_bin = /var/lib/mysql/mysql-bin expire_logs_days = 7

transaction-isolation = READ-COMMITTED是硬要求,CM 在 REPEATABLE-READ 下会出现一些诡异的状态更新丢失。max_allowed_packet调到 64M 是因为 CM 会把大段配置快照写进库,默认 4M 会直接报错,而且报错信息藏在 CM 的服务端日志里,界面上只显示一个泛泛的失败。innodb_flush_log_at_trx_commit=2是性能与安全的折中,牺牲极端断电场景下最后 1 秒的事务。

建库和授权一次性写进脚本:

CREATE DATABASE scm DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; CREATE DATABASE metastore DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; CREATE DATABASE amon DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; CREATE DATABASE hue DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; CREATE DATABASE oozie DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; CREATE DATABASE nav DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; CREATE DATABASE navms DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; CREATE USER 'scm'@'%' IDENTIFIED BY 'StrongPass#2024'; GRANT ALL PRIVILEGES ON scm.* TO 'scm'@'%'; GRANT ALL PRIVILEGES ON metastore.* TO 'scm'@'%'; GRANT ALL PRIVILEGES ON amon.* TO 'scm'@'%'; GRANT ALL PRIVILEGES ON hue.* TO 'scm'@'%'; GRANT ALL PRIVILEGES ON oozie.* TO 'scm'@'%'; GRANT ALL PRIVILEGES ON nav.* TO 'scm'@'%'; GRANT ALL PRIVILEGES ON navms.* TO 'scm'@'%'; FLUSH PRIVILEGES;

就算你这次只装 Spark 和 YARN,也建议把 metastore、hue 这些库一起建了,后面想加 Hive 不用重新折腾权限。库名和用户名用默认的,别自作聪明改成别的,CM 内部有些初始化逻辑对名字有假设。

3.2 CM Server 与 Agent 的安装顺序

流程是:先装 Server 的 rpm,跑scm_prepare_database.sh初始化库,再启动 Server,最后装 Agent 并指向 Server。顺序错了会很麻烦,尤其是先启动 Agent 再去初始化库,Agent 会一直重连失败。

# 节点A yum install -y cloudera-manager-daemons cloudera-manager-server /opt/cloudera/cm/schema/scm_prepare_database.sh mysql scm scm 'StrongPass#2024' systemctl start cloudera-scm-server tail -f /var/log/cloudera-scm-server/cloudera-scm-server.log

日志里出现Started Jetty server或者Monitoring services started就说明起来了,端口 7180 可以访问。这个启动过程第一次比较慢,因为要建表,等两三分钟很正常,别急着判断失败去重启,重启反而会把初始化的表搞成半成品。

Agent 这边:

# 所有节点 yum install -y cloudera-manager-agent cloudera-manager-daemons sed -i 's/^server_host=.*/server_host=node-a.example.lab/' /etc/cloudera-scm-agent/config.ini systemctl start cloudera-scm-agent

Agent 起来之后在 7180 界面里能看到待加入的主机。这里有个细节:server_host必须和 Server 端证书里的主机名一致,用 IP 有时候也能连上,但后面 Kerberos 或者 TLS 一开就会出问题。养成用 FQDN 的习惯。

3.3 Parcel 离线分发的正确姿势

Parcel 是 CDH 的分发机制,本质上是一个 tar.gz 加一个 sha1 校验文件。内网环境走离线,把 parcel 放到/opt/cloudera/parcel-repo,再补一个.sha文件。文件名必须和 CM 期望的完全一致,包括最后那段 hash 值。

mkdir -p /opt/cloudera/parcel-repo cp CDH-6.2.0-1.cdh6.2.0.p0.967373-el7.parcel /opt/cloudera/parcel-repo/ sha1sum CDH-6.2.0-1.cdh6.2.0.p0.967373-el7.parcel | awk '{print $1}' > CDH-6.2.0-1.cdh6.2.0.p0.967373-el7.parcel.sha chown -R cloudera-scm:cloudera-scm /opt/cloudera/parcel-repo

CM 界面里点"检查新 Parcel",能识别出来就说明路径和校验都对。分发到所有节点、解压、激活,三步走完。解压时 CM 会在/opt/cloudera/parcels/下建软链,比如CDH -> CDH-6.2.0-1.cdh6.2.0.p0.967373。后面所有 spark-submit 的命令都用这个软链路径,升级到 6.2.1 时软链自动指过去,脚本不用改。

提示:Parcel 分发失败时,先在目标节点看/opt/cloudera/parcel-cache里文件大小对不对。遇到过磁盘配额问题导致文件被截断,CM 界面上只显示 timeout,实际是文件不完整。

4. Spark 服务上线与关键参数

终于到正题。但要清楚,Spark 在这套架构里不是独立集群,它跑在 YARN 上,属于"按需申请资源"的客户端角色。所以真正的底座是 YARN、HDFS、ZooKeeper,这三个跑不稳,Spark 一定跟着抖。

4.1 先让 YARN 和 ZooKeeper 跑起来

在 CM 里先加 ZooKeeper 服务,三个节点各一个角色,这是所有协调类组件的依赖。然后加 YARN,ResourceManager 放在节点A和B做 HA,NodeManager 三台全放。HDFS 类似,NameNode 两台 HA,JournalNode 三个,DataNode 三台。

YARN 的容器内存配置是我每次都要调的地方。默认yarn.nodemanager.resource.memory-mb可能给的很大或者很小,得按实际物理内存减掉系统占用和其他角色开销来算。节点B有 16G 内存,跑 NodeManager、DataNode、ZooKeeper,我给 NodeManager 12G,剩下 4G 留给系统和其他进程。yarn.scheduler.maximum-allocation-mb设成 8G,意味着单个 container 最多能申请 8G,这样--executor-memory 6g这种配置不会因为超出上限被拒。

计算公式很简单:NodeManager 可用内存 = 物理内存 - 系统预留(2~4G) - 其他 Java 进程堆内存。三节点 48G 物理内存,实际能提供给 YARN 的容器内存大约 34G 左右。这个数就是你 Spark 集群的算力天花板,后面做容量规划全从这儿推导。

4.2 添加 Spark 服务时的几个关键选择

在 CM 首页点"添加服务",选 Spark。CM 会自动带出一组角色建议:History Server 一个(放节点A),Gateway 类型角色分布在需要提交作业的节点上。Gateway 这个角色容易被误解,它不运行任何进程,作用是把客户端配置(/etc/spark/conf)下发到指定节点。没有 Gateway 的节点自己装了 spark 客户端也连不上集群,因为配置不完整。

关键配置项我列成表,这些都是我实际调过的:

配置项建议值为什么这么设
spark.masteryarn走 YARN 调度,资源统一管理
spark.eventLog.enabledtrue不开就没有 History 可看,事后排查全靠 god
spark.eventLog.dirhdfs://ns1/user/spark/applicationHistoryHDFS 上集中存储,重启不丢
spark.history.fs.logDirectory同上必须和上面完全一致,多一个斜杠都不行
spark.history.fs.cleaner.enabledtrue否则日志无限增长,半年后 HDFS 被塞满
spark.dynamicAllocation.enabledtrue按需伸缩 executor,集群共享场景必备
spark.shuffle.service.enabledtrue动态分配的前提,不开会报错
spark.executor.memory4g起步值,按作业特征再调
spark.yarn.maxAppAttempts2默认 2,太多会拖长失败判定时间

spark.eventLog.dir和spark.history.fs.logDirectory必须严格一致,这是我踩过的第一个坑。前者是写日志的路径,后者是读的路径,不一致的话 History Server 起来是个空界面,作业跑完了点进去什么都没有,你会误以为是权限问题。

4.3 History Server、Gateway 与客户端验证

History Server 启动后,默认端口 18088。访问http://node-a.example.lab:18088能看到应用列表。刚装完是空的,跑个作业才有内容。

客户端这边,CM 会把配置下发到/etc/spark/conf,包括spark-defaults.conf、spark-env.sh、hive-site.xml(用于访问 Hive 元数据)和core-site.xml、hdfs-site.xml、yarn-site.xml。这套配置的来源是 CM 数据库,所以永远不要在节点上手工改这些文件,下一次 CM 重启服务就会覆盖掉。要改配置,走 CM 界面。

验证客户端配置完整性最快的办法:

source /etc/profile spark-submit --version

能打出 Spark 2.4.0-cdh6.2.0 和 Scala 2.11.12 的版本信息,说明基本链路通了。如果报ClassNotFoundException或者找不到 HADOOP_CONF_DIR,检查是不是在 Gateway 角色节点上,以及/etc/spark/conf里的软链是否正常。

5. 跑通第一个作业,才算真的装完

界面全绿不等于能用。我判断一套 Spark 环境是否交付完成的标准是:能提交作业、能在 History Server 看到明细、能在 YARN 界面看到资源占用、日志能正常写出。这四件事都过了,才算装完。

5.1 spark-shell 与 spark-submit 实测

先进交互式环境试水,这是最快发现配置问题的方式:

spark-shell --master yarn --deploy-mode client

进去之后会看到 Spark context 初始化,sc和spark两个变量就绪。跑个最简单的:

val rdd = sc.parallelize(1 to 1000000, 20) rdd.map(x => x * 2).reduce(_ + _)

如果这一步能出结果,说明资源申请、shuffle、结果回收整条链路都通了。接着跑 Pi 的示例,这个能验证更完整的任务调度:

spark-submit \ --master yarn \ --deploy-mode client \ --executor-memory 4g \ --executor-cores 2 \ --conf spark.dynamicAllocation.enabled=true \ --conf spark.dynamicAllocation.minExecutors=2 \ --conf spark.dynamicAllocation.maxExecutors=6 \ --class org.apache.spark.examples.SparkPi \ /opt/cloudera/parcels/CDH/lib/spark/examples/jars/spark-examples_2.11-2.4.0-cdh6.2.0.jar 200

jar 路径要精确到带_2.11和cdh6.2.0后缀的那个文件。CDH 里的示例 jar 和 Apache 原版命名不同,直接用网上抄来的路径会报文件不存在。这一步跑通,YARN 界面里能看到 application 状态从 ACCEPTED 到 RUNNING 再到 FINISHED,History Server 里点进去能看到 stage 和 task 明细。

5.2 动态资源分配与 shuffle service 的打通

动态资源分配这块有个隐藏依赖:spark.shuffle.service.enabled=true要求 YARN 的 NodeManager 侧启用了对应的辅助服务。CM 里 Spark 服务添加时会自动往 YARN 配置里注入yarn.nodemanager.aux-services的增加项,但不会自动重启 NodeManager。所以顺序很重要:

  1. 先装 YARN,跑起来。
  2. 再装 Spark,CM 会修改 YARN 的yarn.nodemanager.aux-services,加入spark_shuffle,并配置yarn.nodemanager.aux-services.spark_shuffle.class=org.apache.spark.network.yarn.YarnShuffleService。
  3. 手动重启 YARN 服务,让 NodeManager 加载新的 aux service。
  4. 再跑带动态分配的作业。

我见过有人第三步漏了,作业报YarnShuffleService is not initialized或者 executor 释放后 shuffle 数据找不到,报错信息指向FetchFailedException,看着像网络问题,实际是 shuffle service 没起来。排查方法:在 NodeManager 节点上jps看有没有YarnShuffleService相关进程,或者查 NodeManager 日志里有没有Initialized spark_shuffle。

动态分配的参数也别照抄。minExecutors设 2 保底,maxExecutors按前面算的容器总量来定,executorIdleTimeout默认 60 秒,如果你的作业有长时间的空闲间隙,可以调到 120 秒,避免反复申请释放带来的调度开销。

6. 踩过的坑与排查速查表

这一章是整篇里我最想写的部分。文档里能查到的配置项,大家都会配;真出问题的时候,往往是几行日志里藏着的细节。下面是我在多个环境里攒下来的对照表。

现象大概率原因处理方式
Agent 在 CM 界面显示"心跳丢失"主机名与证书不一致,或 Agent 进程挂了核对server_host与 FQDN,systemctl restart cloudera-scm-agent
Parcel 分发卡在 0%目标节点磁盘空间不足或校验失败查看/opt/cloudera/parcel-cache文件大小与 sha1
spark-shell 启动即报Connection refusedHistory Server 未起或spark.eventLog.dir路径不可写检查 HDFS 目录权限,hdfs dfs -ls /user/spark
作业卡在 ACCEPTED 不进入 RUNNINGYARN 容器内存不足或队列资源被占满看 YARN 界面的队列使用率,调整maximum-allocation-mb
Executor 频繁丢失节点内存溢出被 OOM Killer 杀掉查/var/log/messages里的 oom 记录,下调 executor 内存
FetchFailedException大量出现shuffle service 未启用或数据被清理确认 aux service 已加载,检查keepAlive配置
History Server 页面为空读写路径不一致对比spark.eventLog.dir和spark.history.fs.logDirectory
作业执行极慢但 CPU 不高透明大页未关闭,GC 抖动复核 THP 配置与swappiness
CM 启动报数据库连接失败MySQL 隔离级别或max_allowed_packet不达标按前面章节核对my.cnf并重启 MySQL

6.1 几点不写在文档里的实战经验

第一,别一次把所有服务全加上。很多人图省事,CM 的安装向导里勾一堆组件,结果某个服务起不来导致整个集群状态异常,其他服务也跟着受影响。我的做法是分三批:第一批 ZooKeeper + HDFS,确认 HDFS 能正常读写;第二批 YARN,确认能提交一个 mapreduce 的 sleep 作业;第三批才上 Spark。每批之间留出验证时间,出问题定位范围小得多。

第二,/etc/spark/conf下的文件不要手改。这条前面说过一次,但值得再说一次,因为它的后果很隐蔽:你手工改了spark-defaults.conf调大了 executor 内存,作业跑得好好的,某天 CM 重启服务或者某个节点 Agent 重连,配置回滚,作业开始 OOM,你完全想不起来中间发生过什么。所有变更走 CM 界面,改完点"部署客户端配置",一键下发。

第三,日志保留策略要提前定。spark.history.fs.cleaner.enabled打开只是启用清理,spark.history.fs.cleaner.interval和spark.history.fs.cleaner.maxAge决定清多快。默认 7 天,如果你的作业量特别大,7 天的 event log 可能上百 G。我一般配成 3 天,并且在 HDFS 上给/user/spark/applicationHistory设配额,防止把整个 HDFS 撑爆。

第四,spark.executor.cores和spark.executor.memory的配比有讲究。经验值是每个 core 配 2~4G 内存,超过 5G 一个 core 容易导致 HDFS 客户端连接数过多。反过来,core 太多而内存太少,会频繁 spill。三节点的环境我通常用--executor-cores 2 --executor-memory 4g,单个 executor 跑 2 到 3 个 task,并发和 GC 压力比较均衡。

6.2 影响范围与后续扩展

这套环境落成之后,能支撑的作业规模大概是几十 GB 级的数据量、十几个并发的 Spark 应用。往下游走,最常见的扩展方向有三个:接 Hive 打通数仓查询、加 Kerberos 做认证、把存储换成对象存储适配。其中 Kerberos 是最容易出问题的,一旦启用,所有提交作业的客户端都要有 keytab,History Server 要配 principal,Spark 的spark.yarn.principal和spark.yarn.keytab必须正确,否则作业提交直接被拒。

我个人在实际操作中的体会是:CDH 6.2 这套东西的价值不在于组件本身多先进,而在于它把版本兼容、配置管理、角色生命周期这堆杂活收敛到一个界面里。代价是你必须尊重它的规则,不要在它管理的目录上手工改东西,不要绕过 CM 去动服务配置。每次想"就改一个小地方"的时候,先想一想下一次配置下发会不会把它覆盖回去。想清楚这一点,这套环境能稳定跑很久。

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

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

立即咨询