HDP集群中PySpark以Yarn为Master时HDFS读写异常问题咨询
我来帮你拆解一下这个问题里你可能没注意到的几个核心Spark on YARN概念,这些正是导致你遇到问题的关键:
1. YARN与本地模式的执行环境本质差异
本地模式下,Spark的Driver和所有Executor都跑在你启动命令的那台机器上,直接复用本地的HDFS客户端配置就能访问HDFS。但YARN模式完全不一样——Executor是分散在集群的Worker节点容器里运行的,它们的环境配置是从YARN集群的全局配置里获取的,不是你本地机器的那套。
举个例子:你本地写/user/hive/warehouse能访问,但YARN容器里的Executor可能因为默认文件系统配置成了本地磁盘(而不是HDFS),就会把这个路径解析成Worker节点本地的/user/hive/warehouse,自然会提示“目录不存在”。
2. HDFS路径的URI规范必须重视
你可能习惯了写相对路径或者省略协议的短路径(比如/tmp/data),本地模式下Spark会自动用你core-site.xml里的fs.defaultFS补全成完整的HDFS URI(比如hdfs://namenode:8020/tmp/data)。但在YARN模式下,如果Executor的配置没同步好,或者你没明确指定协议,Executor就会把路径当成本地磁盘路径处理。
解决方式很直接:永远用完整的HDFS URI指定路径,比如hdfs://your-namenode-host:8020/user/yourname/input,别再只写/user/yourname/input这种短路径了。
3. YARN的权限与资源隔离机制
YARN会给每个Spark任务创建独立的容器,容器的运行用户是你提交任务的用户(或者通过spark.yarn.principal指定的Kerberos用户)。如果这个用户没有目标HDFS目录的读写权限,HDFS有时候会返回“目录不存在”的模糊提示(本质是权限不足),或者保存RDD时直接失败。
你可以先在本地用hdfs dfs -ls /目标路径检查权限,确保提交任务的用户有对应的读/写权限;如果是Kerberos集群,还要确保你提交任务时带了正确的票据(kinit后的状态)。
4. Spark on YARN的部署模式区别(客户端vs集群)
你可能没留意--deploy-mode这个参数的影响:
- 客户端模式:Driver留在你提交任务的本地机器,Executor在YARN集群。这种模式下Driver用本地配置,但Executor还是依赖集群配置。
- 集群模式:Driver也跑在YARN的容器里,完全使用集群的配置。
不管哪种模式,都要确保Executor能拿到正确的HDFS配置。你可以在提交任务时通过--files参数把HDFS的配置文件传递给Executor,比如:
spark-submit --master yarn --deploy-mode cluster --files /etc/hadoop/conf/core-site.xml,/etc/hadoop/conf/hdfs-site.xml your_pyspark_script.py
这样每个Executor容器里都会有正确的HDFS配置,能准确找到NameNode。
5. DataFrame转RDD后的保存逻辑差异
DataFrame的保存API(比如write.parquet)会自动适配Spark的文件系统配置,但转成RDD后,saveAsTextFile这类方法更底层,完全依赖Executor的默认文件系统配置。如果Executor默认不是HDFS,就会把数据写到每个Worker节点的本地磁盘,而不是HDFS上——你自然会觉得“无法正常工作”。
解决方法还是一样:给RDD保存路径指定完整的HDFS URI,或者确保Executor的默认文件系统配置正确指向HDFS。
总结一下,你遗漏的核心概念就是:YARN模式下Executor的独立执行环境、HDFS路径的URI规范、YARN的权限隔离机制,以及Spark on YARN的两种部署模式差异。把这些点补上,调整你的路径写法和提交参数,问题应该就能解决了。
内容的提问来源于stack exchange,提问作者Fisseha Berhane




