Spark를 위한 서버리스 Dataproc로 커스텀 컨테이너 사용

Spark를 위한 서버리스 Dataproc은 Docker 컨테이너 내에서 워크로드를 실행합니다. 컨테이너는 워크로드의 드라이버와 실행자 프로세스를 위한 런타임 환경을 제공합니다. 기본적으로 Spark를 위한 서버리스 Dataproc은 런타임 출시 버전과 연결된 기본 Spark, 자바, Python, R 패키지가 포함된 컨테이너 이미지를 사용합니다. Spark를 위한 서버리스 Dataproc batches API를 사용하면 기본 이미지 대신 커스텀 컨테이너 이미지를 사용할 수 있습니다. 일반적으로 커스텀 컨테이너 이미지는 기본 컨테이너 이미지에서 제공하지 않는 Spark 워크로드 자바 또는 Python 종속 항목을 추가합니다. 중요: 커스텀 컨테이너 이미지에 Spark를 포함하지 마세요. Spark를 위한 서버리스 Dataproc은 런타임 시 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: {hostname}/{project-id}/{image}:{tag} Container Registry 이미지 이름 지정 형식을 사용하여 커스텀 컨테이너 이미지를 지정합니다(예: 'gcr.io/my-project-id/my-image:1.0.1'). 참고: Container Registry 또는 Artifact Registry에서 커스텀 컨테이너 이미지를 호스팅해야 합니다. 서버리스 Dataproc는 다른 레지스트리에서 컨테이너를 가져올 수 없습니다.
  • --jars: 커스텀 컨테이너 이미지에 포함되어 있거나 Cloud Storage에 있는 사용자 워크로드의 경로를 지정합니다(예: /opt/spark/jars/spark-examples.jar 또는 gs://my-bucket/spark/jars/spark-examples.jar).
  • 기타 배치 명령어 옵션: 예를 들어 영구 기록 서버(PHS)를 사용하는 등 다른 선택적 배치 명령어 플래그를 추가할 수 있습니다. 참고: PHS는 일괄 워크로드를 실행하는 리전에 있어야 합니다.
  • 워크로드 인수 명령어 끝에 '--'를 추가하고 워크로드 인수를 추가하여 모든 워크로드 인수를 추가할 수 있습니다.

REST

커스텀 컨테이너 이미지는 batches.create API 요청의 일부로 RuntimeConfig.containerImage 필드를 통해 제공됩니다.

다음 예시에서는 커스텀 컨테이너로 Spark를 위한 서버리스 Dataproc 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'). 참고: Container Registry 또는 Artifact Registry에서 커스텀 컨테이너를 호스팅해야 합니다. 서버리스 Dataproc는 다른 레지스트리에서 컨테이너를 가져올 수 없습니다.
  • 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 리소스 문서 참조). 영구 기록 서버(PHS)를 사용하려면 영구 기록 서버 설정을 참조하세요. 참고: PHS는 일괄 워크로드를 실행하는 리전에 있어야 합니다.

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"
}

커스텀 컨테이너 이미지 빌드

Spark를 위한 서버리스 Dataproc 커스텀 컨테이너 이미지는 Docker 이미지입니다. Docker 이미지 빌드 도구를 사용하여 커스텀 컨테이너 이미지를 빌드할 수 있지만 이미지가 Spark를 위한 서버리스 Dataproc과 호환되어야 합니다. 다음 섹션에서는 이러한 조건을 설명합니다.

운영체제

모든 운영체제 이미지를 커스텀 컨테이너 이미지의 기본 이미지로 선택할 수 있습니다. 권장사항: 호환성 문제를 방지하기 위해 테스트를 수신했으므로 기본 Debian 11 이미지가 권장됩니다(예: debian:11-slim).

유틸리티

Spark를 실행하는 데 필요한 다음 유틸리티 패키지를 커스텀 컨테이너 이미지에 포함해야 합니다.

  • procps
  • tini

