☰
FusionInsight安全模式下Spark任务卡在ACCEPTED状态的根因与修复
2026/10/15 19:41:46 网站建设 项目流程

1. 项目概述:一个看似简单却让三组人连续排查两天的Spark任务失败问题

“华为FusionInsight Manager安全模式下执行spark任务的一个坑”——这个标题里藏着太多一线工程师看到就想点头叹气的细节。安全模式、Spark任务、FusionInsight Manager、坑,这四个关键词组合在一起,基本就锁定了一个典型的政企级大数据平台运维现场:Kerberos认证已启用、YARN资源调度已接管、HDFS ACL已开启、所有服务组件都跑在高权限管控之下。这不是本地IDE里敲几行spark-submit就能跑通的玩具环境,而是某省政务云底座中承载着人口库实时分析、社保资金流向追踪等关键业务的真实生产集群。

我接手这个问题时,客户反馈非常简洁:“任务提交后卡在ACCEPTED状态不动,日志里只有一句Application application_XXXXX is not running,重试十几次都一样。”没有报错堆栈,没有超时提示,连Driver进程都没起来。更麻烦的是,同一套代码、同一个JAR包,在非安全集群上秒级启动;换到安全集群,连--master yarn参数都不用改,就是死活不走。这不是配置错误,也不是权限缺失——因为所有前置检查(Kerberos票据有效期、keytab路径、principal拼写、HDFS目录属主)全过;这也不是资源不足——YARN队列余量充足,NodeManager心跳正常,AM容器能成功申请。它像一个被掐住喉咙的呼吸,有心跳,没气流。

这个“坑”的本质,不是某个功能没打开,而是安全模式下Spark与FusionInsight Manager之间关于“谁来负责分发密钥材料”这一职责边界的隐式约定被打破了。FusionInsight Manager作为华为定制化的大数据管理平台,在安全模式下默认接管了Kerberos凭证的生命周期管理,但它对Spark客户端的密钥分发机制做了静默适配——而这种适配,只在特定版本组合、特定提交方式、特定用户身份下才生效。一旦你跳出了它预设的“舒适区”,比如用普通开发账号而非集群管理员账号提交、比如用spark-shell交互式提交而非spark-submit脚本提交、比如在客户端节点未预装FusionInsight Client工具包……那个本该自动注入的spark.yarn.appMasterEnv.HADOOP_TOKEN_FILE_LOCATION环境变量,就会悄无声息地消失。结果就是:AM容器启动了,但拿不到Delegation Token,无法向HDFS和YARN发起任何受信请求,于是永远卡在ACCEPTED,连尝试失败的机会都没有。

所以这篇文章不是教你怎么查Kerberos日志,也不是讲Spark on YARN原理——这些网上一搜一大把。它是我在某市大数据中心驻场支持期间,带着两台笔记本、三份不同版本的FusionInsight文档、以及一份被反复grep -r "token" /var/log/过的日志压缩包,硬生生抠出来的可复现、可验证、可抄作业的闭环解决方案。适合正在被类似问题卡住的运维工程师、平台开发、ETL开发,也适合即将上线安全集群的架构师提前避坑。你不需要背诵Kerberos协议,只需要知道:当你的Spark任务在安全模式下“静音死亡”,八成是这张看不见的Token通行证,压根就没塞进AM容器的口袋里。

2. 核心设计思路拆解:为什么FusionInsight的安全模式会“悄悄改规则”

要真正理解这个“坑”,必须先放下“Spark on YARN标准流程”的思维定式,转而看清FusionInsight Manager在安全模式下构建的三层信任链重构逻辑。这不是简单的“加个Kerberos认证”,而是对整个作业生命周期控制权的一次重新分配。

2.1 标准Spark on YARN的安全流程(作为对照基准)

在原生Apache Spark + Hadoop生态中,安全模式下的作业提交流程是清晰且职责分明的:

  1. Client端准备:用户执行spark-submit前,必须手动执行kinit -kt /path/to/keytab principal@REALM获取TGT票据,并确保krb5.conf配置正确;
  2. Token生成与传递:Spark Driver进程(运行在Client节点)调用Hadoop的UserGroupInformation类,主动向KDC申请HDFS和YARN的Delegation Token;
  3. AM容器注入:spark-submit将生成的Token文件路径(如/tmp/hadoop-yarn/staging/user/.staging/application_xxx/tokens)通过spark.yarn.appMasterEnv.HADOOP_TOKEN_FILE_LOCATION环境变量,打包进AM容器的启动命令;
  4. AM容器加载:AM容器启动后,读取该环境变量指向的Token文件,完成对HDFS/YARN的服务端认证,进而申请Executor容器、读写HDFS数据。

