שימוש בקונטיינרים בהתאמה אישית עם Google Cloud Serverless ל-Apache Spark

‫Google Cloud Serverless for Apache Spark מריץ עומסי עבודה (workloads) בתוך קונטיינרים של Docker. הקונטיינר מספק את סביבת זמן הריצה לתהליכי מנהל ההתקן וההרצה של עומס העבודה. כברירת מחדל,ב- Google Cloud Serverless for Apache Spark נעשה שימוש ב קובץ אימג' של קונטיינר שכוללת את חבילות ברירת המחדל של Spark, ‏ Java, ‏ Python ו-R שמשויכות לגרסת הפצה של זמן ריצה. ‫API של Google Cloud Serverless for Apache Spark batches מאפשר לכם להשתמש באימג' מותאם אישית של קונטיינר במקום באימג' שמוגדר כברירת מחדל. בדרך כלל, קובץ אימג' של קונטיינר מותאם אישית מוסיף תלות ב-Java או ב-Python של עומס עבודה של Spark, שלא מסופקת על ידי קובץ האימג' של הקונטיינר שמוגדר כברירת מחדל. חשוב: אל תכללו את Spark בקובץ אימג' של קונטיינר המותאם אישית שלכם. ‏ Google Cloud Serverless for Apache Spark יטמיע את Spark בקונטיינר בזמן הריצה.

שליחת עומס עבודה של Spark batch באמצעות קובץ אימג' מותאם אישית של קונטיינר

gcloud

משתמשים בפקודה gcloud dataproc batches submit spark עם הדגל --container-image כדי לציין את אימג' הקונטיינר המותאם אישית כששולחים עומס עבודה של Spark batch.

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 Registry או ב-Artifact Registry. (‫Google Cloud Serverless for Apache Spark לא יכול לאחזר קונטיינרים ממאגרי רישום אחרים).
  • --jars: מציינים נתיב לעומס עבודה של משתמש שכלול בקובץ אימג' של קונטיינר מותאם אישית או שנמצא ב-Cloud Storage, לדוגמה, file:///opt/spark/jars/spark-examples.jar או gs://my-bucket/spark/jars/spark-examples.jar.
  • אפשרויות נוספות לפקודת batches: אפשר להוסיף עוד דגלים אופציונליים לפקודת batches, לדוגמה, כדי להשתמש בשרת היסטוריה מתמשך (PHS). הערה: ה-PHS צריך להיות ממוקם באזור שבו מריצים עומסי עבודה של אצווה.
  • ארגומנטים של עומס עבודה: אפשר להוסיף ארגומנטים של עומס עבודה על ידי הוספת '--' בסוף הפקודה, ואחריו הארגומנטים של עומס העבודה.

REST

קובץ האימג' של הקונטיינר בהתאמה אישית מסופק דרך השדה RuntimeConfig.containerImage כחלק מבקשת API של batches.create.

בדוגמה הבאה מוצג איך להשתמש בקונטיינר בהתאמה אישית כדי לשלוח עומס עבודה של אצווה באמצעות ה-API‏ Google Cloud Serverless for Apache Spark batches.create.

לפני שמשתמשים בנתוני הבקשה, צריך להחליף את הנתונים הבאים:

  • project-id: מזהה הפרויקט בענן ב-Google
  • region: region
  • custom-container-image: מציינים את קובץ האימג' של הקונטיינר המותאם אישית באמצעות פורמט השמות הבא של תמונות ב-Container Registry: custom-container-image, לדוגמה, gcr.io/my-project-id/my-image:1.0.1.{hostname}/{project-id}/{image}:{tag} הערה: צריך לארח את הקונטיינר המותאם אישית ב-Container Registry או ב- Artifact Registry . (‫Google Cloud Serverless for Apache Spark לא יכול לאחזר קונטיינרים ממאגרי רישום אחרים).
  • jar-uri: מציינים נתיב לקובץ JAR של עומס עבודה שכלול בקובץ אימג' של קונטיינר מותאם אישית או שנמצא ב-Cloud Storage, לדוגמה, "/opt/spark/jars/spark-examples.jar" או "gs:///spark/jars/spark-examples.jar".
  • class: השם המוגדר במלואו של מחלקה בקובץ ה-JAR, למשל org.apache.spark.examples.SparkPi.
  • אפשרויות אחרות: אפשר להשתמש בשדות אחרים של משאבי עומסי עבודה באצווה, למשל, אפשר להשתמש בשדה sparkBatch.args כדי להעביר ארגומנטים לעומס העבודה (מידע נוסף זמין במסמכי המשאב Batch). כדי להשתמש בשרת היסטוריה מתמיד (PHS), אפשר לעיין במאמר הגדרה של שרת היסטוריה מתמיד. הערה: ה-PHS צריך להיות ממוקם באזור שבו מריצים עומסי עבודה של אצווה.

ה-method של ה-HTTP וכתובת ה-URL:

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 Serverless for Apache Spark. בקטעים הבאים מוסבר על התנאים האלה.

