Crea immagini container personalizzate per Dataflow

Questo documento descrive come creare un'immagine container personalizzata per i job Dataflow.

Requisiti

Un'immagine container personalizzata per Dataflow deve soddisfare i seguenti requisiti:

  • L'SDK Apache Beam e le dipendenze necessarie sono installati. Ti consigliamo di iniziare con un'immagine predefinita dell'SDK Apache Beam. Per maggiori informazioni, consulta Selezionare un'immagine di base in questo documento.
  • Lo script /opt/apache/beam/boot deve essere eseguito come ultimo passaggio durante l'avvio del container. Questo script inizializza l'ambiente worker e avvia il processo worker dell'SDK. Questo script è il valore predefinito ENTRYPOINT nelle immagini dell'SDK Apache Beam. Tuttavia, se utilizzi un'immagine di base diversa o se sostituisci il valore predefinito ENTRYPOINT, devi eseguire lo script in modo esplicito. Per ulteriori informazioni, consulta Modificare il punto di ingresso del container in questo documento.
  • L'immagine container deve supportare l'architettura delle VM worker per il job Dataflow. Se prevedi di utilizzare il container personalizzato su VM ARM, ti consigliamo di creare un'immagine multi-architettura. Per maggiori informazioni, consulta Creare un'immagine container con più architetture.

Prima di iniziare

  1. Verifica che la versione dell'SDK Apache Beam installato supporti Runner v2 e la versione in uso nella lingua. Per saperne di più, consulta Installare l'SDK Apache Beam.

  2. Per testare la tua immagine container in locale, devi aver installato Docker. Per ulteriori informazioni, consulta Scarica Docker.

  3. Crea un repository Artifact Registry. Specifica il formato dell'immagine Docker. Devi avere almeno accesso come Writer Artifact Registry al repository.

    Per creare un nuovo repository, esegui il comando gcloud artifacts repositories create:

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

    Sostituisci quanto segue:

    • REPOSITORY: un nome per il repository. I nomi dei repository devono essere univoci per ogni località in un progetto.
    • REGION: la regione in cui eseguire il deployment del job Dataflow. Seleziona un'area geografica Dataflow vicina a quella in cui esegui i comandi. Il valore deve essere un nome di regione valido. Per ulteriori informazioni su regioni e località, consulta Località Dataflow.

    In questo esempio viene utilizzato il flag --async. Il comando restituisce immediatamente, senza attendere il completamento dell'operazione.

  4. Per configurare Docker per autenticare le richieste per Artifact Registry, esegui il comando gcloud auth configure-docker:

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

    Il comando aggiorna la configurazione Docker. Ora puoi connetterti ad Artifact Registry nel tuo progetto Google Cloud per eseguire il push delle immagini.

Seleziona un'immagine di base

Ti consigliamo di iniziare con un'immagine dell'SDK Apache Beam come immagine container di base. Queste immagini vengono rilasciate come parte delle release di Apache Beam in Docker Hub.

Utilizza un'immagine di base Apache Beam

Per utilizzare un'immagine dell'SDK Apache Beam come immagine di base, specifica l'immagine del container nell'istruzione FROM, quindi aggiungi le tue personalizzazioni.

Java

Questo esempio utilizza Java 8 con l'SDK Apache Beam versione 2.56.0.

FROM apache/beam_java8_sdk:2.56.0

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

La versione di runtime del container personalizzato deve corrispondere al runtime che utilizzerai per avviare la pipeline. Ad esempio, se avvii la pipeline da un ambiente Java 11 locale, la riga FROM deve specificare un ambiente Java 11: apache/beam_java11_sdk:....

Python

In questo esempio viene utilizzato Python 3.10 con l'SDK Apache Beam versione 2.56.0.

FROM apache/beam_python3.10_sdk:2.56.0

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

La versione di runtime del container personalizzato deve corrispondere al runtime che utilizzerai per avviare la pipeline. Ad esempio, se avvii la pipeline da un ambiente Python 3.10 locale, la riga FROM deve specificare un ambiente Python 3.10: apache/beam_python3.10_sdk:....

Go

Questo esempio utilizza Go con l'SDK Apache Beam versione 2.56.0.

FROM apache/beam_go_sdk:2.56.0

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

Utilizza un'immagine di base personalizzata

