将自定义容器与 Dataproc Serverless for Spark 搭配使用

Dataproc Serverless for Spark 在 Docker 容器中运行工作负载。容器为工作负载的驱动程序和执行程序进程提供运行时环境。默认情况下,Dataproc Serverless for Spark 使用容器映像,其中包含与运行时发布版本关联的默认 Spark、Java、Python 和 R 软件包。借助 Dataproc Serverless for Spark 批处理 API,您可以使用自定义容器映像而不是默认映像。通常,自定义容器映像会添加默认容器映像未提供的 Spark 工作负载 Java 或 Python 依赖项。重要提示:请勿在自定义容器映像中包含 Spark;Dataproc Serverless for Spark 将在运行时将 Spark 装载到容器中。

使用自定义容器映像提交 Spark 批处理工作负载

gcloud

提交 Spark 批处理工作负载时,使用带有 --container-image 标志的 gcloud dataproc batches submit spark 命令指定自定义容器映像。

gcloud dataproc batches submit spark \
    --container-image=custom-image, for example, "gcr.io/my-project-id/my-image:1.0.1" \
    --region=region \
    --jars=path to user workload jar located in Cloud Storage or included in the custom container \
    --class=The fully qualified name of a class in the jar file, such as org.apache.spark.examples.SparkPi \
    -- add any workload arguments here

注意

  • 自定义映像:使用以下 Container Registry 映像命名格式指定自定义容器映像:{hostname}/{project-id}/{image}:{tag},例如“gcr.io/my-project-id/my-image:1.0.1”。 注意:您必须在 Container RegistryArtifact Registry 上托管自定义容器映像。 (Dataproc Serverless 无法从其他注册表中提取容器)。
  • --jars:指定自定义容器映像中包含的或位于 Cloud Storage 中的用户工作负载的路径,例如 file:///opt/spark/jars/spark-examples.jargs://my-bucket/spark/jars/spark-examples.jar
  • 其他批处理命令选项:您可以添加其他可选批处理的命令标志,例如,使用持久性历史记录服务器 (PHS)。注意:PHS 必须位于您运行批处理工作负载的区域。
  • 工作负载参数:您可以通过在命令末尾添加“--”和工作负载参数来添加任何工作负载参数。

REST

自定义容器映像通过 batches.create API 请求中的 RuntimeConfig.containerImage 字段进行提供。

以下示例介绍如何使用自定义容器通过 Dataproc Serverless for Spark batches.create API 提交批处理工作负载。

在使用任何请求数据之前,请先进行以下替换:

  • project-id:Google Cloud 项目 ID
  • region区域
  • custom-container-image:使用以下 Container Registry 映像命名格式指定自定义容器映像:{hostname}/{project-id}/{image}:{tag},例如“gcr.io/my-project-id/my-image:1.0.1”。 注意:您必须在 Container Registry Artifact Registry 上托管自定义容器。 (Dataproc Serverless 无法从其他注册表中提取容器)。
  • jar-uri:指定包含在自定义容器映像中或位于 Cloud Storage 中的工作负载 jar 的路径,例如“/opt/spark/jars/spark-examples.jar” 或“gs:///spark/jars/spark-examples.jar”。
  • class:jar 文件中的类的完全限定名称,例如“org.apache.spark.examples.SparkPi”。
  • 其他选项:您可以使用其他批处理工作负载资源字段,例如,使用 sparkBatch.args 字段将参数传递给您的工作负载(如需了解详情,请参阅 Batch 资源文档)。如需使用 Persistent History Server (PHS),请参阅设置 Persistent History Server。注意:PHS 必须位于您运行批处理工作负载的区域。

HTTP 方法和网址:

POST https://dataproc.googleapis.com/v1/projects/project-id/locations/region/batches

请求 JSON 正文:

{
  "runtimeConfig":{
    "containerImage":"custom-container-image
  },
  "sparkBatch":{
    "jarFileUris":[
      "jar-uri"
    ],
    "mainClass":"class"
  }
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
"name":"projects/project-id/locations/region/batches/batch-id",
  "uuid":",uuid",
  "createTime":"2021-07-22T17:03:46.393957Z",
  "runtimeConfig":{
    "containerImage":"gcr.io/my-project/my-image:1.0.1"
  },
  "sparkBatch":{
    "mainClass":"org.apache.spark.examples.SparkPi",
    "jarFileUris":[
      "/opt/spark/jars/spark-examples.jar"
    ]
  },
  "runtimeInfo":{
    "outputUri":"gs://dataproc-.../driveroutput"
  },
  "state":"SUCCEEDED",
  "stateTime":"2021-07-22T17:06:30.301789Z",
  "creator":"account-email-address",
  "runtimeConfig":{
    "properties":{
      "spark:spark.executor.instances":"2",
      "spark:spark.driver.cores":"2",
      "spark:spark.executor.cores":"2",
      "spark:spark.app.name":"projects/project-id/locations/region/batches/batch-id"
    }
  },
  "environmentConfig":{
    "peripheralsConfig":{
      "sparkHistoryServerConfig":{
      }
    }
  },
  "operation":"projects/project-id/regions/region/operation-id"
}