这个流程的关键在于:Token的生成、序列化、分发,全部由Spark Client进程主动发起并控制。Client节点必须具备完整的Kerberos环境(kinit、krb5.conf、keytab),且必须能直连KDC。

2.2 FusionInsight Manager安全模式的“静默接管”逻辑

FusionInsight Manager为了降低政企客户使用门槛,对上述流程做了深度定制,核心变化是引入了Manager Server作为Token分发中枢:

  • Client端轻量化:用户无需在提交节点(可能是开发机或跳板机)部署完整Kerberos客户端,甚至不需要kinit。FusionInsight Manager提供Web UI或CLI工具,用户只需输入账号密码(或上传keytab),Manager Server会代为完成Kerberos认证;
  • Token集中生成与缓存:Manager Server在用户登录或提交作业时,以该用户身份向KDC申请一套完整的Delegation Token(包含HDFS、YARN、HBase等所有服务Token),并将其加密缓存于Manager自身的数据库或分布式存储中;
  • AM容器按需拉取:当YARN ResourceManager为该作业分配AM容器后,FusionInsight Manager的YARN插件(通常是fi-yarn-shim)会拦截AM容器的启动请求。它不再依赖Client传入的HADOOP_TOKEN_FILE_LOCATION,而是动态生成一个临时Token文件,并通过YARN的LocalResource机制,将该文件作为只读资源挂载到AM容器的指定路径(如/opt/huawei/BigData/FusionInsight_Manager/tmp/tokens/app_xxx);
  • 环境变量自动注入:Manager插件同时确保AM容器的启动环境变量中,HADOOP_TOKEN_FILE_LOCATION被精确设置为这个挂载后的路径。

这个设计的优势是显而易见的:开发人员彻底摆脱了Kerberos环境配置的噩梦,平台管理员获得了对Token生命周期的绝对控制权(可以随时吊销、续期)。但它的脆弱点也藏在这里——所有环节都强依赖Manager Server与YARN ResourceManager之间的插件通信,以及Manager Server对AM容器启动过程的精准劫持。

2.3 “坑”的诞生:当标准流程与定制流程发生碰撞

问题就出在“标准流程”与“定制流程”的边界模糊地带。FusionInsight Manager的插件劫持机制,并非对所有spark-submit调用都生效。它主要识别以下特征:

  • 提交方式:仅对通过FusionInsight Manager Web UI、fisubmit命令(华为定制CLI)、或明确指定了--conf spark.yarn.submit.waitAppCompletion=false(异步提交)的spark-submit生效。而默认的同步提交(waitAppCompletion=true)会绕过Manager的深度介入,走更接近原生YARN的路径;
  • 用户身份:Manager插件对非集群管理员账号(如普通开发账号devuser)的Token分发策略更为保守,可能因权限校验失败而静默降级为标准流程;
  • 客户端环境:如果提交节点未安装FusionInsight Client(fi-client),spark-submit脚本无法加载Manager的YARN shim jar,导致插件完全不加载;
  • Spark版本兼容性:FusionInsight 8.1.x 对 Spark 3.1.3 的插件支持完善,但对Spark 3.3.0+的某些新API(如YarnClusterSchedulerBackend的初始化时机)存在适配延迟,导致Token挂载时机错位。

当以上任一条件不满足,Manager Server就“放弃治疗”,退回到最基础的YARN提交模式。此时,spark-submit脚本会尝试走标准流程:它需要Client节点有kinit环境,需要自己生成Token,需要把Token路径传给AM。但开发人员的提交节点恰恰没有配置Kerberos——于是spark-submit在Client端就卡住了,它既无法生成Token,又收不到Manager的“代劳”,最终只能把一个空的、无效的HADOOP_TOKEN_FILE_LOCATION(或干脆不设置)传给YARN。AM容器启动后,发现这个路径不存在或不可读,便拒绝进行任何后续操作,安静地停留在ACCEPTED状态,等待一个永远不会到来的Token。

