Spark on Kubernetes提交作业因PostgreSQL依赖jar无法创建Executor
Kubernetes环境Spark提交作业PostgreSQL依赖加载异常解决方案
问题描述
在Kubernetes环境使用spark-submit提交PySpark作业,出现postgresql-42.2.14.jar加载失败,无法创建Executor的错误。
提交命令
/usr/middleware/spark-3.1.1-bin-hadoop3.2/bin/spark-submit --master k8s://https://112.23.123.23:6443 --deploy-mode cluster --name spark-postgres-minio-kubernetes --jars file:///AirflowData/kubernetes/externalJars/postgresql-42.2.14.jar --driver-class-path file:///AirflowData/kubernetes/externalJars/postgresql-42.2.14.jar --conf spark.executor.instances=1 --conf spark.kubernetes.namespace=spark --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark --conf spark.kubernetes.file.upload.path=s3a://daci-dataintegration/spark-operator-on-k8s/code --conf spark.hadoop.fs.s3a.fast.upload=true --conf spark.kubernetes.container.image=hostname:5000/spark-py:spark3.1.2 file:///AirflowData/kubernetes/python/postgresminioKube.py
作业代码
from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql import functions as F spark = SparkSession.builder.appName("Postgres-Minio-Kubernetes").getOrCreate() import json #spark = SparkSession.builder.config('spark.driver.extraClassPath', '/hadoop/externalJars/db2jcc4.jar').getOrCreate() jdbcUrl = "jdbc:postgresql://{0}:{1}/{2}".format("hosnamme", "port", "db") connectionProperties = { "user" : "username", "password" : "password", "driver": "org.postgresql.Driver", "fetchsize" : "100000" } pushdown_query = "(select * from public.employees) emp_als" df = spark.read.jdbc(url=jdbcUrl, table=pushdown_query, column="employee_id", lowerBound=1, upperBound=100, numPartitions=2, properties=connectionProperties) df.write.format('csv').options(delimiter=',').mode('overwrite').save('s3a://daci-dataintegration/spark-operator-on-k8s/data/postgres-minio-csv/') df.write.format('parquet').options(delimiter='|').options(header=True).mode('overwrite').save('s3a://daci-dataintegration/spark-operator-on-k8s/data/postgres-minio-csv/')
报错日志
21/11/09 17:05:44 INFO SparkContext: Added JAR file:/tmp/spark-d987d7e7-9d49-4523-8415-1e438da1730e/postgresql-42.2.14.jar at spark://spark-postgres-minio-kubernetes-49d7d77d05a980e5-driver-svc.spark.svc:7078/jars/postgresql-42.2.14.jar with timestamp 1636477543573 21/11/09 17:05:49 ERROR TaskSchedulerImpl: Lost executor 1 on 192.168.216.12: Unable to create executor due to ./postgresql-42.2.14.jar
根因说明
- K8s cluster模式下,Driver和Executor分别运行在独立的Pod中,仅在Driver本地路径存放的Jar无法被Executor直接访问
- 提交命令仅配置了
--driver-class-path,未配置Executor的类路径,Executor无法识别驱动Jar的位置 - 提交命令使用
file://协议指定本地Jar路径,Spark会尝试从Driver的服务端口拉取Jar到Executor的工作目录,网络访问异常或路径不匹配时就会加载失败
解决方案
方案一:直接使用镜像内置Jar(优先选择)
你已经将PostgreSQL驱动Jar放到了镜像内的spark_home/jars目录,Spark启动时会自动加载该目录下的所有Jar,直接删除提交命令中的--jars和--driver-class-path参数即可,不需要额外配置依赖路径。
方案二:使用分布式存储存放依赖
如果不想把依赖打到镜像中,按以下步骤修改:
- 将postgresql-42.2.14.jar上传到你已配置的MinIO路径下,例如
s3a://daci-dataintegration/spark-operator-on-k8s/jars/ - 修改提交命令的
--jars参数为对应的S3路径:--jars s3a://daci-dataintegration/spark-operator-on-k8s/jars/postgresql-42.2.14.jar - 新增Executor类路径配置:
--conf spark.executor.extraClassPath=./postgresql-42.2.14.jar
方案三:保留本地Jar提交方式
如果必须使用本地路径提交Jar,新增以下两个配置即可:
--conf spark.executor.extraClassPath=./postgresql-42.2.14.jar--conf spark.kubernetes.driver.service.port=7078确保Executor Pod可以正常访问Driver的Jar下载端口
校验方式
提交作业后查看Executor的启动日志,确认没有类找不到的报错,作业可以正常读取PostgreSQL数据即可。
内容的提问来源于stack exchange,提问作者Rafa
相关产品推荐
相关产品推荐

