Spark Executor挂载Kubernetes PVC作为本地溢写目录异常求助
核心问题梳理
你在K8s 1.21集群部署Spark 3.1.3,尝试将PVC挂载为Executor的数据溢写本地目录,但三次测试均未达预期:
- 测试1:VolumeName设为
test,挂载成功但Spark未使用该目录(符合文档中需spark-local-dir-前缀的说明) - 测试2:VolumeName设为
spark-local-dir-1,出现PVC未找到的调度警告,后续Pod启动但目录未被使用 - 测试3:保留
test作为VolumeName,添加--conf spark.executorEnv.SPARK_LOCAL_DIRS=/local-data,仍出现PVC调度警告且目录未生效
分步排查与修复方案
1. 解决spark-local-dir-前缀引发的PVC调度警告
当VolumeName以spark-local-dir-开头时,Spark on K8s默认逻辑会优先尝试使用K8s emptyDir而非PVC,调度阶段会先查找对应名称的emptyDir,找不到才回退到PVC,因此出现"PVC未找到"的警告。
修复方式:
显式指定Volume类型为PVC,避免Spark自动切换到emptyDir,提交命令中添加:
--conf spark.kubernetes.executor.volumes.pvc.spark-local-dir-1.options.claimName=你的PVC名称 \ --conf spark.kubernetes.executor.volumes.pvc.spark-local-dir-1.mount.path=/local-data \ --conf spark.kubernetes.executor.volumes.pvc.spark-local-dir-1.mount.readOnly=false
确保claimName与你预先创建的PVC名称完全一致,且和VolumeName的配置一一对应。
2. 确保Spark正确识别溢写目录
Spark不会自动使用挂载目录作为溢写目录,即使前缀符合要求,也需显式指定spark.local.dir配置(注意:spark.executorEnv.SPARK_LOCAL_DIRS是通过环境变量传递,但Spark启动时优先读取自身配置项)。
正确配置:
提交命令中添加:
--conf spark.local.dir=/local-data
该配置会直接告诉Spark将此目录作为数据溢写本地目录,优先级高于环境变量。
3. 验证Executor Pod的目录权限
即使挂载成功,若/local-data目录权限不符合Spark运行用户(默认UID/GID为185)的要求,Spark也无法写入数据。
验证与修复:
- 进入Executor Pod检查权限:
kubectl exec -it <executor-pod-name> -- ls -ld /local-data - 权限不足时,可在Spark提交命令中指定运行用户:
或在PVC的存储类中配置--conf spark.kubernetes.executor.runAsUser=185 \ --conf spark.kubernetes.executor.runAsGroup=185fsGroup,确保挂载后目录权限为Spark用户可读写。
4. 检查Spark日志确认目录使用情况
查看Executor日志,搜索local dirs关键字,确认Spark是否加载了指定目录:
kubectl logs <executor-pod-name> | grep "local dirs"
若日志显示的本地目录不包含/local-data,说明配置未生效,需重新检查spark.local.dir是否正确传递到Executor。
5. 测试3的PVC调度警告排查
测试3中保留test作为VolumeName但添加spark.executorEnv.SPARK_LOCAL_DIRS,出现的警告可能是因为Spark启动时仍默认检查spark-local-dir-前缀Volume,或PVC名称与配置不匹配。
修复方式:
- 确保PVC名称与Spark配置中
claimName完全一致,且PVC已在Executor所在Namespace创建(若Spark运行在特定Namespace下)。 - 避免混合使用
spark-local-dir-前缀Volume和自定义Volume配置,保持配置一致性。
推荐完整配置示例
整合所有正确配置的Spark提交命令:
spark-submit \ --master k8s://https://<k8s-api-server>:6443 \ --deploy-mode cluster \ --name spark-pvc-test \ --class com.yourcompany.YourJob \ --conf spark.executor.instances=2 \ --conf spark.executor.cores=2 \ --conf spark.executor.memory=4G \ --conf spark.kubernetes.container.image=your-spark-image:3.1.3 \ --conf spark.kubernetes.executor.volumes.pvc.spark-local-dir-1.options.claimName=test-pvc \ --conf spark.kubernetes.executor.volumes.pvc.spark-local-dir-1.mount.path=/local-data \ --conf spark.kubernetes.executor.volumes.pvc.spark-local-dir-1.mount.readOnly=false \ --conf spark.local.dir=/local-data \ --conf spark.kubernetes.executor.runAsUser=185 \ local:///path/to/your/job.jar
内容的提问来源于stack exchange,提问作者Koedlt

