搭配 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 批次工作負載時,請使用 gcloud dataproc batches submit spark 指令搭配 --container-image 旗標,指定自訂容器映像檔。

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

注意事項:

  • Custom-image:使用下列 Container Registry 映像檔命名格式指定自訂容器映像檔:{hostname}/{project-id}/{image}:{tag},例如「gcr.io/my-project-id/my-image:1.0.1」。注意:您必須將自訂容器映像檔託管在 Container RegistryArtifact Registry 中。(Dataproc 無伺服器無法從其他登錄檔擷取容器)。
  • --jars指定自訂容器映像檔中所包含或位於 Cloud Storage 中的使用者工作負載路徑,例如 file:///opt/spark/jars/spark-examples.jargs://my-bucket/spark/jars/spark-examples.jar
  • 其他批次指令選項:您可以新增其他選用的批次指令標記,例如使用永久記錄伺服器 (PHS)。注意:PHS 必須位於執行批次工作負載的區域。
  • 工作負載引數您可以新增任何工作負載引數,方法是將「--」加在指令結尾,接著加上工作負載引數。

REST

自訂容器映像檔會透過 RuntimeConfig.containerImage 欄位提供,做為 batches.create API 要求的一部分。

以下範例說明如何使用自訂容器,透過 Dataproc Serverless for Spark batches.create API 提交批次工作負載。

使用任何要求資料之前,請先替換以下項目:

  • project-id:Google Cloud 專案 ID
  • regionregion
  • 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 無伺服器無法從其他登錄檔擷取容器)。
  • jar-uri指定自訂容器映像檔中所附載的工作負載 JAR 檔案路徑,或位於 Cloud Storage 中的路徑,例如「/opt/spark/jars/spark-examples.jar」或「gs:///spark/jars/spark-examples.jar」。
  • classjar 檔案中類別的完整名稱,例如「org.apache.spark.examples.SparkPi」。
  • 其他選項:您可以使用其他批次工作負載資源欄位,例如使用 sparkBatch.args 欄位將引數傳遞至工作負載 (詳情請參閱 Batch 資源說明文件)。如要使用永久記錄伺服器 (PHS),請參閱「設定永久記錄伺服器」。注意: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 映像檔的工具建構自訂容器映像檔,但這些映像檔必須符合特定條件,才能與 Spark 的 Dataproc 無伺服器相容。以下各節將說明這些條件。

作業系統

您可以為自訂容器映像檔選擇任何作業系統基本映像檔。

建議:請使用預設的 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 無伺服器 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 Runtime Environment

請勿在自訂容器映像檔中加入您自己的 Java Runtime Environment (JRE)。在執行期間,Dataproc Serverless for Spark 會將 OpenJDK 從主機掛載到容器中。如果您在自訂容器映像檔中加入 JRE,系統會忽略該 JRE。

Java 套件

您可以在自訂容器映像檔中,將 JAR 檔案納入 Spark 工作負載依附元件,並設定 SPARK_EXTRA_CLASSPATH 環境變數,以便納入 JAR 檔案。Dataproc Serverless for Spark 會在 Spark JVM 程序的 classpath 中新增 env 變數值。建議:將 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 Google Cloud SDK.
RUN ${CONDA_HOME}/bin/mamba install -n base google-cloud-sdk

# 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