Imágenes de contenedor personalizadas de Dataproc on GKE

Puedes especificar una imagen de contenedor personalizada para usar con Dataproc en GKE . Tu imagen de contenedor personalizada debe usar una de las imágenes base de Spark de Dataproc on GKE.

Usa una imagen de contenedor personalizada

Para usar una imagen de contenedor personalizada de Dataproc on GKE, configura spark.kubernetes.container.image property cuando crees un clúster virtual de Dataproc on GKE o envíes un trabajo de Spark al clúster.

  • Ejemplo de creación de un clúster de gcloud CLI:
    gcloud dataproc clusters gke create "${DP_CLUSTER}" \
        --properties=spark:spark.kubernetes.container.image=custom-image \
        ... other args ...
    
  • Ejemplo de envío de trabajos de gcloud CLI:
    gcloud dataproc jobs submit spark \
        --properties=spark.kubernetes.container.image=custom-image \
        ... other args ...
    

Requisitos y configuración de las imágenes de contenedor personalizadas

Imágenes base

Puedes usar las herramientas de docker para compilar un Docker personalizado basado en una de las imágenes base de Spark publicadas de Dataproc on GKE.

Usuario de contenedor

Dataproc en GKE ejecuta contenedores de Spark como el usuario spark de Linux con un UID 1099 y un GID 1099. Usa el UID y GID para los permisos del sistema de archivos. Por ejemplo, si agregas un archivo jar en /opt/spark/jars/my-lib.jar en la imagen como una dependencia de carga de trabajo, debes otorgar permiso de lectura del usuario spark en el archivo.