מערכת הפעלה

אתם יכולים לבחור כל תמונת בסיס של מערכת הפעלה בשביל קובץ אימג' הקונטיינר המותאם אישית שלכם.

המלצה: כדאי להשתמש בתמונות ברירת המחדל של Debian 12, לדוגמה, debian:12-slim, כי הן נבדקו כדי למנוע בעיות תאימות.

שירותים

בקובץ האימג' המותאם אישית של הקונטיינר צריך לכלול את חבילות כלי העזר הבאות, שנדרשות להרצת Spark:

  • procps
  • tini

כדי להריץ XGBoost מ-Spark (Java או Scala), צריך לכלול את libgomp1

משתמש במאגר תגים

‫Serverless (בלי שרת) ל-Apache Spark מפעיל קונטיינרים כמשתמש Linux‏ spark עם 1099 UID ו-1099 GID.Google Cloud ההנחיות USER שמוגדרות בקובצי Dockerfile של קובצי אימג' מותאמים אישית של קונטיינרים מושבתות בזמן הריצה. משתמשים ב-UID וב-GID להרשאות של מערכת הקבצים. לדוגמה, אם מוסיפים קובץ jar בנתיב /opt/spark/jars/my-lib.jar בתמונה כתלות של עומס עבודה, צריך לתת למשתמש spark הרשאת קריאה לקובץ.

סטרימינג של תמונות

בדרך כלל, כדי להתחיל עומס עבודה שדורש קובץ אימג' מותאם אישית של קונטיינר, המערכת של Serverless for 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

אל תכללו את סביבת זמן הריצה של Java‏ (JRE) שלכם בתמונת מאגר ה-Docker המותאם אישית. בזמן הריצה,‏ Google Cloud Serverless for Apache Spark מעלה את OpenJDK מהמארח אל הקונטיינר. אם תכללו JRE בקובץ אימג' של קונטיינר מותאם אישית, המערכת תתעלם ממנה.

חבילות Java

אתם יכולים לכלול קובצי JAR כתלות בעומס העבודה של Spark בקובץ אימג' של קונטיינר המותאם אישית, ולהגדיר את משתנה הסביבה SPARK_EXTRA_CLASSPATH כך שיכלול את קובצי ה-JAR.‫Serverless for Apache Spark יוסיף את הערך של משתנה הסביבה ב-classpath של תהליכי Spark JVM. Google Cloud המלצה: כדאי להציב קובצי JAR בספרייה /opt/spark/jars ולהגדיר את SPARK_EXTRA_CLASSPATH ל-/opt/spark/jars/*.

אפשר לכלול את קובץ ה-JAR של עומס העבודה בקובץ אימג' מותאם אישית של קונטיינר, ואז להפנות אליו באמצעות נתיב מקומי כששולחים את עומס העבודה, לדוגמה file:///opt/spark/jars/my-spark-job.jar (ראו דוגמה במאמר שליחת עומס עבודה של Spark Batch באמצעות קובץ אימג' מותאם אישית של קונטיינר).

חבילות Python

כברירת מחדל, Google Cloud Serverless for Apache Spark מבצעת טעינה של גרסת סביבת Conda באמצעות מאגר OSS Conda-Forge מהמארח לספרייה /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 כדי לנהל ולהתקין חבילות R מערוץ conda-forge.
  • מוסיפים מאגר R למערכת ההפעלה Linux של קובץ האימג' של הקונטיינר, ומתקינים חבילות R באמצעות מנהל החבילות של מערכת ההפעלה Linux (ראו אינדקס של חבילות תוכנה של R).

כשמשתמשים באחת מהאפשרויות האלה, צריך להגדיר את משתנה הסביבה R_HOME כך שיצביע על סביבת ה-R המותאמת אישית. יוצא מן הכלל: אם אתם משתמשים ב-Conda כדי לנהל את סביבת R ולהתאים אישית את סביבת Python, אתם לא צריכים להגדיר את משתנה הסביבה R_HOME. הוא מוגדר אוטומטית על סמך משתנה הסביבה PYSPARK_PYTHON.

דוגמה ליצירת קובץ אימג' של קונטיינר בהתאמה אישית

בקטע הזה מופיעות דוגמאות לפיתוח קובצי אימג' של קונטיינרים בהתאמה אישית, כולל Dockerfiles לדוגמה, ואחריהן פקודת build. דוגמה אחת כוללת את ההגדרה המינימלית שנדרשת ליצירת תמונה. הדוגמה השנייה כוללת דוגמאות להגדרות נוספות, כולל ספריות 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 google-perftools

# Enable jemalloc2 as default memory allocator
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
# Use tcmalloc as memory allocator for Spark executors for NQE jobs.
ENV NQE_USE_TCMALLOC=true

# 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 lib libjemalloc2 google-perftools

# Enable jemalloc2 as default memory allocator
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
# Use tcmalloc as memory allocator for Spark executors for NQE jobs.
ENV NQE_USE_TCMALLOC=true

# 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