Crie imagens de contentores personalizadas para o Dataflow

Este documento descreve como criar uma imagem de contentor personalizada para tarefas do Dataflow.

Requisitos

Uma imagem de contentor personalizada para o Dataflow tem de cumprir os seguintes requisitos:

  • O SDK Apache Beam e as dependências necessárias estão instalados. Recomendamos que comece com uma imagem do SDK do Apache Beam predefinida. Para mais informações, consulte a secção Selecione uma imagem base neste documento.
  • O script /opt/apache/beam/boot tem de ser executado como o último passo durante o arranque do contentor. Este script inicializa o ambiente de trabalho e inicia o processo de trabalho do SDK. Este script é o ENTRYPOINT predefinido nas imagens do SDK do Apache Beam. No entanto, se usar uma imagem base diferente ou substituir o valor ENTRYPOINT predefinido, tem de executar o script explicitamente. Para mais informações, consulte Modifique o ponto de entrada do contentor neste documento.
  • A imagem do contentor tem de suportar a arquitetura das VMs de trabalho para a sua tarefa do Dataflow. Se planeia usar o contentor personalizado em VMs ARM, recomendamos que crie uma imagem de várias arquiteturas. Para mais informações, consulte Crie uma imagem de contentor com várias arquiteturas.

Antes de começar

  1. Verifique se a versão do SDK Apache Beam instalada suporta o Runner v2 e a versão do seu idioma. Para mais informações, consulte Instale o SDK do Apache Beam.

  2. Para testar a imagem do contentor localmente, tem de ter o Docker instalado. Para mais informações, consulte o artigo Obtenha o Docker.

  3. Crie um repositório do Artifact Registry. Especifique o formato da imagem do Docker. Tem de ter, pelo menos, o acesso de gravação do Artifact Registry ao repositório.

    Para criar um novo repositório, execute o comando gcloud artifacts repositories create:

    gcloud artifacts repositories create REPOSITORY \
      --repository-format=docker \
      --location=REGION \
      --async
    

    Substitua o seguinte:

    • REPOSITORY: um nome para o seu repositório. Os nomes dos repositórios têm de ser exclusivos para cada localização num projeto.
    • REGION: a região onde implementar a sua tarefa do Dataflow. Selecione uma região do Dataflow perto de onde executa os comandos. O valor tem de ser um nome de região válido. Para mais informações acerca das regiões e localizações, consulte o artigo Localizações do Dataflow.

    Este exemplo usa a flag --async. O comando é devolvido imediatamente, sem aguardar a conclusão da operação.

  4. Para configurar o Docker para autenticar pedidos para o Artifact Registry, execute o comando gcloud auth configure-docker:

    gcloud auth configure-docker REGION-docker.pkg.dev
    

    O comando atualiza a configuração do Docker. Agora, pode estabelecer ligação ao Artifact Registry no seu Google Cloud projeto para enviar imagens.

Selecione uma imagem base

Recomendamos que comece com uma imagem do SDK do Apache Beam como imagem do contentor base. Estas imagens são lançadas como parte dos lançamentos do Apache Beam para o Docker Hub.

Use uma imagem de base do Apache Beam

Para usar uma imagem do SDK do Apache Beam como imagem base, especifique a imagem do contentor na instrução FROM e, em seguida, adicione as suas próprias personalizações.

Java

Este exemplo usa o Java 8 com a versão 2.68.0 do SDK do Apache Beam.

FROM apache/beam_java8_sdk:2.68.0

# Make your customizations here, for example:
ENV FOO=/bar
COPY path/to/myfile ./

A versão de tempo de execução do contentor personalizado tem de corresponder ao tempo de execução que vai usar para iniciar o pipeline. Por exemplo, se iniciar o pipeline a partir de um ambiente Java 11 local, a linha FROM tem de especificar um ambiente Java 11: apache/beam_java11_sdk:....

Python

Este exemplo usa o Python 3.10 com a versão 2.68.0 do SDK do Apache Beam.

FROM apache/beam_python3.10_sdk:2.68.0

# Make your customizations here, for example:
ENV FOO=/bar
COPY path/to/myfile ./