Spark(자바 또는 Scala)에서 XGBoost를 실행하려면 libgomp1을 포함해야 합니다.

컨테이너 사용자

Spark를 위한 서버리스 Dataproc은 1099 UID 및 1099 GID를 사용하여 컨테이너를 spark Linux 사용자로 실행합니다. 커스텀 컨테이너 이미지 Dockerfile에 설정된 USER 지시문은 런타임 시 무시됩니다. 파일 시스템 권한에 UID 및 GID를 사용합니다. 예를 들어 /opt/spark/jars/my-lib.jar의 jar 파일을 워크로드 종속 항목으로 이미지에 추가하면 spark 사용자에게 파일에 대한 읽기 권한을 부여해야 합니다.

이미지 스트리밍

Spark를 위한 서버리스 Dataproc는 일반적으로 전체 이미지를 디스크에 다운로드하여 커스텀 컨테이너 이미지가 필요한 워크로드를 시작합니다. 따라서 특히 이미지가 큰 고객의 경우 초기화 시간이 지연될 수 있습니다.

대신 필요에 따라 이미지 데이터를 가져오는 방법인 이미지 스트리밍을 사용할 수 있습니다. 이 방법을 사용하면 전체 이미지를 다운로드할 때까지 기다릴 필요 없이 워크로드가 시작되어 초기화 시간이 개선될 수 있습니다. 이미지 스트리밍을 사용 설정하려면 Container Filesystem API를 사용 설정해야 합니다. 또한 컨테이너 이미지를 Artifact Registry에 저장해야 하고 Artifact Registry 저장소가 Dataproc 워크로드와 동일한 리전 또는 해당 워크로드가 실행되는 리전에 해당하는 멀티 리전에 있어야 합니다. Dataproc가 이미지를 지원하지 않거나 이미지 스트리밍 서비스를 사용할 수 없으면 스트리밍 구현으로 전체 이미지를 다운로드합니다. 이미지 스트리밍에는 다음이 지원되지 않습니다.

이 경우 Dataproc가 워크로드를 시작하기 전 전체 이미지를 가져옵니다.

Spark

커스텀 컨테이너 이미지에 Spark를 포함하지 마세요. 런타임 시 Spark를 위한 서버리스 Dataproc은 호스트의 Spark 바이너리와 구성을 컨테이너에 마운트합니다. 바이너리는 /usr/lib/spark 디렉터리에 마운트되고 구성은 /etc/spark/conf 디렉터리에 마운트됩니다. 이러한 디렉터리의 기존 파일은 런타임 시 Spark를 위한 서버리스 Dataproc에서 재정의됩니다.

자바 런타임 환경

커스텀 컨테이너 이미지에 자체 자바 런타임 환경(JRE)을 포함하지 마세요. 런타임 시 Spark를 위한 서버리스 Dataproc은 호스트의 OpenJDK을 컨테이너에 마운트합니다. 커스텀 컨테이너 이미지에 JRE를 포함하면 무시됩니다.

자바 패키지

