Dataproc em imagens de contêiner personalizadas do GKE

É possível especificar uma imagem de contêiner personalizada para usar com o Dataproc no GKE . A 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 o spark.kubernetes.container.image property ao criar um cluster virtual do Dataproc no 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 de 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 contêineres personalizados com base em uma das imagens de base do Spark publicadas do Dataproc no GKE.

Usuário do contêiner

O Dataproc no GKE executa contêineres do Spark como o usuário spark do Linux 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, conceda ao usuário spark permissão de leitura para o arquivo.

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 mudanças. Consulte as notas da versão do Dataproc para informações atualizadas.

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

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

    • É possível instalar, remover e atualizar pacotes no ambiente de base padrão ou criar um novo ambiente, mas é altamente recomendável que o ambiente 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 de utilitário, à imagem do contêiner, inclua os diretórios de 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 for alterada, a imagem do contêiner será rejeitada ou não funcionará corretamente.

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

      Se você incorporar o job jar na imagem, o diretório recomendado será /opt/spark/job. Ao enviar o job, você pode fazer referência a ele com um caminho local, por exemplo, file:///opt/spark/job/my-spark-job.jar.

    • Conector do Cloud Storage:o conector do Cloud Storage é 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, então as imagens personalizadas não precisam ser instaladas novamente.

    • Ponto de entrada:o Dataproc no GKE ignora todas as mudanças feitas nas primitivas ENTRYPOINT e CMD na imagem do contêiner.

    • Scripts de inicialização:é possível 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 da 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.

  • Configs: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 todas as propriedades pela API Dataproc no GKE pelos seguintes motivos:

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

Imagens de base do Spark

O Dataproc é compatível com as seguintes imagens de contêiner de Spark de base:

  • 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 abaixo no diretório Dockerfile.

  1. Defina a imagem (exemplo: us-central1-docker.pkg.dev/my-project/spark/spark-test-image:latest) e mude 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.

    gcloud storage 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 exemplo de script de inicialização.

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