纯PySpark安装中GS文件系统报错的解决及默认配置方案
问题场景
我已查阅多个相关问题及博客文章,编写了以下PySpark脚本尝试读取GCS桶数据:
from pyspark.sql import SparkSession spark = SparkSession.builder\ .appName("GCSFilesRead")\ .getOrCreate() bucket_name="my-gcs-bucket" path=f"gs://{bucket_name}/path/to/file.csv" df=spark.read.csv(path, header=True) print(df.head())
运行时出现错误:
py4j.protocol.Py4JJavaError: An error occurred while calling o29.csv. : org.apache.hadoop.fs.UnsupportedFileSystemException: No FileSystem for scheme "gs" at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:3443) at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:3466) at org.apache.hadoop.fs.FileSystem.access$300(FileSystem.java:174) at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:3574)
我的环境通过Dockerfile搭建,内容如下:
FROM openjdk:11.0.11-jre-slim-buster # install a whole bunch of apt-get dev essential libraries (unixodbc-dev, libgdbm-dev...) # some other setup for other services # copy my repository, requirements file # install Python-3.9 and activate a venv RUN pip install pyspark==3.3.1
当前环境无HADOOP_HOME、SPARK_HOME等环境变量,仅为纯PySpark安装。我尝试过以下配置,但仍出现相同错误:
配置1:
spark = SparkSession.builder\ .appName("GCSFilesRead")\ .config("spark.jars.package", "/path/to/jar/gcs-connector-hadoop3-2.2.10.jar") \ .getOrCreate()
配置2:
spark = SparkSession.builder\ .appName("GCSFilesRead")\ .config("fs.gs.impl", "com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem")\ .config("fs.AbstractFileSystem.gs.impl", "com.google.cloud.hadoop.fs.gcs.GoogleHadoopFS")\ .getOrCreate()
现咨询两个问题:
- 在当前环境下,需进行哪些操作才能让脚本正常运行?我看到过修改
pom.xml、core-site.xml的方案,但纯PySpark安装似乎没有这些文件。 - 如何在纯PySpark安装中将Jar包安装/配置设为Spark默认设置?我希望直接运行
python path/to/file.py即可,无需在spark-submit中传参或在SparkSession中配置。我知道常规Spark安装可通过spark-defaults.conf添加默认Jar,但纯PySpark安装似乎没有该文件。
问题1:让脚本正常运行的操作
你之前的配置存在两个核心问题:spark.jars.package用于拉取Maven仓库依赖,本地Jar需用spark.jars参数;仅配置FileSystem实现类不够,必须确保GCS连接器Jar被加载,同时处理私有桶的认证。具体步骤:
下载并放置对应版本的GCS连接器Jar
PySpark 3.3.1对应Hadoop 3.x,需下载gcs-connector-hadoop3-2.2.10.jar(或兼容版本)。在Dockerfile中添加以下命令,将Jar放入PySpark的默认jars目录:# 获取PySpark安装路径并下载Jar RUN SPARK_HOME=$(python -c "import pyspark; print(pyspark.__path__[0])") \ && wget -P $SPARK_HOME/jars https://repo1.maven.org/maven2/com/google/cloud/bigdataoss/gcs-connector/hadoop3-2.2.10/gcs-connector-hadoop3-2.2.10.jar修正SparkSession配置
加载Jar并指定FileSystem实现,同时添加私有桶认证配置:from pyspark.sql import SparkSession spark = SparkSession.builder\ .appName("GCSFilesRead")\ .config("fs.gs.impl", "com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem")\ .config("fs.AbstractFileSystem.gs.impl", "com.google.cloud.hadoop.fs.gcs.GoogleHadoopFS")\ # 私有桶需配置服务账号密钥路径 .config("google.cloud.auth.service.account.json.keyfile", "/path/to/service-account-key.json")\ .getOrCreate() bucket_name="my-gcs-bucket" path=f"gs://{bucket_name}/path/to/file.csv" df=spark.read.csv(path, header=True) print(df.head())若Jar已放入
SPARK_HOME/jars,可省略spark.jars配置,Spark会自动加载。处理私有桶认证
将服务账号密钥文件复制到Docker镜像,并设置环境变量:COPY service-account-key.json /path/to/service-account-key.json ENV GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"
问题2:将Jar配置为PySpark默认设置
针对纯PySpark安装,可通过以下三种方式实现默认加载:
方式1:将Jar放入PySpark默认jars目录
pip安装的PySpark默认jars目录为虚拟环境路径/lib/pythonX.X/site-packages/pyspark/jars,将GCS连接器Jar复制到该目录后,Spark启动时会自动加载所有Jar。Dockerfile中的配置可参考问题1中的步骤1。
方式2:设置环境变量SPARK_SUBMIT_OPTS
在Dockerfile中添加环境变量,指定默认Jar和配置:
# 若Jar已放入默认jars目录,可省略--jars参数 ENV SPARK_SUBMIT_OPTS="--conf fs.gs.impl=com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem --conf fs.AbstractFileSystem.gs.impl=com.google.cloud.hadoop.fs.gcs.GoogleHadoopFS"
之后直接运行python path/to/file.py,Spark会自动应用这些配置。
方式3:自定义spark-defaults.conf
手动创建配置文件并通过环境变量指定目录:
# 创建配置目录并写入默认配置 RUN mkdir -p /opt/spark/conf RUN echo "fs.gs.impl com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem" >> /opt/spark/conf/spark-defaults.conf RUN echo "fs.AbstractFileSystem.gs.impl com.google.cloud.hadoop.fs.gcs.GoogleHadoopFS" >> /opt/spark/conf/spark-defaults.conf # 若Jar未放入默认目录,添加以下行 # RUN echo "spark.jars /path/to/gcs-connector-hadoop3-2.2.10.jar" >> /opt/spark/conf/spark-defaults.conf ENV SPARK_CONF_DIR="/opt/spark/conf"
Spark启动时会自动读取该目录下的配置。
内容的提问来源于stack exchange,提问作者kpython