Se vuoi utilizzare un'immagine di base diversa o devi modificare alcuni aspetti delle immagini Apache Beam predefinite (ad esempio la versione o le patch del sistema operativo), utilizza un processo di creazione multifase. Copia gli artefatti necessari da un'immagine di base Apache Beam predefinita.

Imposta ENTRYPOINT per l'esecuzione dello script /opt/apache/beam/boot, che inizializza l'ambiente worker e avvia il processo worker dell'SDK. Se non imposti questo punto di ingresso, i worker Dataflow non si avviano correttamente.

L'esempio seguente mostra un Dockerfile che copia i file dall'SDK Apache Beam:

Java

FROM openjdk:8

# Copy files from official SDK image, including script/dependencies.
COPY --from=apache/beam_java8_sdk:2.56.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.56.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.56.0 /opt/apache/beam /opt/apache/beam

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

In questo esempio si presuppone che siano state installate le dipendenze necessarie (in questo caso Python 3.10 e pip) nell'immagine di base esistente. L'installazione dell'SDK Apache Beam nell'immagine assicura che quest'ultima abbia le dipendenze SDK necessarie e riduce il tempo di avvio dei worker.

Importante: la versione dell'SDK specificata nelle istruzioni RUN e COPY deve corrispondere alla versione utilizzata per avviare la pipeline.

Go

FROM golang:latest

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

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

Modifica il punto di ingresso del container

Se il container esegue uno script personalizzato durante l'avvio, lo script deve terminare con l'esecuzione di /opt/apache/beam/boot. Gli argomenti passati da Dataflow durante l'avvio del container devono essere passati allo script di avvio predefinito. L'esempio seguente mostra uno script di avvio personalizzato che chiama lo script di avvio predefinito:

#!/bin/bash

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

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

Nel Dockerfile, imposta ENTRYPOINT in modo che chiami lo script:

Java

FROM apache/beam_java8_sdk:2.56.0

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

Python

FROM apache/beam_python3.10_sdk:2.56.0

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

Go

FROM apache/beam_go_sdk:2.56.0

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

Crea ed esegui il push dell'immagine

Puoi utilizzare Cloud Build o Docker per creare la tua immagine container ed eseguirne il push in un repository Artifact Registry.

Cloud Build

Per creare il file ed eseguirne il push nel repository Artifact Registry, esegui il 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

Sostituisci quanto segue:

  • REGION: la regione in cui eseguire il deployment del job Dataflow. Il valore della variabile REGION deve essere un nome di regione valido.
  • PROJECT_ID: il nome o il nome utente del progetto.
  • REPOSITORY: il nome del repository di immagini.
  • FILE_NAME: il nome del Dockerfile.
  • TAG: il tag immagine. Specifica sempre un tag o SHA del container con il controllo delle versioni. Non utilizzare il tag :latest o un tag modificabile.

Preinstalla le dipendenze Python

Questa sezione si applica alle pipeline Python.

Quando avvii un job Python Dataflow, puoi specificare ulteriori dipendenze utilizzando l'opzione --requirements_file o --extra_packages in fase di runtime. Per maggiori informazioni, consulta la pagina relativa alla gestione delle dipendenze della pipeline Python. In ogni container worker Dataflow sono installate dipendenze aggiuntive. Al primo avvio del job e durante la scalabilità automatica, l'installazione delle dipendenze spesso determina un elevato utilizzo della CPU e un lungo periodo di preparazione per tutti i worker Dataflow appena avviati.

Per evitare installazioni ripetitive di dipendenze, puoi pre-creare un'immagine container dell'SDK Python personalizzata con le dipendenze preinstallate. Puoi eseguire questo passaggio al momento della creazione utilizzando un Dockerfile o in fase di esecuzione quando invii il job.

I worker creano un nuovo ambiente Python virtuale all'avvio del container. Per questo motivo, installa le dipendenze nell'ambiente Python predefinito (globale) anziché creare un ambiente virtuale. Se attivi un ambiente virtuale nell'immagine container, questo ambiente potrebbe non essere attivo all'avvio del job. Per ulteriori informazioni, consulta la sezione Problemi comuni.

Preinstallazione con un Dockerfile

Per aggiungere ulteriori dipendenze direttamente al container personalizzato Python, utilizza i comandi seguenti:

FROM apache/beam_python3.10_sdk:2.56.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

Invia il job con le opzioni delle pipeline --sdk_container_image e --sdk_location. L'opzione --sdk_location impedisce il download dell'SDK all'avvio del job. L'SDK viene recuperato direttamente dall'immagine container.