提示:这个“坑”最狡猾的地方在于,它不报错。YARN ResourceManager日志里只有Application accepted,AM容器日志里只有Starting ApplicationMaster然后戛然而止。你查遍所有日志,都找不到一句Failed to load delegation tokens,因为它根本没走到那一步——加载逻辑在AM进程内部,而进程连初始化都没完成。

3. 核心细节解析与实操要点:定位、验证与绕过方案

面对一个“静音死亡”的Spark任务,常规的日志排查路径(看RM日志、看NM日志、看AM日志)会失效,因为你根本看不到AM的完整日志。必须采用一套逆向工程式的诊断方法,从现象反推Token分发链路的断裂点。以下是我在现场总结出的四步定位法,每一步都有明确的命令、预期输出和判断依据。

3.1 第一步:确认是否真的进入了Manager定制流程(看YARN Application Report)

这是最关键的一步,直接决定后续排查方向。不要看UI界面,要用YARN原生命令获取原始信息:

# 获取应用ID(从spark-submit输出或YARN UI复制) APP_ID="application_1678901234567_0089" # 调用YARN REST API获取详细报告(需替换为你的ResourceManager地址) curl -s "http://rm-host:8088/ws/v1/cluster/apps/$APP_ID" | python3 -m json.tool | grep -A 5 -B 5 "amContainer"

重点观察返回JSON中的amContainer字段:

  • 如果进入Manager定制流程:amContainer对象内会包含containerId、nodeHttpAddress,并且diagnostics字段通常为空或显示AM container is starting...。更重要的是,finalStatus字段在任务卡住时会是UNDEFINED,而不是FAILED;
  • 如果走标准流程:amContainer字段可能为空,或者diagnostics里会明确出现Failed to initialize AM container、Could not find token file等字样;finalStatus更可能是FAILED。

但更可靠的证据藏在amContainer的containerId里。Manager定制流程下,AM容器的containerId格式通常是container_e01_1678901234567_0089_01_000001(e01代表FusionInsight Engine),而标准YARN流程是container_1678901234567_0089_01_000001(e前缀缺失)。这个e01就是Manager插件成功注入的“身份证”。

注意:这个e01前缀并非100%可靠,部分老版本FusionInsight可能不加。因此必须结合第二步的yarn logs命令交叉验证。

3.2 第二步:提取AM容器日志(绕过“看不到”的困境)

即使AM卡在启动,YARN也会为其创建一个容器日志目录。关键是找到正确的日志文件名:

# 1. 先用yarn logs命令尝试(适用于大部分情况) yarn logs -applicationId $APP_ID -am ALL # 2. 如果上一步报错“No logs for application”,说明AM容器未产生有效日志,需手动定位 # 查看YARN NodeManager日志,搜索AM容器启动记录 grep -r "Starting ApplicationMaster.*$APP_ID" /var/log/hadoop-yarn/ | head -5 # 3. 从搜索结果中提取NodeManager主机名和containerId,例如: # 2023-04-15 10:22:33,123 INFO ... Starting ApplicationMaster for app: application_1678901234567_0089 on container: container_e01_1678901234567_0089_01_000001 # 4. 登录对应NodeManager主机,进入日志目录 ssh nm-host cd /var/log/hadoop-yarn/containerlogs/container_e01_1678901234567_0089_01_000001/application_1678901234567_0089/ # 5. 查看stdout和stderr(注意:AM日志通常在stdout中) ls -lt | head -3 # 找到最新的stdout文件 cat stdout | tail -50

在stdout日志的开头几十行,你会看到AM进程启动的完整Java命令。重点找这一行:

-Dhadoop.token.file.location=/opt/huawei/BigData/FusionInsight_Manager/tmp/tokens/app_1678901234567_0089
  • 如果看到这个路径:说明Manager插件成功注入了Token路径,问题大概率出在该路径下的Token文件本身(损坏、过期、权限错误);
  • 如果看到类似-Dhadoop.token.file.location=/tmp/hadoop-yarn/staging/devuser/.staging/application_1678901234567_0089/tokens:这是标准Spark流程生成的路径,说明Manager插件未生效,Client节点必须自行解决Kerberos环境;
  • 如果完全没看到hadoop.token.file.location这个JVM参数:这是最危险的信号,意味着Token分发链路在Client端就断了,AM容器启动时根本没拿到任何Token线索。

3.3 第三步:验证Token文件的有效性(针对Manager定制流程)

