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

如何在Spark客户端模式下阻止Executor复制JAR包

解决Spark Kubernetes客户端模式下JAR包重复复制的问题

核心问题分析

你遇到的慢启动问题,本质是客户端模式下Spark默认会将Driver端的依赖JAR包逐个传递给Executor,哪怕Executor已经能通过镜像或共享存储访问到这些JAR。之前的配置没生效,主要是两个原因:

  1. 保留了--packages参数,该参数会强制Spark Driver下载依赖并自动同步给Executor;
  2. 未显式配置让Executor优先使用本地(镜像/NFS)的JAR,而非Driver传递的版本。

下面给出两种可行的解决方案:


方案一:基于自定义Docker镜像(推荐)

将所有依赖JAR打包到Spark镜像中,从根源上避免JAR传输:

1. 构建自定义镜像

创建Dockerfile,基于官方Spark镜像添加依赖JAR:

FROM apache/spark-py:v3.3.2

# 将预先下载好的Iceberg、AWS SDK等JAR包复制到镜像内的固定目录
COPY ./extra-jars/ /opt/spark/jars/extra/
  • 提前下载所需JAR包到本地extra-jars目录(可通过spark-shell --packages 目标包名 --exclude-packages org.slf4j:slf4j-api下载后从缓存目录提取);
  • 构建并推送镜像到你的Kubernetes镜像仓库:docker build -t your-registry/spark-py-extra:v3.3.2 . && docker push your-registry/spark-py-extra:v3.3.2

2. 客户端模式配置(Jupyter Notebook示例)

在SparkSession初始化时,移除--packages参数,添加以下关键配置:

from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .master("k8s://https://10.164.64.27:6443") \
    .appName("your-app-name") \
    .config("spark.kubernetes.namespace", "spark-cluster") \
    .config("spark.kubernetes.authenticate.driver.serviceAccountName", "spark-sa") \
    .config("spark.executor.instances", "2") \
    # 使用自定义镜像
    .config("spark.kubernetes.driver.container.image", "your-registry/spark-py-extra:v3.3.2") \
    .config("spark.kubernetes.executor.container.image", "your-registry/spark-py-extra:v3.3.2") \
    # 让Executor优先使用镜像内的JAR,忽略Driver传递的依赖
    .config("spark.executor.userClassPathFirst", "true") \
    # 指定Executor使用镜像内的JAR路径
    .config("spark.executor.extraClassPath", "/opt/spark/jars/extra/*") \
    # Driver端(Jupyter所在环境)需能访问相同依赖,可挂载NFS或本地存放JAR
    .config("spark.driver.extraClassPath", "/tmp/spark-data/jars/*") \
    .getOrCreate()

方案二:复用NFS共享存储

如果不想构建镜像,可通过显式配置Executor挂载NFS,让Executor直接读取共享存储中的JAR:

1. 配置Executor挂载NFS

在SparkSession中添加Kubernetes Volume挂载配置,确保Executor能访问NFS:

from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .master("k8s://https://10.164.64.27:6443") \
    .appName("your-app-name") \
    .config("spark.kubernetes.namespace", "spark-cluster") \
    .config("spark.kubernetes.authenticate.driver.serviceAccountName", "spark-sa") \
    .config("spark.executor.instances", "2") \
    .config("spark.kubernetes.driver.container.image", "apache/spark-py:v3.3.2") \
    .config("spark.kubernetes.executor.container.image", "apache/spark-py:v3.3.2") \
    # 配置Executor挂载NFS
    .config("spark.kubernetes.executor.volumes.nfs.spark-data.mount.path", "/tmp/spark-data") \
    .config("spark.kubernetes.executor.volumes.nfs.spark-data.mount.readOnly", "true") \
    .config("spark.kubernetes.executor.volumes.nfs.spark-data.server", "your-nfs-server-ip") \
    .config("spark.kubernetes.executor.volumes.nfs.spark-data.path", "/nfs/shared/path") \
    # 让Executor优先使用NFS中的JAR
    .config("spark.executor.userClassPathFirst", "true") \
    .config("spark.executor.extraClassPath", "local:///tmp/spark-data/jars/*") \
    # Driver端(Jupyter所在节点)需挂载同一NFS到/tmp/spark-data
    .config("spark.driver.extraClassPath", "/tmp/spark-data/jars/*") \
    .getOrCreate()

2. 关键注意事项

  • 必须移除所有--packages参数,否则Spark仍会强制同步Driver下载的JAR;
  • Jupyter所在的节点必须挂载同一个NFS到/tmp/spark-data,确保Driver能读取依赖JAR;
  • local://前缀用于告诉Spark使用Executor本地文件系统的JAR,而非分布式存储。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:33:11