A versão de tempo de execução do contentor personalizado tem de corresponder ao tempo de execução que vai usar para iniciar o pipeline. Por exemplo, se iniciar o pipeline a partir de um ambiente Python 3.10 local, a linha FROM tem de especificar um ambiente Python 3.10: apache/beam_python3.10_sdk:....

Ir

Este exemplo usa o Go com a versão 2.68.0 do SDK do Apache Beam.

FROM apache/beam_go_sdk:2.68.0

# Make your customizations here, for example:
ENV FOO=/bar
COPY path/to/myfile ./

Use uma imagem base personalizada

Se quiser usar uma imagem base diferente ou precisar de modificar algum aspeto das imagens Apache Beam predefinidas (como a versão ou os patches do SO), use um processo de compilação em várias fases. Copie os artefactos necessários de uma imagem de base do Apache Beam predefinida.

Defina o ENTRYPOINT para executar o script /opt/apache/beam/boot, que inicializa o ambiente do trabalhador e inicia o processo do trabalhador do SDK. Se não definir este ponto de entrada, os trabalhadores do Dataflow não são iniciados corretamente.

O exemplo seguinte mostra um Dockerfile que copia ficheiros do SDK do Apache Beam:

Java

FROM openjdk:8

# Copy files from official SDK image, including script/dependencies.
COPY --from=apache/beam_java8_sdk:2.68.0 /opt/apache/beam /opt/apache/beam

# Set the entrypoint to Apache Beam SDK launcher.
ENTRYPOINT ["/opt/apache/beam/boot"]

Python

FROM python:3.10-slim

# Install SDK.
RUN pip install --no-cache-dir apache-beam[gcp]==2.68.0

# Verify that the image does not have conflicting dependencies.
RUN pip check

# Copy files from official SDK image, including script/dependencies.
COPY --from=apache/beam_python3.10_sdk:2.68.0 /opt/apache/beam /opt/apache/beam

# Set the entrypoint to Apache Beam SDK launcher.
ENTRYPOINT ["/opt/apache/beam/boot"]

Este exemplo pressupõe que as dependências necessárias (neste caso, o Python 3.10 e o pip) foram instaladas na imagem base existente. A instalação do SDK do Apache Beam na imagem garante que a imagem tem as dependências do SDK necessárias e reduz o tempo de arranque do trabalhador.

Importante: a versão do SDK especificada nas instruções RUN e COPY tem de corresponder à versão usada para iniciar o pipeline.

Ir

FROM golang:latest

# Copy files from official SDK image, including script/dependencies.
COPY --from=apache/beam_go_sdk:2.68.0 /opt/apache/beam /opt/apache/beam

# Set the entrypoint to Apache Beam SDK launcher.
ENTRYPOINT ["/opt/apache/beam/boot"]

Modifique o ponto de entrada do contentor

Se o seu contentor executar um script personalizado durante o arranque do contentor, o script tem de terminar com a execução de /opt/apache/beam/boot. Os argumentos transmitidos pelo Dataflow durante o arranque do contentor têm de ser transmitidos para o script de arranque predefinido. O exemplo seguinte mostra um script de arranque personalizado que chama o script de arranque predefinido:

#!/bin/bash

echo "This is my custom script"
# ...

# Pass command arguments to the default boot script.
/opt/apache/beam/boot "$@"

No Dockerfile, defina o ENTRYPOINT para chamar o seu script:

Java

FROM apache/beam_java8_sdk:2.68.0

COPY script.sh path/to/my/script.sh
ENTRYPOINT [ "path/to/my/script.sh" ]

Python

FROM apache/beam_python3.10_sdk:2.68.0

COPY script.sh path/to/my/script.sh
ENTRYPOINT [ "path/to/my/script.sh" ]

Ir

FROM apache/beam_go_sdk:2.68.0

COPY script.sh path/to/my/script.sh
ENTRYPOINT [ "path/to/my/script.sh" ]

Crie e envie a imagem

Pode usar o Cloud Build ou o Docker para criar a imagem do contentor e enviá-la para um repositório do Artifact Registry.

Cloud Build