Componentes

  • Java: La variable de entorno JAVA_HOME apunta a la ubicación de la instalación de Java. El valor predeterminado actual es /usr/lib/jvm/adoptopenjdk-8-hotspot-amd64, que está sujeto a cambios (consulta las notas de la versión de Dataproc para obtener información actualizada).

    • Si personalizas el entorno de Java, asegúrate de que JAVA_HOME esté configurado en la ubicación correcta y que PATH incluya la ruta de acceso a los objetos binarios.
  • Python: Las imágenes base de Spark de Dataproc on GKE tienen Miniconda3 instalado en /opt/conda. CONDA_HOME apunta a esta ubicación, ${CONDA_HOME}/bin se incluye en PATH y PYSPARK_PYTHON se establece en ${CONDA_HOME}/python.

    • Si personalizas Conda, asegúrate de que CONDA_HOME apunte al directorio principal de Conda, ${CONDA_HOME}/bin se incluya en PATH y PYSPARK_PYTHON esté configurado como ${CONDA_HOME}/python..

    • Puedes instalar, quitar y actualizar paquetes en el entorno base predeterminado o crear un entorno nuevo, pero se recomienda que el entorno incluya todos los paquetes instalados en el entorno base de la imagen de contenedor base.

    • Si agregas módulos de Python, como una secuencia de comandos de Python con funciones de utilidad, a la imagen de contenedor, incluye los directorios de módulos en PYTHONPATH.

  • Spark: Spark está instalado en /usr/lib/spark y SPARK_HOME apunta a esta ubicación. Spark no se puede personalizar. Si se cambia, se rechazará la imagen de contenedor o no funcionará correctamente.

    • Trabajos: Puedes personalizar las dependencias de trabajos de Spark. SPARK_EXTRA_CLASSPATH define la ruta de clase adicional para los procesos de Spark JVM. Recomendación: Coloca los archivos jar en /opt/spark/jars y establece SPARK_EXTRA_CLASSPATH en /opt/spark/jars/*.

      Si incorporas el archivo jar del trabajo en la imagen, el directorio recomendado es /opt/spark/job. Cuando envías el trabajo, puedes hacer referencia a él con una ruta local, por ejemplo, file:///opt/spark/job/my-spark-job.jar.

    • Conector de Cloud Storage: El conector de Cloud Storage se instala en /usr/lib/spark/jars.

    • Utilidades: Se requieren los paquetes de utilidades procps y tini para ejecutar Spark. Estas utilidades se incluyen en las imágenes base de Spark, por lo que las imágenes personalizadas no necesitan volver a instalarlas.

    • Punto de entrada: Dataproc on GKE ignora los cambios realizados en las primitivas ENTRYPOINT y CMD en la imagen del contenedor.

    • Secuencias de comandos de inicialización: Puedes agregar una secuencia de comandos de inicialización opcional en /opt/init-script.sh. Una secuencia de comandos de inicialización puede descargar archivos de Cloud Storage, iniciar un proxy dentro del contenedor, llamar a otras secuencias de comandos y realizar otras tareas de inicio.

      La secuencia de comandos de punto de entrada llama a la secuencia de comandos de inicialización con todos los argumentos de línea de comandos ($@) antes de iniciar el controlador de Spark, el ejecutor de Spark y otros procesos. La secuencia de comandos de inicialización puede seleccionar el tipo de proceso de Spark según el primer argumento ($1). Los valores posibles incluyen spark-submit para los contenedores del controlador y executor para los contenedores del ejecutor.

  • Parámetros de configuración: Los archivos de configuración de Spark se encuentran en /etc/spark/conf. La variable de entorno SPARK_CONF_DIR apunta a esta ubicación.

    No personalices los parámetros de configuración de Spark en la imagen de contenedor. En su lugar, envía cualquier propiedad a través de la API de Dataproc on GKE por los siguientes motivos:

    • Algunas propiedades, como el tamaño de la memoria del ejecutor, se determinan en el entorno de ejecución y no en el tiempo de compilación de la imagen del contenedor; Dataproc en GKE las debe insertar .
    • Dataproc en GKE impone restricciones en las propiedades que proporcionan los usuarios. Dataproc en GKE activa los archivos de configuración de configMap en /etc/spark/conf en el contenedor, lo que anula la configuración incorporada en la imagen.

Imágenes de Spark base

Dataproc admite las siguientes imágenes base de contenedor de Spark:

  • Spark 2.4: ${REGION}-docker.pkg.dev/cloud-dataproc/spark/dataproc_1.5
  • Spark 3.1: ${REGION}-docker.pkg.dev/cloud-dataproc/spark/dataproc_2.0

Compilación de la imagen de contenedor personalizada de muestra

Dockerfile de muestra

FROM us-central1-docker.pkg.dev/cloud-dataproc/spark/dataproc_2.0:latest

# Change to root temporarily so that it has permissions to create dirs and copy
# files.
USER root

# Add a BigQuery connector jar.
ENV SPARK_EXTRA_JARS_DIR=/opt/spark/jars/
ENV SPARK_EXTRA_CLASSPATH='/opt/spark/jars/*'
RUN mkdir -p "${SPARK_EXTRA_JARS_DIR}" \
    && chown spark:spark "${SPARK_EXTRA_JARS_DIR}"
COPY --chown=spark:spark \
    spark-bigquery-with-dependencies_2.12-0.22.2.jar "${SPARK_EXTRA_JARS_DIR}"

# Install Cloud Storage client Conda package.
RUN "${CONDA_HOME}/bin/conda" install google-cloud-storage

# Add a custom Python file.
ENV PYTHONPATH=/opt/python/packages
RUN mkdir -p "${PYTHONPATH}"
COPY test_util.py "${PYTHONPATH}"

# Add an init script.
COPY --chown=spark:spark init-script.sh /opt/init-script.sh

# (Optional) Set user back to `spark`.
USER spark

Compila la imagen del contenedor

Ejecuta los siguientes comandos en el directorio de Dockerfile.

  1. Establece la imagen (por ejemplo: us-central1-docker.pkg.dev/my-project/spark/spark-test-image:latest) y cámbiala al directorio de compilación.
    IMAGE=custom container image \
        BUILD_DIR=$(mktemp -d) \
        cd "${BUILD_DIR}"
    
  2. Descarga el conector de BigQuery.

    gsutil cp \
        gs://spark-lib/bigquery/spark-bigquery-with-dependencies_2.12-0.22.2.jar .
    

  3. Crea un archivo de ejemplo de Python.

    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

  4. Crea una secuencia de comandos init de ejemplo.

    cat >init-script.sh <<EOF
    echo "hello world" >/tmp/init-script.out
    EOF
    

  5. Compila y envía la imagen.

    docker build -t "${IMAGE}" . && docker push "${IMAGE}"