Créer des images de conteneurs personnalisées pour Dataflow

Ce document explique comment créer une image de conteneur personnalisée pour les tâches Dataflow.

Conditions requises

Une image de conteneur personnalisé pour Dataflow doit répondre aux exigences suivantes :

  • Le SDK Apache Beam et les dépendances nécessaires sont installés. Nous vous recommandons de commencer par une image par défaut du SDK Apache Beam. Pour en savoir plus, consultez la section Sélectionner une image de base de ce document.
  • Le script /opt/apache/beam/boot doit s'exécuter à la dernière étape lors du démarrage du conteneur. Ce script initialise l'environnement de calcul et lance le processus des SDK. Ce script correspond à la valeur ENTRYPOINT par défaut dans les images du SDK Apache Beam. Toutefois, si vous utilisez une image de base différente ou si vous remplacez la valeur par défaut ENTRYPOINT, vous devez exécuter le script de manière explicite. Pour plus d'informations, consultez Modifier le point d'entrée du conteneur de ce document.
  • Votre image de conteneur doit être compatible avec l'architecture des VM de nœud de calcul pour votre tâche Dataflow. Si vous prévoyez d'utiliser le conteneur personnalisé sur des VM basées sur l'architecture ARM, nous vous recommandons de créer une image multi-architecture. Pour en savoir plus, consultez Créer une image de conteneur multi-architecture.

Avant de commencer

  1. Vérifiez que la version du SDK Apache Beam installée est compatible avec l'exécuteur v2 et votre version de langage. Pour en savoir plus, consultez la section Installer le SDK Apache Beam.

  2. Pour tester votre image de conteneur localement, vous devez avoir installé Docker. Pour en savoir plus, consultez la page Obtenir Docker.

  3. Créez un dépôt Artifact Registry. Spécifiez le format d'image Docker. Vous devez au moins disposer d'un accès Rédacteur à Artifact Registry au dépôt.

    Pour créer un dépôt, exécutez la commande gcloud artifacts repositories create :

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

    Remplacez les éléments suivants :

    • REPOSITORY : nom de votre dépôt. Les noms de dépôt doivent être uniques pour chaque emplacement d'un projet.
    • REGION: région dans laquelle déployer votre tâche Dataflow. Sélectionnez une région Dataflow proche de l'emplacement où vous exécutez les commandes. La valeur doit être un nom de région valide. Pour en savoir plus sur les régions et les emplacements, consultez la page Emplacements Dataflow.

    Cet exemple utilise l'option --async. La commande renvoie immédiatement une réponse, sans attendre la fin de l'opération.

  4. Pour configurer Docker afin d'authentifier les requêtes destinées à Artifact Registry, exécutez la commande gcloud auth configure-docker :

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

    La commande met à jour votre configuration Docker. Vous pouvez désormais vous connecter à Artifact Registry dans votre projet Google Cloud pour transférer des images.

Sélectionner une image de base

Nous vous recommandons de commencer par une image du SDK Apache Beam comme image de conteneur de base. Les images sont publiées dans les versions d'Apache Beam sur Docker Hub.

Utiliser une image de base Apache Beam

Pour utiliser une image du SDK Apache Beam comme image de base, spécifiez l'image de conteneur dans l'instruction FROM, puis ajoutez vos propres personnalisations.

Java

Cet exemple utilise Java 8 avec le SDK Apache Beam version 2.55.1.

FROM apache/beam_java8_sdk:2.55.1

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

La version d'exécution du conteneur personnalisé doit correspondre à l'environnement d'exécution que vous utiliserez pour démarrer le pipeline. Par exemple, si vous démarrez le pipeline à partir d'un environnement Java 11 local, la ligne FROM doit spécifier un environnement Java 11 : apache/beam_java11_sdk:....

Python

Cet exemple utilise Python 3.10 avec le SDK Apache Beam version 2.55.1.

FROM apache/beam_python3.10_sdk:2.55.1

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

La version d'exécution du conteneur personnalisé doit correspondre à l'environnement d'exécution que vous utiliserez pour démarrer le pipeline. Par exemple, si vous démarrez le pipeline à partir d'un environnement Python 3.10 local, la ligne FROM doit spécifier un environnement Python 3.10 : apache/beam_python3.10_sdk:....

Go

Cet exemple utilise Go avec le SDK Apache Beam version 2.55.1.

FROM apache/beam_go_sdk:2.55.1

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

Utiliser une image de base personnalisée