jar 파일을 Spark 워크로드 종속 항목으로 커스텀 컨테이너 이미지에 포함할 수 있으며 jar가 포함되도록 SPARK_EXTRA_CLASSPATH 환경 변수를 설정할 수 있습니다. Spark를 위한 서버리스 Dataproc은 Spark JVM 프로세스의 클래스 경로에 환경 변수 값을 추가합니다. 권장사항: jar를 /opt/spark/jars 디렉터리에 배치하고 SPARK_EXTRA_CLASSPATH/opt/spark/jars/*로 설정합니다.

커스텀 컨테이너 이미지에 워크로드 jar을 포함한 다음 워크로드를 제출할 때 로컬 경로로 참조할 수 있습니다(예: file:///opt/spark/jars/my-spark-job.jar). 커스텀 컨테이너 이미지를 사용하여 Spark 배치 워크로드 제출 예시를 참조하세요.

Python 패키지

기본적으로 Spark를 위한 Dataproc 서버리스는 호스트의 Conda를 런타임에 컨테이너의 /opt/dataproc/conda 디렉터리에 마운트합니다. PYSPARK_PYTHON/opt/dataproc/conda/bin/python으로 설정되어 있습니다. 기본 디렉터리인 /opt/dataproc/conda/binPATH에 포함됩니다.

커스텀 컨테이너 이미지의 다른 디렉터리(예: /opt/conda)에 패키지가 있는 Python 환경을 포함하고 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 환경 변수에 따라 자동으로 설정됩니다.

커스텀 컨테이너 이미지 빌드 예시

Dockerfile

# Debian 11 is recommended.
FROM debian:11-slim

# Suppress interactive prompts
ENV DEBIAN_FRONTEND=noninteractive

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

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

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

# (Optional) 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}"
COPY spark-bigquery-with-dependencies_2.12-0.22.2.jar "${SPARK_EXTRA_JARS_DIR}"

# (Optional) Install and configure Miniconda3.
ENV CONDA_HOME=/opt/miniconda3
ENV PYSPARK_PYTHON=${CONDA_HOME}/bin/python
ENV PATH=${CONDA_HOME}/bin:${PATH}
COPY Miniconda3-py39_4.10.3-Linux-x86_64.sh .
RUN bash Miniconda3-py39_4.10.3-Linux-x86_64.sh -b -p /opt/miniconda3 \
  && ${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 --prepend channels conda-forge \
  && ${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/conda install ipython ipykernel

# (Optional) Install Conda packages.
#
# The following packages are installed in the default image, it is strongly
# recommended to include all of them.
#
# Use mamba to install packages quickly.
RUN ${CONDA_HOME}/bin/conda install mamba -n base -c conda-forge \
    && ${CONDA_HOME}/bin/mamba install \
      conda \
      cython \
      fastavro \
      fastparquet \
      gcsfs \
      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 \
      koalas \
      matplotlib \
      nltk \
      numba \
      numpy \
      openblas \
      orc \
      pandas \
      pyarrow \
      pysal \
      pytables \
      python \
      regex \
      requests \
      rtree \
      scikit-image \
      scikit-learn \
      scipy \
      seaborn \
      sqlalchemy \
      sympy \
      virtualenv

# (Optional) Add extra Python modules.
ENV PYTHONPATH=/opt/python/packages
RUN mkdir -p "${PYTHONPATH}"
COPY test_util.py "${PYTHONPATH}"

# (Optional) Install R and R libraries.
RUN apt update \
  && apt install -y gnupg \
  && apt-key adv --no-tty \
      --keyserver "hkp://keyserver.ubuntu.com:80" \
      --recv-keys E19F5F87128899B192B1A2C2AD5F960A256A04AF \
  && echo "deb http://cloud.r-project.org/bin/linux/debian bullseye-cran40/" \
      >/etc/apt/sources.list.d/cran-r.list \
  && apt update \
  && apt install -y \
      libopenblas-base \
      libssl-dev \
      r-base \
      r-base-dev \
      r-recommended \
      r-cran-blob

ENV R_HOME=/usr/lib/R

# (Required) 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 디렉터리에서 실행합니다.

IMAGE=gcr.io/my-project/my-image:1.0.1

# Download the BigQuery connector.
gsutil cp \
  gs://spark-lib/bigquery/spark-bigquery-with-dependencies_2.12-0.22.2.jar .

# Download the Miniconda3 installer.
wget https://repo.anaconda.com/miniconda/Miniconda3-py39_4.10.3-Linux-x86_64.sh

# Python module example
cat >test_util.py <<EOF
def hello(name):
  print("hello {}".format(name))

def read_lines(path):
  with open(path) as f:
    return f.readlines()
EOF

# Build and push the image.
docker build -t "${IMAGE}" .
docker push "${IMAGE}"