PySpark YARN集群模式下间歇性资源下载失败问题排查求助
报错核心信息是Resource ... is not publicly accessible and as such cannot be part of the public cache,具体原因如下:
Spark以YARN集群模式提交时,会将脚本依赖的本地文件(比如file_event.json)上传到HDFS的sparkStaging临时目录。YARN的NodeManager会尝试将这些资源下载到公共本地缓存供后续容器复用,但如果上传到HDFS的文件没有开放其他用户可读权限(即o+r权限),NodeManager就无法读取该文件,导致AM容器启动失败。
间歇性出现的诱因可能是:
- 文件上传时权限设置未稳定生效(比如HDFS权限同步延迟)
- 部分NodeManager节点的权限校验逻辑触发时机不一致
1. 提交时指定文件分发权限
在spark-submit命令中添加配置,强制设置上传文件的权限:
spark-submit \ --master yarn \ --deploy-mode cluster \ --conf spark.yarn.dist.files.permissions=664 \ # 其他参数和脚本路径
664表示文件所有者和组可读可写,其他用户可读,满足公共缓存的权限要求;若文件需要执行权限,可改为775。
2. 修复sparkStaging目录权限
如果临时目录本身权限不足,手动递归修改目录及文件权限:
hdfs dfs -chmod -R o+r /user/user01/sparkStaging
该命令会给sparkStaging下所有文件和子目录添加其他用户的读权限。
3. 禁用NodeManager公共缓存(备选方案)
如果不需要复用缓存,可直接关闭公共缓存功能,绕开权限校验:
spark-submit \ --master yarn \ --deploy-mode cluster \ --conf spark.yarn.use.node-manager-local-cache=false \ # 其他参数和脚本路径
注意:此方案会导致每个容器都重新下载资源,可能降低集群性能,仅在权限问题无法快速修复时临时使用。
1. 开启Spark调试日志
提交时增加日志级别配置,查看文件上传的详细过程:
spark-submit \ --master yarn \ --deploy-mode cluster \ --conf spark.driver.logLevel=DEBUG \ --verbose \ # 其他参数和脚本路径
日志中会包含文件上传到HDFS的状态、路径、权限设置等信息,可直接定位是否上传失败或权限异常。
2. 直接检查HDFS临时目录
提交任务后,立即查看对应sparkStaging目录下的文件状态:
# 替换为实际的application ID hdfs dfs -ls hdfs://hdfserver/user/user01/sparkStaging/application_1704800602555_46873
确认文件是否存在,以及权限是否包含o+r(比如权限列显示-rw-rw-r--即符合要求)。
3. 查看YARN应用日志
通过YARN命令拉取应用的完整日志,定位文件下载失败的具体细节:
# 替换为实际的application ID yarn logs -applicationId application_1704800602555_46873
日志中会包含AM容器启动时的资源下载报错,可进一步确认权限问题或HDFS访问异常。
4. 在脚本中添加文件校验逻辑
如果是脚本中手动处理文件上传,可在PySpark脚本开头添加HDFS文件检查代码:
import subprocess # 检查HDFS文件是否存在及权限 def check_hdfs_file(hdfs_path): # 执行ls命令获取文件信息 result = subprocess.run(["hdfs", "dfs", "-ls", hdfs_path], capture_output=True, text=True) if result.returncode != 0: print(f"文件不存在: {hdfs_path}") return False # 解析权限列(输出的第二列) permissions = result.stdout.split()[0] if 'r' not in permissions[-1]: print(f"文件无其他用户读权限: {permissions}") return False print(f"文件状态正常: {hdfs_path}") return True # 替换为实际的文件路径 check_hdfs_file("hdfs://hdfserver/user/user01/sparkStaging/application_1704800602555_46873/file_event.json")
内容的提问来源于stack exchange,提问作者LeoMan

