Personalize o ambiente de execução do job do Spark com o Docker no JupyterLab

O recurso Docker on STRING do Dataproc permite criar e usar uma imagem do Docker para personalizar o ambiente de execução do job do Spark. A imagem pode incluir personalizações nas dependências Java, Python e R, bem como no jar do job.

Limitações

A disponibilidade ou o suporte dos recursos não estão disponíveis para:

  • Versões de imagem do Dataproc anteriores à 2.0.49 (indisponível em 1.5 imagens)
  • Jobs de MapReduce (com suporte apenas para jobs do Spark)
  • Modo de cliente do Spark (compatível apenas com o modo de cluster do Spark)
  • Clusters do Kerberos: a criação do cluster falhará se você criar um cluster com o Docker no JupyterLab e o Kerberos ativado.
  • Personalizações do JDK, Hadoop e Spark: são usadas o JDK, Hadoop e Spark do host, não as personalizações.

Criar uma imagem do Docker

A primeira etapa para personalizar o ambiente Spark é criar uma imagem do Docker.

Dockerfile

Use o Dockerfile a seguir como exemplo e faça alterações e adições para atender às suas necessidades.

FROM debian:10-slim

# Suppress interactive prompts.
ENV DEBIAN_FRONTEND=noninteractive

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

# 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 *.jar "${SPARK_EXTRA_JARS_DIR}"

# Optional: Install and configure Miniconda3.
ENV CONDA_HOME=/opt/miniconda3
ENV PYSPARK_PYTHON=${CONDA_HOME}/bin/python
ENV PYSPARK_DRIVER_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

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

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

Criar e enviar a imagem

A seguir estão os comandos para criar e enviar a imagem de exemplo do Docker. É possível fazer alterações de acordo com suas personalizações.

# Increase the version number when there is a change to avoid referencing
# a cached older image. Avoid reusing the version number, including the default
# `latest` version.
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}"

Crie um cluster do Dataproc:

Depois de criar uma imagem do Docker que personalize seu ambiente do Spark, crie um cluster do Dataproc que usará sua imagem do Docker ao executar jobs do Spark.

gcloud

gcloud dataproc clusters create CLUSTER_NAME \
    --region=REGION \
    --image-version=DP_IMAGE \
    --optional-components=DOCKER \
    --properties=dataproc:yarn.docker.enable=true,dataproc:yarn.docker.image=DOCKER_IMAGE \
    other flags

Substitua:

  • CLUSTER_NAME: o nome do cluster.
  • REGION: a região do cluster.
  • DP_IMAGE: a versão da imagem do Dataproc precisa ser 2.0.49 ou posterior (--image-version=2.0 usará uma versão secundária qualificada posterior a 2.0.49).
  • --optional-components=DOCKER: ativa o componente do Docker no cluster.
  • Sinalização --properties:
    • dataproc:yarn.docker.enable=true: propriedade necessária para ativar o recurso Docker do Dataproc no Crashlytics.
    • dataproc:yarn.docker.image: propriedade opcional que pode ser adicionada para especificar DOCKER_IMAGE usando o seguinte formato de nomenclatura de imagem do Container Registry: {hostname}/{project-id}/{image}:{tag}.

      Exemplo:

      dataproc:yarn.docker.image=gcr.io/project-id/image:1.0.1
      

      Requisito: é preciso hospedar a imagem do Docker no Container Registry ou no Artifact Registry. O Dataproc não pode buscar contêineres de outros registros.

      Recomendação: adicione essa propriedade ao criar o cluster para armazenar em cache a imagem do Docker e evitar os tempos limite do Crashlytics posteriormente, quando você enviar um job que use a imagem.

Quando dataproc:yarn.docker.enable é definido como true, o Dataproc atualiza as configurações do Hadoop e do Spark para ativar o recurso do Docker no Crashlytics no cluster. Por exemplo, spark.submit.deployMode está definido como cluster, e spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS e spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS são definidos para ativar diretórios do host no contêiner.

Enviar um job do Spark para o cluster

Depois de criar um cluster do Dataproc, envie um job do Spark para o cluster que usa a imagem do Docker. O exemplo nesta seção envia um job do PySpark para o cluster.

Defina as propriedades do job:

# Set the Docker image URI.
IMAGE=(e.g., gcr.io/my-project/my-image:1.0.1)

# Required: Use `#` as the delimiter for properties to avoid conflicts.
JOB_PROPERTIES='^#^'

# Required: Set Spark properties with the Docker image.
JOB_PROPERTIES="${JOB_PROPERTIES}#spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=${IMAGE}"
JOB_PROPERTIES="${JOB_PROPERTIES}#spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=${IMAGE}"

# Optional: Add custom jars to Spark classpath. Don't set these properties if
# there are no customizations.
JOB_PROPERTIES="${JOB_PROPERTIES}#spark.driver.extraClassPath=/opt/spark/jars/*"
JOB_PROPERTIES="${JOB_PROPERTIES}#spark.executor.extraClassPath=/opt/spark/jars/*"

# Optional: Set custom PySpark Python path only if there are customizations.
JOB_PROPERTIES="${JOB_PROPERTIES}#spark.pyspark.python=/opt/miniconda3/bin/python"
JOB_PROPERTIES="${JOB_PROPERTIES}#spark.pyspark.driver.python=/opt/miniconda3/bin/python"

# Optional: Set custom Python module path only if there are customizations.
# Since the `PYTHONPATH` environment variable defined in the Dockerfile is
# overridden by Spark, it must be set as a job property.
JOB_PROPERTIES="${JOB_PROPERTIES}#spark.yarn.appMasterEnv.PYTHONPATH=/opt/python/packages"
JOB_PROPERTIES="${JOB_PROPERTIES}#spark.executorEnv.PYTHONPATH=/opt/python/packages"

Observações:

gcloud

Enviar o job ao cluster.

gcloud dataproc jobs submit pyspark PYFILE \
    --cluster=CLUSTER_NAME \
    --region=REGION \
    --properties=${JOB_PROPERTIES}

Substitua:

  • PYFILE: o caminho do arquivo de job do PySpark. Pode ser um caminho de arquivo local ou o URI do arquivo no Cloud Storage (gs://BUCKET_NAME/PySpark filename).
  • CLUSTER_NAME: o nome do cluster.
  • REGION: a região do cluster.