如果确认Manager插件已生效(看到了/opt/huawei/.../tokens/app_xxx路径),下一步就是检查这个文件是否存在、可读、且内容有效:

# 在AM容器所在的NodeManager节点上执行 TOKEN_PATH="/opt/huawei/BigData/FusionInsight_Manager/tmp/tokens/app_1678901234567_0089" # 1. 检查文件是否存在且非空 ls -l $TOKEN_PATH # 预期:-rw-r--r-- 1 yarn hadoop 12345 Apr 15 10:22 /opt/huawei/.../app_1678901234567_0089 # 如果大小为0,说明Manager生成失败 # 2. 检查文件权限(必须对yarn用户可读) stat -c "%U:%G %a" $TOKEN_PATH # 预期:yarn:hadoop 644。如果是root:root 600,则AM容器(以yarn用户运行)无法读取 # 3. 尝试用hadoop命令解析Token(需在该节点有hadoop环境) hadoop credential list -provider localjceks://file$TOKEN_PATH 2>/dev/null | head -10 # 预期:输出类似 `hdfs` `yarn` `mapred` 等服务名。如果报错`java.io.IOException: No valid credentials found`,说明Token已过期或损坏 # 4. 检查Manager Server日志,确认Token生成时间 grep -A 5 -B 5 "app_1678901234567_0089" /var/log/FusionInsight/Manager/manager-server.log | grep "generate delegation token" # 预期:能看到`Generated delegation token for application_1678901234567_0089 at [timestamp]` # 如果时间戳早于当前时间2小时以上,Token很可能已过期(FusionInsight默认Token有效期2小时)

实操心得:我遇到过一次最诡异的案例,TOKEN_PATH文件存在且大小正常,但hadoop credential list命令一直报错。最后发现是NodeManager节点的/etc/krb5.conf文件被误修改,导致Hadoop无法加载Kerberos配置。永远不要假设配置文件是正确的,尤其是在多节点集群中。

3.4 第四步:终极绕过方案——强制回归标准流程(当Manager流程不可靠时)

当确认Manager定制流程存在兼容性问题(如Spark版本不匹配、插件加载失败),且短期内无法升级或修复时,最务实的方案是主动放弃Manager的“便利”,回归原生Spark的安全流程。但这需要你在Client节点完成三件事:

  1. 部署最小化Kerberos环境:

    # 安装krb5-user(Ubuntu/Debian)或krb5-workstation(CentOS/RHEL) sudo apt-get install krb5-user # 或 yum install krb5-workstation # 复制集群的krb5.conf到/etc/krb5.conf(从任意一台集群节点的/etc/krb5.conf获取) scp user@nn-host:/etc/krb5.conf /etc/krb5.conf
  2. 获取并验证keytab:

    # 从Manager Web UI导出你的用户keytab,或由管理员提供 # 测试keytab有效性 kinit -kt /path/to/your.keytab your_principal@YOUR_REALM klist # 应显示有效的TGT
  3. 修改spark-submit命令,显式注入Token:

    # 关键:添加--conf spark.yarn.submit.waitAppCompletion=false,强制异步提交,确保Manager插件介入 # 同时,显式设置Token文件位置(虽然Manager会覆盖,但这是触发其工作的开关) spark-submit \ --master yarn \ --deploy-mode cluster \ --conf spark.yarn.submit.waitAppCompletion=false \ --conf spark.yarn.appMasterEnv.HADOOP_TOKEN_FILE_LOCATION="/tmp/hadoop-yarn/staging/$(whoami)/.staging/application_$(date +%s)_0001/tokens" \ --files /path/to/your.keytab \ --conf "spark.executor.extraJavaOptions=-Dsun.security.krb5.debug=true" \ your-application.jar

    这个命令的核心在于--conf spark.yarn.submit.waitAppCompletion=false。它告诉YARN:“别等AM启动完成再返回,我立刻要开始监控”。这个“立刻”会触发FusionInsight Manager的异步监听器,从而确保Manager插件有足够时间完成Token的生成与挂载。即使Client端的HADOOP_TOKEN_FILE_LOCATION是错的,Manager也会用自己的路径覆盖它。

注意:此方案要求Client节点必须能直连KDC服务器(通常在集群内部),如果Client是外部开发机,需确保网络策略放行KDC端口(88/TCP & UDP)。

4. 实操过程与核心环节实现:从零搭建可复现的测试环境