Si vous souhaitez utiliser une image de base différente ou si vous devez modifier un aspect des images Apache Beam par défaut (telles que la version ou les correctifs du système d'exploitation), utilisez unecompilation en plusieurs étapes. Copiez les artefacts nécessaires à partir d'une image de base Apache Beam par défaut.

Définissez l'option ENTRYPOINT pour exécuter le script /opt/apache/beam/boot, qui initialise l'environnement de calcul et lance le processus du SDK. Si vous ne définissez pas ce point d'entrée, les nœuds de calcul Dataflow ne démarrent pas correctement.

L'exemple suivant montre un fichier Dockerfile qui copie des fichiers à partir du SDK Apache Beam :

Java

FROM openjdk:8

# Copy files from official SDK image, including script/dependencies.
COPY --from=apache/beam_java8_sdk:2.55.1 /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.55.1

# 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.55.1 /opt/apache/beam /opt/apache/beam

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

Cet exemple suppose que les dépendances nécessaires (dans ce cas, Python 3.10 et pip) ont été installées sur l'image de base existante. L'installation du SDK Apache Beam dans l'image garantit que l'image dispose des dépendances de SDK nécessaires et réduit le temps de démarrage des nœuds de calcul.

Important : La version du SDK spécifiée dans les instructions RUN et COPY doit correspondre à la version utilisée pour lancer le pipeline.

Go

FROM golang:latest

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

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

Modifier le point d'entrée du conteneur

Si votre conteneur exécute un script personnalisé au démarrage du conteneur, il doit se terminer par l'exécution de /opt/apache/beam/boot. Les arguments transmis par Dataflow au démarrage du conteneur doivent être transmis au script de démarrage par défaut. L'exemple suivant présente un script de démarrage personnalisé qui appelle le script de démarrage par défaut :

#!/bin/bash

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

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

Dans votre Dockerfile, définissez le ENTRYPOINT pour appeler votre script :

Java

FROM apache/beam_java8_sdk:2.55.1

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

Python

FROM apache/beam_python3.10_sdk:2.55.1

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

Go

FROM apache/beam_go_sdk:2.55.1

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

Créer et transférer l'image

Vous pouvez utiliser Cloud Build ou Docker pour créer votre image de conteneur et la transférer dans un dépôt Artifact Registry.

Cloud Build

Pour créer le fichier et le transférer vers votre dépôt Artifact Registry, exécutez la commande 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

Remplacez les éléments suivants :

  • REGION: région dans laquelle déployer votre tâche Dataflow La valeur de la variable REGION doit être un nom de région valide.
  • PROJECT_ID : nom du projet ou de l'utilisateur.
  • REPOSITORY : nom du dépôt de l'image.
  • FILE_NAME : nom de votre fichier Dockerfile.
  • TAG : tag de l'image. Spécifiez toujours un SHA ou un tag de conteneur avec versions gérées. N'utilisez pas le tag :latest ni un tag modifiable.

Préinstaller des dépendances Python

Cette section s'applique aux pipelines Python.

Lorsque vous lancez une tâche Python Dataflow, vous pouvez spécifier des dépendances supplémentaires en utilisant l'option --requirements_file ou --extra_packages au moment de l'exécution. Pour en savoir plus, consultez la page Gérer les dépendances de pipeline Python. Des dépendances supplémentaires sont installées dans chaque conteneur de nœuds de calcul Dataflow. Lors du premier démarrage de la tâche et de l'autoscaling, l'installation des dépendances entraîne souvent une utilisation élevée du processeur et une longue période de préchauffage sur tous les nouveaux nœuds de calcul Dataflow.

Pour éviter ces installations de dépendances répétitives, vous pouvez préconfigurer l'image de conteneur personnalisée du SDK Python avec les dépendances préinstallées. Vous pouvez effectuer cette étape au moment de la compilation à l'aide d'un fichier Dockerfile, ou au moment de l'exécution lorsque vous envoyez la tâche.

Les nœuds de calcul créent un environnement Python virtuel lorsqu'ils démarrent le conteneur. Pour cette raison, installez des dépendances dans l'environnement Python (global) par défaut au lieu de créer un environnement virtuel. Si vous activez un environnement virtuel dans votre image de conteneur, cet environnement peut ne pas être activé au démarrage du job. Pour en savoir plus, consultez la section Problèmes courants.

Préinstaller à l'aide d'un fichier Dockerfile

Pour ajouter des dépendances supplémentaires directement à votre conteneur personnalisé Python, utilisez les commandes suivantes :

FROM apache/beam_python3.10_sdk:2.55.1

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

Envoyez votre job avec les options de pipeline --sdk_container_image et --sdk_location. L'option --sdk_location empêche le téléchargement du SDK lors du lancement de votre job. Le SDK est récupéré directement à partir de l'image de conteneur.

L'exemple suivant exécute l'exemple 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

Remplacez les éléments suivants :

  • INPUT_FILE : fichier d'entrée pour le pipeline
  • OUTPUT_FILE : chemin d'accès au fichier dans lequel écrire le résultat
  • PROJECT_ID : ID de projet Google Cloud
  • REGION: région dans laquelle déployer votre tâche Dataflow
  • TEMP_LOCATION : chemin d'accès à Cloud Storage dans lequel Dataflow prépare les fichiers de jobs temporaires
  • IMAGE_URI : URI de l'image de conteneur personnalisée

Préconfigurer une image de conteneur lors de l'envoi de la tâche

Préconfigurer une image de conteneur vous permet de pré-installer les dépendances de pipeline avant le démarrage de la tâche. Vous n'avez pas besoin de créer une image de conteneur personnalisé.

Pour précompiler un conteneur avec des dépendances Python supplémentaires lorsque vous envoyez une tâche, utilisez les options de pipeline suivantes :

  • --prebuild_sdk_container_engine=[cloud_build | local_docker]. Lorsque cette option est définie, Apache Beam génère un conteneur personnalisé et installe toutes les dépendances spécifiées par les options --requirements_file et --extra_packages. Cette option accepte les valeurs suivantes :

    • cloud_build. Utilisez Cloud Build pour créer le conteneur. L'API Cloud Build doit être activée dans votre projet.
    • local_docker. Utilisez votre installation Docker locale pour créer le conteneur.
  • --docker_registry_push_url=IMAGE_PATH. Remplacez IMAGE_PATH par un dossier Artifact Registry.

  • --sdk_location=container. Cette option empêche les nœuds de calcul de télécharger le SDK au lancement de la tâche. À la place, le SDK est récupéré directement à partir de l'image de conteneur.

L'exemple suivant utilise Cloud Build pour précompiler l'image :

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 fonctionnalité prédéfinie nécessite le SDK Apache Beam pour Python en version 2.25.0 ou ultérieure.

Le workflow de préconfiguration d'images de conteneurs du SDK utilise l'image transmise avec l'option de pipeline --sdk_container_image comme image de base. Si cette option n'est pas définie, une image Apache Beam sera utilisée par défaut comme image de base.

Vous pouvez réutiliser une image de conteneur de SDK Python préconfigurée dans un autre job qui possède les mêmes dépendances et utilise la même version du SDK. Pour réutiliser l'image, transmettez à l'autre tâche l'URL de l'image de conteneur préconfigurée à l'aide de l'option de pipeline --sdk_container_image. Supprimez les options de dépendance --requirements_file, --extra_packages et --setup_file.

Si vous ne prévoyez pas de réutiliser l'image, supprimez-la une fois le job terminé. Vous pouvez supprimer l'image à l'aide de gcloud CLI, ou bien dans les pages Artifact Registry de la console Google Cloud.

Si l'image est stockée dans Artifact Registry, utilisez la commande artifacts docker images delete :

   gcloud artifacts docker images delete IMAGE --delete-tags

Problèmes courants

  • Si votre job possède des dépendances Python supplémentaires en provenance d'un miroir PyPi privé et ne peut pas être extrait par un job Cloud Build distant, essayez d'utiliser l'option Docker locale ou de créer votre conteneur à l'aide d'un fichier Dockerfile.

  • Si le job Cloud Build échoue avec le code de sortie docker exit code 137, le job de compilation est à court de mémoire, potentiellement en raison de la taille des dépendances en cours d'installation. Utilisez un type de machine de nœud de calcul Cloud Build plus grand en transmettant --cloud_build_machine_type=machine_type, où machine_type est l'une des options suivantes :

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

    Par défaut, Cloud Build utilise le type de machine e2-medium.

  • Dans Apache Beam 2.44.0 et versions ultérieures, les nœuds de calcul créent un environnement virtuel lors du démarrage d'un conteneur personnalisé. Si le conteneur crée son propre environnement virtuel pour installer des dépendances, celles-ci sont supprimées. Ce comportement peut entraîner des erreurs, telles que les suivantes :

    ModuleNotFoundError: No module named '<dependency name>'

    Pour éviter ce problème, installez les dépendances dans l'environnement Python (global) par défaut. Pour contourner ce problème, désactivez ce comportement dans Beam 2.48.0 et versions ultérieures en définissant la variable d'environnement suivante dans votre image de conteneur :

    ENV RUN_PYTHON_SDK_IN_DEFAULT_ENVIRONMENT=1

Étapes suivantes