L'esempio seguente esegue la pipeline di esempio 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

Sostituisci quanto segue:

  • INPUT_FILE: un file di input per la pipeline
  • OUTPUT_FILE: un percorso in cui scrivere l'output
  • PROJECT_ID: l'ID del progetto Google Cloud
  • REGION: la regione in cui eseguire il deployment del job Dataflow
  • TEMP_LOCATION: il percorso in Cloud Storage per consentire a Dataflow di organizzare i file temporanei dei job
  • IMAGE_URI: l'URI dell'immagine container personalizzata

Crea un'immagine container durante l'invio del job

La pre-creazione di un'immagine container consente di preinstallare le dipendenze della pipeline prima dell'avvio del job. Non è necessario creare un'immagine container personalizzata.

Per pre-creare un container con dipendenze Python aggiuntive quando invii un job, utilizza le seguenti opzioni di pipeline:

  • --prebuild_sdk_container_engine=[cloud_build | local_docker]. Se questo flag è impostato, Apache Beam genera un container personalizzato e installa tutte le dipendenze specificate dalle opzioni --requirements_file e --extra_packages. Questo flag supporta i seguenti valori:

    • cloud_build. Utilizza Cloud Build per creare il container. L'API Cloud Build deve essere abilitata nel tuo progetto.
    • local_docker. Usa la tua installazione Docker locale per creare il container.
  • --docker_registry_push_url=IMAGE_PATH. Sostituisci IMAGE_PATH con una cartella Artifact Registry.

  • --sdk_location=container. Questa opzione impedisce ai worker di scaricare l'SDK all'avvio del job. ma viene recuperato direttamente dall'immagine container.

L'esempio seguente utilizza Cloud Build per pre-creare l'immagine:

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

La funzionalità di pre-creazione richiede l'SDK Apache Beam per Python versione 2.25.0 o successive.

Il flusso di lavoro per la pre-creazione delle immagini container dell'SDK utilizza l'immagine passata utilizzando l'opzione della pipeline --sdk_container_image come immagine di base. Se l'opzione non è impostata, per impostazione predefinita viene utilizzata un'immagine Apache Beam come immagine di base.

Puoi riutilizzare un'immagine container dell'SDK Python predefinito in un altro job con le stesse dipendenze e la stessa versione dell'SDK. Per riutilizzare l'immagine, trasmetti l'URL dell'immagine container predefinito all'altro job usando l'opzione pipeline --sdk_container_image. Rimuovi le opzioni di dipendenza --requirements_file, --extra_packages e --setup_file.

Se non prevedi di riutilizzare l'immagine, eliminala al termine del job. Puoi eliminare l'immagine con gcloud CLI o nelle pagine Artifact Registry della console Google Cloud.

Se l'immagine è archiviata in Artifact Registry, utilizza il comando artifacts docker images delete:

   gcloud artifacts docker images delete IMAGE --delete-tags

Problemi comuni

  • Se il job ha dipendenze Python aggiuntive da un mirroring PyPi privato e non può essere eseguito da un job Cloud Build remoto, prova a utilizzare l'opzione Docker locale oppure prova a creare il container utilizzando un Dockerfile.

  • Se il job di Cloud Build ha esito negativo con docker exit code 137, ha esaurito la memoria, potenzialmente a causa delle dimensioni delle dipendenze installate. Utilizza un tipo di macchina worker Cloud Build più grande passando --cloud_build_machine_type=machine_type, dove machine_type è una delle seguenti opzioni:

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

    Per impostazione predefinita, Cloud Build utilizza il tipo di macchina e2-medium.

  • In Apache Beam 2.44.0 e versioni successive, i worker creano un ambiente virtuale all'avvio di un container personalizzato. Se il container crea un proprio ambiente virtuale per installare le dipendenze, queste vengono ignorate. Questo comportamento può causare errori quali:

    ModuleNotFoundError: No module named '<dependency name>'

    Per evitare questo problema, installa le dipendenze nell'ambiente Python predefinito (globale). Come soluzione alternativa, disattiva questo comportamento in Beam 2.48.0 e nelle versioni successive impostando la seguente variabile di ambiente nell'immagine container:

    ENV RUN_PYTHON_SDK_IN_DEFAULT_ENVIRONMENT=1

Passaggi successivi