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 básicas 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 a 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 imagem de contêiner personalizada

Imagens de base

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

Usuário do contêiner

O Dataproc no GKE executa contêineres do Spark como o usuário spark do Linux com um 1099 UID e um 1099 GID. 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 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 alterações. Consulte as notas de lançamento do Dataproc para informações atualizadas.

    • Se você personalizar o ambiente Java, verifique se JAVA_HOME está definido para 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 este 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,${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 básico padrão, ou criar um novo ambiente, mas é altamente recomendável que o ambiente inclua todos os pacotes instalados no ambiente básico da imagem de contêiner.

    • 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 ele for alterado, 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 classpath extra para processos da JVM do Spark. Recomendação: coloque arquivos JAR 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 Spark. Esses utilitários estão incluídos nas imagens básicas do Spark, então as imagens personalizadas não precisam reinstalá-los.

    • Ponto de entrada: o Dataproc no GKE ignora todas as alterações 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 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 todas as propriedades pela API Dataproc no GKE por estes 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 configurações de configMap em /etc/spark/conf no contêiner, substituindo as configurações incorporadas na imagem.

Imagens básicas do Spark

O Dataproc oferece suporte às seguintes imagens básicas de contêiner do Spark:

  • Spark 3.5: ${REGION}-docker.pkg.dev/cloud-dataproc/spark/dataproc_2.2

Exemplo de criação de imagem de contêiner personalizada

Dockerfile de amostra

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. Defina a imagem (exemplo: us-central1-docker.pkg.dev/my-project/spark/spark-test-image:latest) e mude para o diretório de criação.
    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 do 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 de inicialização 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}"