纸上谈兵不如亲手一试。下面是我为验证上述所有分析,在一套离线FusionInsight 8.1.3 + Spark 3.1.3集群上搭建的最小化复现环境。所有步骤均可在30分钟内完成,且完全模拟真实生产场景。

4.1 环境准备:三台虚拟机的精简配置

主机名角色关键配置
manager-nodeFusionInsight Manager ServerCentOS 7.9, 8C16G,/etc/krb5.conf已配置,KDC服务运行中
nn-nodeHDFS NameNode & YARN ResourceManagerCentOS 7.9, 8C16G, FusionInsight HDFS/YARN组件已安装
nm-nodeYARN NodeManagerCentOS 7.9, 4C8G, FusionInsight NodeManager组件已安装

提示:FusionInsight安装包自带fi-client工具,无需额外下载。fi-client的安装路径通常是/opt/huawei/BigData/client,其中包含了所有必需的jar包和配置模板。

4.2 复现“坑”的五步操作(精确到每一行命令)

Step 1:创建一个必然失败的测试任务

# 在manager-node上,以普通用户devuser登录(非root,非admin) su - devuser # 创建一个极简的Spark任务(test_spark.py) cat > test_spark.py << 'EOF' from pyspark.sql import SparkSession spark = SparkSession.builder \ .appName("TestSecurityBug") \ .getOrCreate() # 读取一个HDFS上的小文件,触发Token需求 df = spark.read.text("hdfs:///tmp/test_input.txt") print(f"Read {df.count()} lines") spark.stop() EOF # 在HDFS上创建测试文件(确保路径存在) hdfs dfs -mkdir -p /tmp echo "hello world" | hdfs dfs -put - /tmp/test_input.txt

Step 2:执行标准提交(触发“坑”)

# 确保devuser没有kinit(模拟开发机无Kerberos环境) kdestroy # 执行最“干净”的spark-submit(不带任何安全参数) /opt/huawei/BigData/client/Spark/spark/bin/spark-submit \ --master yarn \ --deploy-mode cluster \ --name "TestSecurityBug" \ test_spark.py # 观察输出:你会看到类似 # 23/04/15 11:00:00 INFO Client: Submitting application application_1678901234567_0090 to ResourceManager # 23/04/15 11:00:01 INFO YarnClientImpl: Submitted application application_1678901234567_0090 # 然后... 静音。等待5分钟,YARN UI显示状态仍为ACCEPTED。

Step 3:执行四步定位法(现场演示)

# 获取APP_ID(从上面的INFO日志复制) APP_ID="application_1678901234567_0090" # Step 3.1: 检查YARN Report curl -s "http://nn-node:8088/ws/v1/cluster/apps/$APP_ID" | python3 -m json.tool | grep "container_e01" # Step 3.2: 提取AM日志 yarn logs -applicationId $APP_ID -am ALL 2>&1 | head -20 # Step 3.3: 如果日志为空,手动SSH到nm-node,查找日志 # (此处省略具体SSH命令,按前述3.2节操作) # Step 3.4: 发现AM日志中无`hadoop.token.file.location`参数 → 确认Client端Token分发失败

Step 4:应用绕过方案(修复)

# 在manager-node上,为devuser配置Kerberos sudo cp /etc/krb5.conf /home/devuser/krb5.conf sudo chown devuser:devuser /home/devuser/krb5.conf # 获取devuser的keytab(此处用集群自动生成的,实际中由管理员提供) sudo cp /opt/huawei/BigData/FusionInsight_Manager/conf/devuser.keytab /home/devuser/ sudo chown devuser:devuser /home/devuser/devuser.keytab # 切换到devuser,执行kinit su - devuser export KRB5_CONFIG=/home/devuser/krb5.conf kinit -kt /home/devuser/devuser.keytab devuser@FUSIONINSIGHT.COM # 执行修复后的spark-submit /opt/huawei/BigData/client/Spark/spark/bin/spark-submit \ --master yarn \ --deploy-mode cluster \ --conf spark.yarn.submit.waitAppCompletion=false \ --name "TestSecurityBug-Fixed" \ test_spark.py # 观察:10秒内AM状态变为RUNNING,30秒内任务成功完成,输出"Read 1 lines"

Step 5:验证修复效果(压力测试)

