You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置SPARK_USER环境变量导致K8s上Spark的S3写入失败

Spark在K8s上设置SPARK_USER后S3写入仅生成_SUCCESS文件的问题解决

问题描述

在Kubernetes环境运行Spark作业时,为了在Spark History Server里区分自己的作业,手动设置了SPARK_USER环境变量,结果出现S3写入异常:作业执行完后,S3路径下只生成_SUCCESS文件,没有实际数据输出;但移除SPARK_USER的设置后,S3写入就恢复正常,本地文件系统写入也不受影响,CSV和Parquet格式都存在这个问题。

用户使用的Spark配置如下:

spark.hadoop.fs.s3a.metadatastore.impl org.apache.hadoop.fs.s3a.s3guard.NullMetadataStore
spark.hadoop.fs.defaultFS file:///
spark.sql.parquet.binaryAsString true
spark.hadoop.fs.s3a.experimental.input.fadvise normal
spark.hadoop.parquet.enable.summary-metadata false
spark.sql.parquet.mergeSchema false
spark.sql.parquet.filterPushdown true
spark.sql.parquet.compression.codec snappy
spark.speculation false
spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version 2
spark.hadoop.mapreduce.outputcommitter.factory.scheme.s3a org.apache.hadoop.fs.s3a.commit.S3ACommitterFactory
spark.hadoop.fs.s3a.committer.name directory
spark.hadoop.fs.s3a.committer.staging.conflict-mode append
spark.sql.sources.commitProtocolClass org.apache.spark.internal.io.cloud.PathOutputCommitProtocol
spark.sql.parquet.output.committer.class org.apache.spark.internal.io.cloud.BindingParquetOutputCommitter
spark.kubernetes.driver.volumes.persistentVolumeClaim.datasets.options.claimName datasets
spark.hadoop.fs.s3a.readahead.range 256K
spark.hadoop.fs.s3a.committer.tmp.path file:///mnt/data/scratch/scratch/tmp
spark.hadoop.fs.s3a.committer.staging.tmp.path /mnt/data/scratch/scratch/staging
spark.hadoop.fs.s3a.buffer.dir /mnt/data/scratch/scratch/buffer
spark.kubernetes.driver.volumes.persistentVolumeClaim.datasets.mount.path /mnt/data/scratch/scratch
spark.serializer org.apache.spark.serializer.KryoSerializer
spark.kryoserializer.buffer.max 2047m
spark.kryoserializer.buffer 256m
spark.hadoop.fs.s3a.multipart.size 256m

问题原因

核心问题出在S3A Directory Committer的本地临时目录权限上:
当设置SPARK_USER后,Spark作业会以该用户身份去创建和使用配置里的临时目录(spark.hadoop.fs.s3a.committer.tmp.path、staging.tmp.path等),但Kubernetes容器中该用户可能没有这些路径的读写权限,导致Task阶段生成的临时数据无法被提交器同步到S3,最后只完成了提交标记(_SUCCESS),实际数据却没传上去。

解决方案

1. 给SPARK_USER授权临时目录权限

在K8s Pod的启动脚本里,提前创建配置中的临时路径,并把权限赋给SPARK_USER:

mkdir -p /mnt/data/scratch/scratch/tmp /mnt/data/scratch/scratch/staging /mnt/data/scratch/scratch/buffer
chown -R $SPARK_USER:$SPARK_USER /mnt/data/scratch/scratch

或者直接把临时目录改成容器内默认有读写权限的路径(比如/tmp),修改Spark配置:

spark.hadoop.fs.s3a.committer.tmp.path file:///tmp/s3a-committer-tmp
spark.hadoop.fs.s3a.committer.staging.tmp.path /tmp/s3a-committer-staging
spark.hadoop.fs.s3a.buffer.dir /tmp/s3a-buffer

2. 换成S3A Magic Committer

Magic Committer是专门为云存储设计的提交器,能避免本地临时目录的权限问题,修改以下配置即可切换:

spark.hadoop.fs.s3a.committer.name magic
spark.hadoop.mapreduce.outputcommitter.factory.scheme.s3a org.apache.hadoop.fs.s3a.commit.S3ACommitterFactory

注意:需要确保你的Spark(2.4+)和Hadoop(3.1+)版本兼容Magic Committer。

3. 不用SPARK_USER,改用其他方式标记作业

如果只是为了在History Server区分作业,没必要硬改SPARK_USER,可以用这些方式:

  • 提交作业时自定义应用名称,带上标识:
    spark-submit --conf spark.app.name="MyJob_${USER}" ...
    
  • 或者通过Spark配置设置用户标识(部分版本支持):
    spark.user=your-custom-user
    

验证

修改配置后重新提交作业,检查S3路径是否生成了实际的数据文件,同时确认Spark History Server里的作业标识是否正确显示。

内容的提问来源于stack exchange,提问作者Hutch3232

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:10:05