构建自定义容器映像

Dataproc Serverless for Spark 自定义容器映像是 Docker 映像。您可以使用用于构建 Docker 映像的工具来构建自定义容器映像,但映像必须满足一些条件才能与 Dataproc Serverless for Spark 兼容。 以下部分介绍了这些条件。

操作系统

您可以为自定义容器映像选择任何操作系统基础映像。

建议:使用默认的 Debian 12 映像(例如 debian:12-slim),因为它们已完成测试,可以避免兼容性问题。

实用程序

您必须在自定义容器映像中包含以下实用程序软件包,这些软件包是运行 Spark 所必需的:

  • procps
  • tini

如需从 Spark(Java 或 Scala)运行 XGBoost,您必须添加 libgomp1

容器用户

Dataproc Serverless for Spark 以 spark Linux 用户身份通过 1099 UID 和 1099 GID 来运行容器。自定义容器映像 Dockerfile 中设置的 USER 指令在运行时被忽略。使用 UID 和 GID 获得文件系统权限。 例如,如果您将映像中位于 /opt/spark/jars/my-lib.jar 中的 jar 文件添加为工作负载依赖项,则必须向 spark 用户授予该文件的读取权限。

映像流式传输

Dataproc Serverless for Spark 通常会将整个映像下载到磁盘,以启动需要自定义容器映像的工作负载。这可能会导致初始化时间延迟,对于有大量图片的客户来说尤其如此。

您可以改用映像流式传输,这种方法可根据需要拉取映像数据。这样一来,工作负载便可以启动,而无需等待整个映像下载完毕,从而可能缩短初始化时间。如需启用映像流式传输,您必须启用 Container File System API。您还必须将容器映像存储在 Artifact Registry 中,并且 Artifact Registry 代码库必须与您的 Dataproc 工作负载位于同一区域,或者位于与工作负载运行区域相对应的多区域中。如果 Dataproc 不支持映像或映像流式传输服务不可用,我们的流式传输实现会下载整个映像。

请注意,我们不支持以下图片流式传输:

在这些情况下,Dataproc 会先拉取整个映像,然后再启动工作负载。

Spark

请勿在自定义容器映像中包含 Spark。在运行时,Dataproc Serverless for Spark 将 Spark 二进制文件和配置从主机装载到容器中:二进制文件装载到 /usr/lib/spark 目录,配置装载到 /etc/spark/conf 目录。Dataproc Serverless for Spark 在运行时会替换这些目录中的现有文件。

Java 运行时环境

请勿在您的自定义容器映像中添加自己的 Java 运行时环境 (JRE)。在运行时,Dataproc Serverless for Spark 将 OpenJDK 从主机装载到容器中。如果您在自定义容器映像中包含 JRE,则该映像将被忽略。

Java 软件包