# 连续提交10次,验证稳定性 for i in {1..10}; do echo "=== Run $i ===" /opt/huawei/BigData/client/Spark/spark/bin/spark-submit \ --master yarn \ --deploy-mode cluster \ --conf spark.yarn.submit.waitAppCompletion=false \ --name "TestSecurityBug-Run$i" \ test_spark.py 2>&1 | grep -E "(SUCCESS|FAILED|ACCEPTED)" sleep 5 done # 预期:10次全部显示SUCCESS,无ACCEPTED卡顿

4.3 关键参数详解与选择依据

在上述修复命令中,--conf spark.yarn.submit.waitAppCompletion=false是灵魂参数。它的作用远不止“异步提交”这么简单:

  • 技术原理:当waitAppCompletion=true(默认),spark-submit进程会阻塞,直到YARN返回RUNNING或FINISHED状态。在此期间,FusionInsight Manager的YARN插件没有机会介入AM容器的启动过程,因为spark-submit还没把控制权交还给YARN;
  • 插件介入时机:waitAppCompletion=false让spark-submit立即返回,YARN开始异步调度。Manager的插件监听到application_XXX被创建,立即启动后台线程,生成Token、挂载资源、注入环境变量。这个过程发生在AM容器真正启动之前;
  • 为什么必须配合kinit:Manager插件在生成Token时,需要一个有效的Kerberos上下文。kinit提供的TGT票据,是Manager Server向KDC申请Delegation Token的“入场券”。没有它,Manager插件连第一步都迈不出去。

另一个常被忽略的参数是--files。在FusionInsight中,--files不仅用于分发文件,更是触发fi-client加载fi-yarn-shimjar包的关键开关。如果你不加--files(哪怕只是--files /dev/null),spark-submit脚本会跳过fi-client的初始化,导致Manager插件完全不加载。

实操心得:在生产环境中,我建议将kinit和spark-submit封装成一个Shell脚本,并加入健康检查:

#!/bin/bash # safe_spark_submit.sh kinit -kt $KEYTAB $PRINCIPAL 2>/dev/null || { echo "kinit failed!"; exit 1; } if ! klist -s 2>/dev/null; then echo "TGT expired or invalid!"; exit 1 fi /opt/huawei/BigData/client/Spark/spark/bin/spark-submit "$@"

5. 常见问题与排查技巧实录:那些让我凌晨三点还在敲键盘的瞬间

这个“坑”之所以让人抓狂,是因为它总在最意想不到的时刻,以最隐蔽的方式出现。以下是我在过去一年中,从客户现场、社区问答、内部工单里收集到的TOP 5高频问题,每一个都附带了真实的排查过程和独家解决技巧。

5.1 问题1:任务在Manager UI提交成功,但用CLI提交就卡住(同集群、同用户、同代码)

现象描述:
客户在FusionInsight Manager Web UI上点击“提交Spark作业”,填写JAR包路径和参数,点击提交,任务秒级RUNNING。但当他用fisubmit命令行工具,输入完全相同的参数,任务就卡在ACCEPTED。

排查过程:

  • 第一反应是CLI工具版本问题,检查fisubmit --version,发现是8.1.2,而Manager Server是8.1.3,存在小版本差异;
  • 查看fisubmit源码(位于/opt/huawei/BigData/client/Spark/spark/bin/fisubmit),发现它内部调用的是spark-submit,但会额外添加--conf spark.yarn.submit.waitAppCompletion=true(即强制同步);
  • 对比Web UI的提交日志(/var/log/FusionInsight/Manager/manager-server.log),发现UI提交时,Manager Server日志里有[INFO] Generating delegation token for application_...,而CLI提交时,这条日志完全缺失;
  • 最终定位:fisubmit脚本在8.1.2版本中,有一个硬编码逻辑:当检测到--master yarn时,会自动添加--conf spark.yarn.submit.waitAppCompletion=true,这直接关闭了Manager插件的异步介入通道。

独家解决技巧:
不要用fisubmit,直接用spark-submit,并显式覆盖fisubmit的错误配置:

# 错误:fisubmit --master yarn ... (会自动加waitAppCompletion=true) # 正确:spark-submit --master yarn --conf spark.yarn.submit.waitAppCompletion=false ... # 更保险:在spark-submit命令后,追加一个空的--files参数,强制加载fi-client spark-submit --master yarn --conf spark.yarn.submit.waitAppCompletion=false --files /dev/null ...

5.2 问题2:任务偶尔成功,偶尔卡住,毫无规律(同一台Client,同一段代码)

