搭配使用自訂容器和 Google Cloud Serverless for Apache Spark

Google Cloud Serverless for Apache Spark 會在 Docker 容器中執行工作負載。容器會為工作負載的驅動程式和執行器程序提供執行階段環境。根據預設, Google Cloud 無伺服器 Apache Spark 會使用包含預設 Spark、Java、Python 和 R 封裝的容器映像檔,這些封裝與執行階段發布版本相關聯。透過 Google Cloud 無伺服器 Apache Spark批次 API,您可以使用自訂容器映像檔,而非預設映像檔。一般來說,自訂容器映像檔會新增預設容器映像檔未提供的 Spark 工作負載 Java 或 Python 依附元件。重要事項:請勿在自訂容器映像檔中加入 Spark; Google Cloud Serverless for Apache 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

注意:

  • 自訂映像檔:使用下列 Container Registry 映像檔命名格式指定自訂容器映像檔:{hostname}/{project-id}/{image}:{tag},例如「gcr.io/my-project-id/my-image:1.0.1」。注意:您必須透過 Container RegistryArtifact Registry 託管自訂容器映像檔。(Google Cloud Serverless for Apache Spark 無法從其他登錄檔擷取容器)。
  • --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 欄位提供。

以下範例說明如何使用自訂容器,透過 Google Cloud Serverless for Apache 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 託管自訂容器。(Google Cloud Serverless for Apache Spark 無法從其他登錄檔擷取容器)。
  • jar-uri 指定自訂容器映像檔中包含或位於 Cloud Storage 的工作負載 JAR 路徑,例如「/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"
}

建構自訂容器映像檔

Google Cloud Serverless for Apache Spark 自訂容器映像檔是 Docker 映像檔。您可以使用 Docker 映像檔建構工具建構自訂容器映像檔,但映像檔必須符合特定條件,才能與 Google Cloud 適用於 Apache Spark 的無伺服器服務相容。以下各節將說明這些條件。

作業系統

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

建議:使用預設的 Debian 12 映像檔,例如 debian:12-slim,因為這些映像檔經過測試,可避免相容性問題。

公用程式

自訂容器映像檔必須包含下列公用程式套件,才能執行 Spark:

  • procps
  • tini

如要從 Spark (Java 或 Scala) 執行 XGBoost,必須加入 libgomp1

容器使用者

Google Cloud Serverless for Apache Spark 會以 spark Linux 使用者身分執行容器,並提供 1099 UID 和 1099 GID。在自訂容器映像檔 Dockerfile 中設定的 USER 指令會在執行階段遭到忽略。使用 UID 和 GID 設定檔案系統權限。舉例來說,如果您在圖片中的 /opt/spark/jars/my-lib.jar 新增 JAR 檔案做為工作負載依附元件,就必須授予 spark 使用者該檔案的讀取權限。

映像檔串流

無伺服器 Apache Spark 通常會先將整個映像檔下載到磁碟,再開始執行需要自訂容器映像檔的工作負載。這可能導致初始化時間延遲,尤其是使用大型圖片的客戶。

您可以改用映像檔串流,這種方法會視需要提取映像檔資料。這樣一來,工作負載不必等待整個映像檔下載完畢即可啟動,進而縮短初始化時間。如要啟用圖片串流,必須啟用 Container File System API。您也必須將容器映像檔儲存在 Artifact Registry 中,且 Artifact Registry 存放區必須與 Dataproc 工作負載位於相同區域,或位於與工作負載執行所在區域對應的多區域。如果 Dataproc 不支援該映像檔,或映像檔串流服務無法使用,串流導入作業就會下載整個映像檔。

請注意,圖片串流不支援下列項目:

在這些情況下,Dataproc 會先提取整個映像檔,再啟動工作負載。

Spark

請勿在自訂容器映像檔中加入 Spark。在執行階段, Google Cloud Serverless for Apache Spark 會將主機的 Spark 二進位檔和設定掛接到容器中:二進位檔會掛接到 /usr/lib/spark 目錄,設定則會掛接到 /etc/spark/conf 目錄。這些目錄中的現有檔案會在執行階段遭到 Google Cloud Serverless for Apache Spark 覆寫。

Java Runtime Environment

請勿在自訂容器映像檔中加入自己的 Java Runtime Environment (JRE)。在執行階段, Google Cloud Serverless for Apache Spark 會將主機的 OpenJDK 掛接至容器。如果您在自訂容器映像檔中加入 JRE,系統會忽略該 JRE。

Java 套件

您可以在自訂容器映像檔中加入 JAR 檔案做為 Spark 工作負載依附元件,並設定 SPARK_EXTRA_CLASSPATH 環境變數來加入 JAR。 Google Cloud Serverless for Apache Spark 會在 Spark JVM 程序的類別路徑中加入環境變數值。建議: 將 JAR 放在 /opt/spark/jars 目錄下,並將 SPARK_EXTRA_CLASSPATH 設為 /opt/spark/jars/*

您可以將工作負載 JAR 檔案納入自訂容器映像檔,然後在提交工作負載時,以本機路徑參照該檔案,例如 file:///opt/spark/jars/my-spark-job.jar (請參閱「使用自訂容器映像檔提交 Spark 批次工作負載」一文中的範例)。

Python 套件

根據預設, Google Cloud Serverless for Apache Spark 會在執行階段,將使用 OSS Conda-Forge repo 建構的 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