Para criar o ficheiro e enviá-lo para o seu repositório do Artifact Registry, execute o comando gcloud builds submit:

  gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/dataflow/FILE_NAME:TAG .

Docker

docker build . --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/dataflow/FILE_NAME:TAG
docker push REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/dataflow/FILE_NAME:TAG

Substitua o seguinte:

  • REGION: a região na qual implementar a sua tarefa do Dataflow. O valor da variável REGION tem de ser um nome de região válido.
  • PROJECT_ID: o nome do projeto ou o nome de utilizador.
  • REPOSITORY: o nome do repositório de imagens.
  • FILE_NAME: o nome do seu Dockerfile.
  • TAG: a etiqueta de imagem. Especifique sempre um SHA ou uma etiqueta do contentor com controlo de versões. Não use a etiqueta :latest nem uma etiqueta mutável.

Pré-instale dependências do Python

Esta secção aplica-se a pipelines Python.

Quando inicia uma tarefa do Dataflow Python, pode especificar dependências adicionais com a opção --requirements_file ou --extra_packages no momento da execução. Para mais informações, consulte o artigo Gerir dependências de pipelines Python. As dependências adicionais são instaladas em cada contentor do worker do Dataflow. Quando a tarefa é iniciada pela primeira vez e durante o dimensionamento automático, a instalação de dependências leva frequentemente a uma elevada utilização da CPU e a um longo período de preparação em todos os trabalhadores do Dataflow iniciados recentemente.

Para evitar instalações repetitivas de dependências, pode pré-criar uma imagem de contentor do SDK Python personalizada com as dependências pré-instaladas. Pode executar este passo no momento da compilação através de um Dockerfile ou no momento da execução quando envia a tarefa.

Os trabalhadores criam um novo ambiente Python virtual quando iniciam o contentor. Por este motivo, instale as dependências no ambiente Python predefinido (global) em vez de criar um ambiente virtual. Se ativar um ambiente virtual na imagem do contentor, este ambiente pode não ser ativado quando a tarefa é iniciada. Para mais informações, consulte a secção Problemas comuns.

Pré-instale com um Dockerfile

Para adicionar dependências adicionais diretamente ao seu contentor personalizado Python, use os seguintes comandos:

FROM apache/beam_python3.10_sdk:2.68.0

COPY requirements.txt .

# Pre-install Python dependencies. For reproducibile builds,
# supply all of the dependencies and their versions in a requirements.txt file.
RUN pip install -r requirements.txt

# You can also install individual dependencies.
RUN pip install lxml
# Pre-install other dependencies.
RUN apt-get update \
  && apt-get dist-upgrade \
  && apt-get install -y --no-install-recommends ffmpeg

Envie o seu trabalho com as opções de pipeline --sdk_container_image e --sdk_location. A opção --sdk_location impede que o SDK seja transferido quando a tarefa é iniciada. O SDK é obtido diretamente da imagem do contentor.

O exemplo seguinte executa o exemplo de pipeline wordcount:

python -m apache_beam.examples.wordcount \
  --input=INPUT_FILE \
  --output=OUTPUT_FILE \
  --project=PROJECT_ID \
  --region=REGION \
  --temp_location=TEMP_LOCATION \
  --runner=DataflowRunner \
  --experiments=use_runner_v2 \
  --sdk_container_image=IMAGE_URI
  --sdk_location=container

Substitua o seguinte:

  • INPUT_FILE: um ficheiro de entrada para o pipeline
  • OUTPUT_FILE: um caminho para escrever a saída
  • PROJECT_ID: o ID do projeto da Google Cloud Platform
  • REGION: a região para implementar a sua tarefa do Dataflow
  • TEMP_LOCATION: o caminho do Cloud Storage para o Dataflow preparar ficheiros de tarefas temporários
  • IMAGE_URI: o URI da imagem do contentor personalizado

Pré-crie uma imagem de contentor quando enviar a tarefa

A pré-criação de uma imagem de contentor permite-lhe pré-instalar as dependências do pipeline antes do início da tarefa. Não precisa de criar uma imagem de contentor personalizada.

