irpas技术客

Spark standalone模式在多用户环境下保存结果报错 java.io.ioexception: mkdirs failed to create fil

网络 3317

文章目录 0. 前情提要1. 解决方案2. 系统环境3. 问题描述4. 问题分析5. 解决思路6. 仍存在的问题参考资料

0. 前情提要

在服务器上用standalone模式部署了Spark,使用本地文件系统(没有使用HDFS),在多用户提交Spark application计算任务并保存结果到本地文件系统时出现问题,保存时提示:

java.io.IOException: mkdirs failed to create file

java.io.IOException: Failed to rename DeprecatedRawLocalFileStatus

因为很少有像我这么“奇葩”的使用场景(单机Standalone+本地文件系统+多用户),所以花了两三个小时搜索研究才最终解决。

1. 解决方案

不想看完整问题分析的同学可以直接采用下面的解决方案:

关闭Spark使root用户执行start-master.sh和start-worker.sh启动Spark在创建SparkSession时,将spark.hadoop.fs.permissions.umask-mode设置为000。可以在Spark安装目录的conf/spark-defaults.conf文件内设置;以pySpark为例,也可以通过这种方式在运行时设置: spark = SparkSession \ .builder \ .master("spark://youraddress:7077") \ .config("spark.hadoop.fs.permissions.umask-mode", "000") \ .appName("yourname") \ .getOrCreate() 如果你不存在多用户使用的场景,可以忽略第2、3步,使用相同的用户启动Spark和提交Spark任务即可

感兴趣的同学可以接着往下看前因后果,不感兴趣的可以右上角了

2. 系统环境 单台服务器:68 vCPUs + 600GB RAMCentOS 8Spark 3.1.2 (Standalone模式,使用本地文件系统,无HDFS)JupyterHub(支持多用户的Jupyter notebook)pySpark 3. 问题描述

用户可以正常执行Spark计算,而一旦将Spark结果输出到本地文件系统时,就会报错,比如执行df.write.csv('result')。(注意: 这里的df是Spark DataFrame,不是pandas DataFrame,如果Spark driver有足够内存将结果转换为pandas DataFrame再保存,是不会出现这个问题的)

报错分为两种情况:

启动Spark的为非root用户时:java.io.IOException: mkdirs failed to create file启动Spark的为root时:java.io.IOException: Failed to rename DeprecatedRawLocalFileStatus

会导致结果保存过程中止,无法导出计算结果

4. 问题分析

问题的根本原因在于启动Spark的用户和使用Spark进行计算的用户不同,其他用户创建的文件和文件夹无法被当前用户修改:

在Spark保存结果时,首先会以提交计算任务的用户(driver)创建一个文件夹(比如上文提到的result),该文件夹的权限为755(rwxr-xr-x),其他非权限用户不具有写权限然后,各个executor会以启动Spark的用户在上述文件夹中写入临时结果,如果启动Spark的用户不是root,就无法写入,报第一个错误如果启动Spark的用户是root,那么临时结果可以被写入,最后需要由提交计算任务的用户(driver)来重新组织。由于这些临时文件的所有者是root,所以driver没有办法修改,报第二个错误 5. 解决思路

解决问题的关键在于,在启动和提交Spark计算用户不相同的前提下,让双方创建的文件、文件夹都能够被双方修改。问题似乎很简单,设置一下umask或者ACL不就好了吗?于是我开始了一些失败的尝试:

将保存位置的默认ACL文件夹权限设置为所有人可读写将用户的umask设置为000(所有人可读写)

结果发现,在保存Spark结果的时候,这些设置都没有生效,生成的文件权限依然为755 这说明Spark有自己的一套配置覆盖了上面的默认配置,那么这个配置在哪呢?

答案是spark.hadoop.fs.permissions.umask-mode,其默认值为022,所以生成的文件权限依然为755(感谢这位答主)。

然而,我以为我的使用环境(本地文件系统)不适用这个配置项,所以刚开始看到这个答案的时候不以为然直接忽略了…… 后来又折腾了几个小时,抱着试一试的心态,发现居然成功了

6. 仍存在的问题 首先肯定是安全性的问题,用户的文件理应只有用户自己能修改(或者至少是组成员)。因为这台服务器的用户都是可信的,所以图省事我把umask-mode改成了000,稍微安全一点的做法是改成002,然后建立一个(或多个)新组把Spark启动用户和计算用户加入进去即使umask-mode改成了000,如果启动Spark的用户不是root,依然会报第一个错误,原因不明有条件、不怕麻烦的话大家还是上HDFS或者其他文件系统吧,起码出了问题后能搜到的相关内容都更多些

谨以我昨晚的搜索记录纪念一下这次debug:

参考资料 https://spark.apache.org/docs/latest/configuration.htmlhttps://stackoverflow.com/questions/43077881/spark-how-to-write-files-with-a-given-permissionhttps://stackoverflow.com/questions/51769375/how-to-force-spark-hive-to-create-task-directories-with-custom-permissionshttps://·/user@spark.apache.org/msg28820.htmlhttps://stackoverflow.com/a/35987436/6059213


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #spark #mkdirs #failed #To #create #Fil