Imagens de contêiner personalizadas do Dataproc no GKE

É possível especificar uma imagem de contêiner personalizada para usar com o Dataproc no GKE . Sua imagem de contêiner personalizada precisa usar uma das imagens de base do Spark do Dataproc no GKE.

Usar uma imagem de contêiner personalizada

Para usar uma imagem de contêiner personalizada do Dataproc no GKE, defina spark.kubernetes.container.image property ao criar um Dataproc no cluster virtual do GKE ou enviar um job do Spark para o cluster.

  • Exemplo de criação de cluster da CLI gcloud:
    gcloud dataproc clusters gke create "${DP_CLUSTER}" \
        --properties=spark:spark.kubernetes.container.image=custom-image \
        ... other args ...
    
  • Exemplo de envio do job da CLI gcloud:
    gcloud dataproc jobs submit spark \
        --properties=spark.kubernetes.container.image=custom-image \
        ... other args ...
    

Requisitos e configurações de imagens de contêiner personalizadas

Imagens de base

É possível usar ferramentas docker para criar um Docker personalizado com base em uma das imagens base do Spark do Dataproc no GKE.

Usuário do contêiner

O Dataproc no GKE executa contêineres do Spark como usuário do Linux spark com um UID 1099 e um GID 1099. Use o UID e o GID para permissões do sistema de arquivos. Por exemplo, se você adicionar um arquivo jar em /opt/spark/jars/my-lib.jar na imagem como uma dependência de carga de trabalho, será necessário conceder permissão de leitura ao usuário spark.

Componentes

  • Java:a variável de ambiente JAVA_HOME aponta para o local da instalação do Java. O valor padrão atual é /usr/lib/jvm/adoptopenjdk-8-hotspot-amd64, que está sujeito a alterações. Consulte as notas da versão do Dataproc para mais informações.

    • Se você personalizar o ambiente Java, verifique se JAVA_HOME está definido como o local correto e se PATH inclui o caminho para os binários.
  • Python:as imagens básicas do Spark do Dataproc no GKE têm o Miniconda3 instalado em /opt/conda. CONDA_HOME aponta para esse local, ${CONDA_HOME}/bin está incluído em PATH e PYSPARK_PYTHON está definido como ${CONDA_HOME}/python.

    • Se você personalizar o Conda, verifique se CONDA_HOME aponta para o diretório inicial do Conda, se ${CONDA_HOME}/bin está incluído em PATH e se PYSPARK_PYTHON está definido como ${CONDA_HOME}/python.

    • É possível instalar, remover e atualizar pacotes no ambiente base padrão ou criar um novo ambiente, mas é altamente recomendável que ele inclua todos os pacotes instalados no ambiente de base da imagem do contêiner de base.

    • Se você adicionar módulos Python, como um script Python com funções utilitárias, à imagem do contêiner, inclua os diretórios do módulo em PYTHONPATH.

  • Spark:o Spark está instalado em /usr/lib/spark, e SPARK_HOME aponta para esse local. O Spark não pode ser personalizado. Se ele for alterado, a imagem do contêiner será rejeitada ou não funcionará corretamente.

    • Jobs: você pode personalizar as dependências dos jobs do Spark. SPARK_EXTRA_CLASSPATH define o caminho de classe extra para os processos da JVM do Spark. Recomendação: coloque os jars em /opt/spark/jars e defina SPARK_EXTRA_CLASSPATH como /opt/spark/jars/*.

      Se você incorporar o jar do job na imagem, o diretório recomendado será /opt/spark/job. Ao enviar o job, é possível referenciá-lo com um caminho local, por exemplo, file:///opt/spark/job/my-spark-job.jar.

    • Conector do Cloud Storage:o conector do Cloud Storage está instalado em /usr/lib/spark/jars.

    • Utilitários: os pacotes de utilitários procps e tini são necessários para executar o Spark. Esses utilitários estão incluídos nas imagens de base do Spark. Portanto, não é necessário reinstalar as imagens personalizadas.

    • Ponto de entrada: o Dataproc no GKE ignora todas as alterações feitas nos primitivos ENTRYPOINT e CMD na imagem do contêiner.

    • Scripts de inicialização: você pode adicionar um script de inicialização opcional em /opt/init-script.sh. Um script de inicialização pode fazer o download de arquivos do Cloud Storage, iniciar um proxy no contêiner, chamar outros scripts e executar outras tarefas de inicialização.

      O script de ponto de entrada chama o script de inicialização com todos os argumentos de linha de comando ($@) antes de iniciar o driver do Spark, o executor do Spark e outros processos. O script de inicialização pode selecionar o tipo de processo do Spark com base no primeiro argumento ($1): os valores possíveis incluem spark-submit para contêineres de driver e executor para contêineres de executor.

  • Configurações:as configurações do Spark estão localizadas em /etc/spark/conf. A variável de ambiente SPARK_CONF_DIR aponta para esse local.

    Não personalize as configurações do Spark na imagem do contêiner. Em vez disso, envie as propriedades por meio do Dataproc na API GKE pelos seguintes motivos:

    • Algumas propriedades, como o tamanho da memória do executor, são determinadas no ambiente de execução, não no tempo de compilação da imagem do contêiner. Elas precisam ser injetadas pelo Dataproc no GKE.
    • O Dataproc no GKE restringe as propriedades fornecidas pelos usuários. O Dataproc no GKE monta configurações de configMap em /etc/spark/conf no contêiner, modificando as configurações incorporadas na imagem.

Imagens de base do Spark

O Dataproc aceita as seguintes imagens de contêiner base do 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

Exemplo de build de imagem de contêiner personalizada

Exemplo de Dockerfile

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

Crie a imagem do contêiner

Execute os comandos a seguir no diretório do Dockerfile

  1. Definir imagem (exemplo: us-central1-docker.pkg.dev/my-project/spark/spark-test-image:latest) e mudar para o diretório de build.
    IMAGE=custom container image \
        BUILD_DIR=$(mktemp -d) \
        cd "${BUILD_DIR}"
    
  2. Faça o download do conector do BigQuery.

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

  3. Crie um arquivo de exemplo em 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. Crie um script init de exemplo.

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

  5. Crie e envie a imagem.

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