Spark独立集群与客户端分属不同用户的权限问题咨询
Spark独立集群跨用户数据持久化权限问题解决方案
问题背景
多台虚拟机以sparkcluster用户运行Spark 3.3独立集群(1主3从),本地Windows机器部署客户端应用连接集群执行数据加载、持久化与转换操作。Spark UI确认连接成功,但持久化数据时抛出IO异常,已排查出原因是集群运行用户与客户端应用运行用户不一致。不想将应用部署到集群机器(违背分布式设计初衷),询问是否可通过配置用户/客户端白名单允许特定客户端执行操作。
异常信息
核心异常
java.io.IOException: Mkdirs failed to create file:/share/data/spark/load/TESTCACHE/f1ab4f4b-0b95-490b-b05c-5154cec2ae6b/fb51846b-c20d-42b3-bb3c-74abf71d10a2.part/_temporary/0/_temporary/attempt_202211301636564407278350514085268_0003_m_000000_34 (exists=false, cwd=file:/app/spark/spark-3.3.0-bin-hadoop3/work/app-20221129201401-0055/0)
完整堆栈
17:33:21.372 [task-result-getter-2] WARN org.apache.spark.scheduler.TaskSetManager - Lost task 0.0 in stage 2.0 (TID 2) (30.103.216.22 executor 0): java.io.IOException: Mkdirs failed to create file:/share/data/spark/tmp_load/b0ef0b46-da4c-474a-b381-72d79ba38161.part/_temporary/0/_temporary/attempt_202211292233192374251041408678060_0002_m_000000_2 (exists=false, cwd=file:/app/spark/spark-3.3.0-bin-hadoop3/work/app-20221129201401-0055/0) at org.apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.java:515) at org.apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.java:500) at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:1195) at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:1175) at org.apache.parquet.hadoop.util.HadoopOutputFile.create(HadoopOutputFile.java:74) at org.apache.parquet.hadoop.ParquetFileWriter.<init>(ParquetFileWriter.java:329) at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:482) at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:420) at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:409) at org.apache.spark.sql.execution.datasources.parquet.ParquetOutputWriter.<init>(ParquetOutputWriter.scala:36) at org.apache.spark.sql.execution.datasources.parquet.ParquetFileFormat$$anon$1.newInstance(ParquetFileFormat.scala:155) at org.apache.spark.sql.execution.datasources.SingleDirectoryDataWriter.newOutputWriter(FileFormatDataWriter.scala:161) at org.apache.spark.sql.execution.datasources.SingleDirectoryDataWriter.<init>(FileFormatDataWriter.scala:146) at org.apache.spark.sql.execution.datasources.FileFormatWriter$.executeTask(FileFormatWriter.scala:317) at org.apache.spark.sql.execution.datasources.FileFormatWriter$.$anonfun$write$21(FileFormatWriter.scala:256) at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:90) at org.apache.spark.scheduler.Task.run(Task.scala:136) at org.apache.spark.executor.Executor$TaskRunner.$anonfun$run$3(Executor.scala:548) at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:1504) at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:551) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834)
原因分析
客户端提交任务后,Spark Executor以集群节点的sparkcluster用户运行,但客户端的本地用户与sparkcluster用户权限隔离,导致Executor无法在共享存储目录下创建临时文件/目录,触发权限报错。
解决方案
1. 配置Spark独立集群用户白名单与访问控制
通过Spark内置的ACL(访问控制列表)功能,允许指定客户端用户在集群执行操作:
- 修改主节点
spark-env.sh:
参数说明:export SPARK_MASTER_OPTS="-Dspark.authenticate=true -Dspark.authenticate.secret=your-secure-secret -Dspark.acls.enable=true -Dspark.admin.acls=sparkcluster,your-windows-username"spark.authenticate=true:开启集群节点间身份认证spark.authenticate.secret:设置集群共享密钥,所有节点需保持一致spark.acls.enable=true:启用访问控制列表spark.admin.acls:添加拥有管理员权限的用户,包含集群用户sparkcluster和客户端Windows用户名
- 修改
spark-defaults.conf:
分别设置UI查看权限和任务修改权限,确保客户端用户可正常操作。spark.ui.view.acls=sparkcluster,your-windows-username spark.modify.acls=sparkcluster,your-windows-username - 同步配置到所有Worker节点,然后重启Spark集群。
2. 统一任务执行用户身份
客户端提交任务时,强制指定任务以sparkcluster用户身份执行,绕开用户权限差异:
- 提交命令添加参数:
spark-submit --conf spark.executorEnv.USER=sparkcluster --conf spark.driverEnv.USER=sparkcluster --class your.main.class your-app.jar - 代码中设置配置:
import org.apache.spark.sql.SparkSession val spark = SparkSession.builder() .appName("YourApp") .master("spark://master-ip:7077") .config("spark.executorEnv.USER", "sparkcluster") .config("spark.driverEnv.USER", "sparkcluster") .getOrCreate()
3. 配置共享存储代理权限(适用于HDFS场景)
如果共享存储使用HDFS,可通过Hadoop代理用户配置,允许sparkcluster代理客户端用户操作:
- 修改HDFS的
hadoop-env.sh:
允许export HADOOP_OPTS="-Dhadoop.proxyuser.sparkcluster.hosts=your-windows-client-ip -Dhadoop.proxyuser.sparkcluster.groups=*"sparkcluster用户代理来自指定Windows客户端IP的所有用户组,操作HDFS资源。
4. 调整共享存储目录权限(测试环境临时方案)
直接为共享存储目录添加全局写入权限(不推荐生产环境使用):
chmod -R 777 /share/data/spark/
内容的提问来源于stack exchange,提问作者vs777
相关产品推荐
相关产品推荐