现象描述:
开发人员在自己的笔记本上,用同一个spark-submit命令,今天提交10次全成功,明天提交10次有7次卡住。重启Client机器、重装fi-client都无效。

排查过程:

  • 初步怀疑是网络抖动,但抓包发现KDC通信稳定;
  • 检查/tmp目录空间,发现/tmp已满(98%),而spark-submit默认在/tmp下创建临时目录;
  • spark-submit在生成Token时,会先在/tmp下创建一个随机目录,再将Token写入。如果/tmp满,创建失败,但错误被静默吞掉;
  • 查看spark-submit的debug日志(加--conf spark.logConf=true),发现一行WARN FileUtil: Failed to create /tmp/spark-xxx, using /home/devuser/tmp instead,但后续的Token生成逻辑仍试图写入/tmp,导致失败。

独家解决技巧:
永远不要依赖/tmp。在spark-submit中,强制指定所有临时目录:

spark-submit \ --master yarn \ --conf spark.yarn.submit.waitAppCompletion=false \ --conf spark.local.dir=/home/devuser/spark-tmp \ # Driver本地临时目录 --conf spark.yarn.stagingDir=hdfs:///user/devuser/staging \ # YARN staging目录 --conf spark.yarn.preserve.staging.files=true \ # 保留staging文件,便于调试 ...

并在Client节点上,确保/home/devuser/spark-tmp目录存在且有足够空间。

5.3 问题3:AM容器启动后,日志显示java.lang.SecurityException: Unable to locate a login configuration(Kerberos配置缺失)

现象描述:
AM容器终于启动了(状态变为RUNNING),但几秒后就FAIL,AM日志里抛出SecurityException,提示找不到login配置。

排查过程:

  • 这个异常很经典,通常意味着java.security.auth.login.config系统属性未设置;
  • 在Manager定制流程下,这个属性应该由Manager插件自动注入。检查AM的stdout日志,发现-Djava.security.auth.login.config=...参数确实缺失;
  • 进一步检查Manager Server日志,发现大量WARN FiYarnShim: Failed to inject login config;
  • 原因:Manager插件的fi-yarn-shimjar包,与当前Spark版本的spark-yarn_2.12-3.1.3.jar存在类加载冲突,导致插件初始化失败。

独家解决技巧:
这是一个典型的jar包冲突问题。解决方案是隔离插件类加载器:

# 编辑FusionInsight Manager的YARN插件配置 # 文件路径:/opt/huawei/BigData/FusionInsight_Manager/conf/yarn-site.xml # 添加以下属性: <property> <name>yarn.nodemanager.env-whitelist</name> <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,SPARK_CONF_DIR,SPARK_HOME,SPARK_MASTER,SPARK_YARN_MODE,SPARK_JARS,SPARK_ASSEMBLY_JAR,SPARK_SUBMIT_OPTS,SPARK_DRIVER_MEMORY,SPARK_EXECUTOR_MEMORY,SPARK_EXECUTOR_CORES,SPARK_DRIVER_CORES,SPARK_DRIVER_EXTRA_JAVA_OPTIONS,SPARK_EXECUTOR_EXTRA_JAVA_OPTIONS,SPARK_YARN_APPMASTER_JAVA_OPTS,SPARK_YARN_STAGING_DIR,SPARK_YARN_CACHE_FILES,SPARK_YARN_CACHE_ARCHIVES,SPARK_YARN_CACHE_FILES_TIMESTAMPS,SPARK_YARN_CACHE_ARCHIVES_TIMESTAMPS,SPARK_YARN_CACHE_FILES_SIZES,SPARK_YARN_CACHE_ARCHIVES_SIZES,SPARK_YARN_CACHE_FILES_VISIBILITIES,SPARK_YARN_CACHE_ARCHIVES_VISIBILITIES,SPARK_YARN_CACHE_FILES_DELEGATION_TOKENS,SPARK_YARN_CACHE_ARCHIVES_DELEGATION_TOKENS,SPARK_YARN_CACHE_FILES_DELEGATION_TOKENS_TIMESTAMPS,SPARK_YARN_CACHE_ARCHIVES_DELEGATION_TOKENS_TIMESTAMPS,SPARK_YARN_CACHE_FILES_DELEGATION_TOKENS_SIZES,SPARK_YARN_CACHE_ARCH

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

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

立即咨询