您可以将 jar 文件作为 Spark 工作负载依赖项添加到自定义容器映像中,也可以设置 SPARK_EXTRA_CLASSPATH 环境变量以包含 jar。Dataproc Serverless for Spark 会将环境变量值添加到 Spark JVM 进程的类路径中。建议:将 jar 放入/opt/spark/jars目录下并将 SPARK_EXTRA_CLASSPATH 设置为 /opt/spark/jars/*

您可以在自定义容器映像中添加工作负载 jar,然后在提交工作负载时通过本地路径引用该工作负载,例如 file:///opt/spark/jars/my-spark-job.jar(如需查看示例,请参阅使用自定义容器映像提交 Spark 批处理工作负载)。

Python 软件包

默认情况下,Dataproc Serverless for Spark 会在运行时将 Conda 从主机装载到容器中的 /opt/dataproc/conda 目录中。PYSPARK_PYTHON 设置为 /opt/dataproc/conda/bin/python。其基本目录 /opt/dataproc/conda/bin 包含在 PATH 中。

您可以将 Python 环境与软件包添加到自定义容器映像的其他目录中,例如 /opt/conda,并将 PYSPARK_PYTHON 环境变量设置为 /opt/conda/bin/python

您的自定义容器映像可以包含不属于 Python 环境的其他 Python 模块,例如具有实用函数的 Python 脚本。设置 PYTHONPATH 环境变量,以包含模块所在的目录。

R 环境

您可以使用以下选项之一自定义自定义容器映像中的 R 环境:

  • 使用 Conda 管理和安装 conda-forge 渠道的 R 软件包。
  • 为容器映像的 Linux OS 添加 R 代码库,并使用 Linux OS 软件包管理器安装 R 软件包(请参阅 R 软件包索引)。

使用任一选项时,您都必须将 R_HOME 环境变量设置为指向自定义 R 环境。例外情况:如果您同时使用 Conda 管理 R 环境和自定义 Python 环境,则无需设置 R_HOME 环境变量;系统会根据 PYSPARK_PYTHON 环境变量自动设置该变量。

自定义容器映像构建示例

本部分包含自定义容器映像构建示例,其中包括 Dockerfiles 示例,后跟构建命令。其中一个示例包含构建映像所需的最低配置。另一个示例包含额外配置的示例,包括 Python 和 R 库。

最低配置

# Recommendation: Use Debian 12.
FROM debian:12-slim

# Suppress interactive prompts
ENV DEBIAN_FRONTEND=noninteractive

# Install utilities required by Spark scripts.
RUN apt update && apt install -y procps tini libjemalloc2

# Enable jemalloc2 as default memory allocator
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2

# Create the 'spark' group/user.
# The GID and UID must be 1099. Home directory is required.
RUN groupadd -g 1099 spark
RUN useradd -u 1099 -g 1099 -d /home/spark -m spark
USER spark
    

额外配置

# Recommendation: Use Debian 12.
FROM debian:12-slim

# Suppress interactive prompts
ENV DEBIAN_FRONTEND=noninteractive

# Install utilities required by Spark scripts.
RUN apt update && apt install -y procps tini libjemalloc2

# Enable jemalloc2 as default memory allocator
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2

# Install utilities required by XGBoost for Spark.
RUN apt install -y procps libgomp1

# Install and configure Miniconda3.
ENV CONDA_HOME=/opt/miniforge3
ENV PYSPARK_PYTHON=${CONDA_HOME}/bin/python
ENV PATH=${CONDA_HOME}/bin:${PATH}
ADD https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh .
RUN bash Miniforge3-Linux-x86_64.sh -b -p /opt/miniforge3 \
  && ${CONDA_HOME}/bin/conda config --system --set always_yes True \
  && ${CONDA_HOME}/bin/conda config --system --set auto_update_conda False \
  && ${CONDA_HOME}/bin/conda config --system --set channel_priority strict
# Packages ipython and ipykernel are required if using custom conda and want to
# use this container for running notebooks.
RUN ${CONDA_HOME}/bin/mamba install ipython ipykernel

# Install Conda packages.
#
# The following packages are installed in the default image.
# Recommendation: include all packages.
#
# Use mamba to quickly install packages.
RUN ${CONDA_HOME}/bin/mamba install -n base \
    accelerate \
    bigframes \
    cython \
    deepspeed \
    evaluate \
    fastavro \
    fastparquet \
    gcsfs \
    google-cloud-aiplatform \
    google-cloud-bigquery-storage \
    google-cloud-bigquery[pandas] \
    google-cloud-bigtable \
    google-cloud-container \
    google-cloud-datacatalog \
    google-cloud-dataproc \
    google-cloud-datastore \
    google-cloud-language \
    google-cloud-logging \
    google-cloud-monitoring \
    google-cloud-pubsub \
    google-cloud-redis \
    google-cloud-spanner \
    google-cloud-speech \
    google-cloud-storage \
    google-cloud-texttospeech \
    google-cloud-translate \
    google-cloud-vision \
    langchain \
    lightgbm \
    koalas \
    matplotlib \
    mlflow \
    nltk \
    numba \
    numpy \
    openblas \
    orc \
    pandas \
    pyarrow \
    pynvml \
    pysal \
    pytables \
    python \
    pytorch-cpu \
    regex \
    requests \
    rtree \
    scikit-image \
    scikit-learn \
    scipy \
    seaborn \
    sentence-transformers \
    sqlalchemy \
    sympy \
    tokenizers \
    transformers \
    virtualenv \
    xgboost

# Install pip packages.
RUN ${PYSPARK_PYTHON} -m pip install \
    spark-tensorflow-distributor \
    torcheval

# Install R and R libraries.
RUN ${CONDA_HOME}/bin/mamba install -n base \ 
    r-askpass \
    r-assertthat \
    r-backports \
    r-bit \
    r-bit64 \
    r-blob \
    r-boot \
    r-brew \
    r-broom \
    r-callr \
    r-caret \
    r-cellranger \
    r-chron \
    r-class \
    r-cli \
    r-clipr \
    r-cluster \
    r-codetools \
    r-colorspace \
    r-commonmark \
    r-cpp11 \
    r-crayon \
    r-curl \
    r-data.table \
    r-dbi \
    r-dbplyr \
    r-desc \
    r-devtools \
    r-digest \
    r-dplyr \
    r-ellipsis \
    r-evaluate \
    r-fansi \
    r-fastmap \
    r-forcats \
    r-foreach \
    r-foreign \
    r-fs \
    r-future \
    r-generics \
    r-ggplot2 \
    r-gh \
    r-glmnet \
    r-globals \
    r-glue \
    r-gower \
    r-gtable \
    r-haven \
    r-highr \
    r-hms \
    r-htmltools \
    r-htmlwidgets \
    r-httpuv \
    r-httr \
    r-hwriter \
    r-ini \
    r-ipred \
    r-isoband \
    r-iterators \
    r-jsonlite \
    r-kernsmooth \
    r-knitr \
    r-labeling \
    r-later \
    r-lattice \
    r-lava \
    r-lifecycle \
    r-listenv \
    r-lubridate \
    r-magrittr \
    r-markdown \
    r-mass \
    r-matrix \
    r-memoise \
    r-mgcv \
    r-mime \
    r-modelmetrics \
    r-modelr \
    r-munsell \
    r-nlme \
    r-nnet \
    r-numderiv \
    r-openssl \
    r-pillar \
    r-pkgbuild \
    r-pkgconfig \
    r-pkgload \
    r-plogr \
    r-plyr \
    r-praise \
    r-prettyunits \
    r-processx \
    r-prodlim \
    r-progress \
    r-promises \
    r-proto \
    r-ps \
    r-purrr \
    r-r6 \
    r-randomforest \
    r-rappdirs \
    r-rcmdcheck \
    r-rcolorbrewer \
    r-rcpp \
    r-rcurl \
    r-readr \
    r-readxl \
    r-recipes \
    r-recommended \
    r-rematch \
    r-remotes \
    r-reprex \
    r-reshape2 \
    r-rlang \
    r-rmarkdown \
    r-rodbc \
    r-roxygen2 \
    r-rpart \
    r-rprojroot \
    r-rserve \
    r-rsqlite \
    r-rstudioapi \
    r-rvest \
    r-scales \
    r-selectr \
    r-sessioninfo \
    r-shape \
    r-shiny \
    r-sourcetools \
    r-spatial \
    r-squarem \
    r-stringi \
    r-stringr \
    r-survival \
    r-sys \
    r-teachingdemos \
    r-testthat \
    r-tibble \
    r-tidyr \
    r-tidyselect \
    r-tidyverse \
    r-timedate \
    r-tinytex \
    r-usethis \
    r-utf8 \
    r-uuid \
    r-vctrs \
    r-whisker \
    r-withr \
    r-xfun \
    r-xml2 \
    r-xopen \
    r-xtable \
    r-yaml \
    r-zip

ENV R_HOME=/usr/lib/R

# Add extra Python modules.
ENV PYTHONPATH=/opt/python/packages
RUN mkdir -p "${PYTHONPATH}"

# Add extra jars.
ENV SPARK_EXTRA_JARS_DIR=/opt/spark/jars/
ENV SPARK_EXTRA_CLASSPATH='/opt/spark/jars/*'
RUN mkdir -p "${SPARK_EXTRA_JARS_DIR}"

#Uncomment below and replace EXTRA_JAR_NAME with the jar file name.
#COPY "EXTRA_JAR_NAME" "${SPARK_EXTRA_JARS_DIR}"

# Create the 'spark' group/user.
# The GID and UID must be 1099. Home directory is required.
RUN groupadd -g 1099 spark
RUN useradd -u 1099 -g 1099 -d /home/spark -m spark
USER spark
      

构建命令

在 Dockerfile 目录中运行以下命令,以构建自定义映像并将其推送到 Artifact Registry

# Build and push the image.
gcloud builds submit --region=REGION \
    --tag REGION-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE_NAME:IMAGE_VERSION