Para pré-criar um contentor com dependências Python adicionais quando envia uma tarefa, use as seguintes opções de pipeline:

  • --prebuild_sdk_container_engine=[cloud_build | local_docker]. Quando esta flag está definida, o Apache Beam gera um contentor personalizado e instala todas as dependências especificadas pelas opções --requirements_file e --extra_packages. Esta flag suporta os seguintes valores:

    • cloud_build. Use o Cloud Build para criar o contentor. A API Cloud Build tem de estar ativada no seu projeto.
    • local_docker. Use a sua instalação local do Docker para criar o contentor.
  • --docker_registry_push_url=IMAGE_PATH. Substitua IMAGE_PATH por uma pasta do Artifact Registry.

  • --sdk_location=container. Esta opção impede que os trabalhadores transfiram o SDK quando a tarefa é iniciada. Em alternativa, o SDK é obtido diretamente a partir da imagem do contentor.

O exemplo seguinte usa o Cloud Build para pré-criar a imagem:

python -m apache_beam.examples.wordcount \
  --input=INPUT_FILE \
  --output=OUTPUT_FILE \
  --project=PROJECT_ID \
  --region=REGION \
  --temp_location=TEMP_LOCATION \
  --runner=DataflowRunner \
  --disk_size_gb=DISK_SIZE_GB \
  --experiments=use_runner_v2 \
  --requirements_file=./requirements.txt \
  --prebuild_sdk_container_engine=cloud_build \
  --docker_registry_push_url=IMAGE_PATH \
  --sdk_location=container

A funcionalidade de pré-compilação requer a versão 2.25.0 ou posterior do SDK do Apache Beam para Python.

O fluxo de trabalho de pré-compilação da imagem do contentor do SDK usa a imagem transmitida através da opção de pipeline --sdk_container_image como imagem de base. Se a opção não estiver definida, é usada por predefinição uma imagem do Apache Beam como imagem base.

Pode reutilizar uma imagem de contentor do SDK Python pré-criada noutro trabalho com as mesmas dependências e versão do SDK. Para reutilizar a imagem, transmita o URL da imagem do contentor pré-criado para a outra tarefa através da opção --sdk_container_image pipeline. Remova as opções de dependência --requirements_file, --extra_packages e --setup_file.

Se não planeia reutilizar a imagem, elimine-a após a conclusão da tarefa. Pode eliminar a imagem com a CLI gcloud ou nas páginas do Artifact Registry na Google Cloud consola.

Se a imagem estiver armazenada no Artifact Registry, use o comando artifacts docker images delete:

   gcloud artifacts docker images delete IMAGE --delete-tags

Problemas comuns

  • Se o seu trabalho tiver dependências Python adicionais de um espelho PyPi privado e não puderem ser extraídas por um trabalho de compilação na nuvem remoto, experimente usar a opção Docker local ou criar o seu contentor através de um Dockerfile.

  • Se a tarefa do Cloud Build falhar com docker exit code 137, significa que a tarefa de compilação ficou sem memória, possivelmente devido ao tamanho das dependências que estão a ser instaladas. Use um tipo de máquina de trabalho do Cloud Build maior transmitindo --cloud_build_machine_type=machine_type, em que machine_type é uma das seguintes opções:

    • n1-highcpu-8
    • n1-highcpu-32
    • e2-highcpu-8
    • e2-highcpu-32

    Por predefinição, o Cloud Build usa o tipo de máquina e2-medium.

  • No Apache Beam 2.44.0 e posteriores, os trabalhadores criam um ambiente virtual quando iniciam um contentor personalizado. Se o contentor criar o seu próprio ambiente virtual para instalar dependências, essas dependências são rejeitadas. Este comportamento pode causar erros, como os seguintes:

    ModuleNotFoundError: No module named '<dependency name>'

    Para evitar este problema, instale as dependências no ambiente Python predefinido (global). Como solução alternativa, desative este comportamento no Beam 2.48.0 e posteriormente definindo a seguinte variável de ambiente na imagem do contentor:

    ENV RUN_PYTHON_SDK_IN_DEFAULT_ENVIRONMENT=1

O que se segue?