Spark on K8s提交任务报错:Kubernetes模式不支持引用本地应用依赖
这个错误的原因非常明确:Kubernetes部署模式下,Spark无法直接引用本地文件系统中的应用依赖。
当你使用--deploy-mode cluster时,Spark Driver会作为一个Pod在Kubernetes集群内部的某个节点启动,它完全无法访问你提交命令的本地机器的文件系统,所以你用local:///opt/spark/examples/jars/spark-examples_2.11-2.3.0.jar这种本地路径是行不通的。
下面给你几个可行的解决方案:
方案1:将Jar包打包到自定义Spark镜像中
如果你的docker.io/garfiny/spark:v2.3.0是自己构建的镜像,可以把spark-examples_2.11-2.3.0.jar提前复制到镜像的/opt/spark/examples/jars/目录下。这样提交命令时虽然路径还是local:///...,但此时的local指的是Driver Pod内部的文件系统,就可以正常访问了。
方案2:使用远程存储服务托管Jar包
把你的Jar包上传到HTTP服务器、S3、GCS或者其他支持远程访问的存储服务,然后在提交命令中使用对应的远程URL:
修改后的spark-submit命令示例(假设Jar包放在HTTP服务器上):
~/opt/spark/spark-2.3.0-bin-hadoop2.7/bin/spark-submit \ --master k8s://https://206.189.126.172:6443 \ --deploy-mode cluster \ --name word-count \ --class org.apache.spark.examples.SparkPi \ --conf spark.executor.instances=5 \ --conf spark.kubernetes.container.image=docker.io/garfiny/spark:v2.3.0 \ --conf spark.kubernetes.driver.pod.name=word-count \ http://your-http-server-address/spark-examples_2.11-2.3.0.jar
方案3:通过Kubernetes ConfigMap/Secret挂载Jar包
你可以把Jar包创建成Kubernetes的ConfigMap(或者Secret,如果是敏感文件),然后在Spark配置中指定将这个ConfigMap挂载到Driver和Executor Pod的某个路径下,之后用local://引用挂载后的路径。不过这个步骤相对繁琐,适合需要频繁更新Jar包的场景。
另外注意:你提交命令中的—-conf spark.kubernetes.driver.pod.name=word-count使用了全角的破折号,要改成半角的--conf,避免出现不必要的解析错误。
内容的提问来源于stack exchange,提问作者garfiny

