Requisitos
Una imagen de contenedor personalizada para Dataflow debe cumplir los siguientes requisitos:
- El SDK de Apache Beam y las dependencias necesarias están instalados. Te recomendamos que empieces con una imagen predeterminada del SDK de Apache Beam. Para obtener más información, consulta la sección Seleccionar una imagen base de este documento.
- La secuencia de comandos
/opt/apache/beam/boot
debe ejecutarse como último paso durante el inicio del contenedor. Esta secuencia de comandos inicializa el entorno del trabajador e inicia el proceso del trabajador del SDK. Esta secuencia de comandos es laENTRYPOINT
predeterminada en las imágenes del SDK de Apache Beam. Sin embargo, si usas otra imagen base o anulas el valor predeterminadoENTRYPOINT
, debes ejecutar la secuencia de comandos explícitamente. Para obtener más información, consulta Modificar el punto de entrada del contenedor en este documento. - La imagen de contenedor debe admitir la arquitectura de las VMs de trabajador de tu trabajo de Dataflow. Si tiene previsto usar el contenedor personalizado en máquinas virtuales ARM, le recomendamos que cree una imagen de varias arquitecturas. Para obtener más información, consulta Crear una imagen de contenedor de varias arquitecturas.
Antes de empezar
Verifica que la versión del SDK de Apache Beam instalada sea compatible con Runner v2 y con la versión de tu idioma. Para obtener más información, consulta Instalar el SDK de Apache Beam.
Para probar tu imagen de contenedor de forma local, debes tener instalado Docker. Para obtener más información, consulta Descargar Docker.
Crea un repositorio de Artifact Registry. Especifica el formato de la imagen Docker. Debe tener al menos acceso de escritura de Artifact Registry al repositorio.
Para crear un repositorio, ejecuta el comando
gcloud artifacts repositories create
:gcloud artifacts repositories create REPOSITORY \ --repository-format=docker \ --location=REGION \ --async
Haz los cambios siguientes:
- REPOSITORY: un nombre para tu repositorio. Los nombres de los repositorios deben ser únicos en cada ubicación de un proyecto.
- REGION: la región en la que se desplegará tu trabajo de Dataflow. Selecciona una región de Dataflow cercana a la ubicación en la que ejecutas los comandos. El valor debe ser un nombre de región válido. Para obtener más información sobre las regiones y las ubicaciones, consulta el artículo sobre ubicaciones de Dataflow.
En este ejemplo se usa la marca
--async
. El comando se devuelve inmediatamente, sin esperar a que se complete la operación.Para configurar Docker de forma que autentique las solicitudes de Artifact Registry, ejecuta el comando
gcloud auth configure-docker
:gcloud auth configure-docker REGION-docker.pkg.dev
El comando actualiza tu configuración de Docker. Ahora puede conectarse a Artifact Registry en su Google Cloud proyecto para enviar imágenes.
Selecciona una imagen base
Te recomendamos que empieces con una imagen del SDK de Apache Beam como imagen de contenedor base. Estas imágenes se publican como parte de las versiones de Apache Beam en Docker Hub.
Usar una imagen base de Apache Beam
Para usar una imagen del SDK de Apache Beam como imagen base, especifica la imagen del contenedor en la instrucción FROM
y, a continuación, añade tus propias personalizaciones.
Java
En este ejemplo se usa Java 8 con la versión 2.67.0 del SDK de Apache Beam.
FROM apache/beam_java8_sdk:2.67.0
# Make your customizations here, for example:
ENV FOO=/bar
COPY path/to/myfile ./
La versión del tiempo de ejecución del contenedor personalizado debe coincidir con el tiempo de ejecución que utilizarás para iniciar la canalización. Por ejemplo, si vas a iniciar la canalización desde un entorno local de Java 11, la línea FROM
debe especificar un entorno de Java 11: apache/beam_java11_sdk:...
.
Python
En este ejemplo se usa Python 3.10 con la versión 2.67.0 del SDK de Apache Beam.
FROM apache/beam_python3.10_sdk:2.67.0
# Make your customizations here, for example:
ENV FOO=/bar
COPY path/to/myfile ./
La versión del tiempo de ejecución del contenedor personalizado debe coincidir con el tiempo de ejecución que utilizarás para iniciar la canalización. Por ejemplo, si vas a iniciar la canalización desde un entorno local de Python 3.10, la línea FROM
debe especificar un entorno de Python 3.10:
apache/beam_python3.10_sdk:...
.
Go
En este ejemplo se usa Go con la versión 2.67.0 del SDK de Apache Beam.
FROM apache/beam_go_sdk:2.67.0
# Make your customizations here, for example:
ENV FOO=/bar
COPY path/to/myfile ./
Usar una imagen base personalizada
Si quiere usar otra imagen base o modificar algún aspecto de las imágenes predeterminadas de Apache Beam (como la versión del SO o los parches), utilice un proceso de compilación multietapa. Copia los artefactos necesarios de una imagen base predeterminada de Apache Beam.
Define ENTRYPOINT
para ejecutar la secuencia de comandos /opt/apache/beam/boot
, que inicializa el entorno del trabajador e inicia el proceso del trabajador del SDK. Si no defines este punto de entrada, los trabajadores de Dataflow no se iniciarán correctamente.
En el siguiente ejemplo se muestra un archivo Dockerfile que copia archivos del SDK de Apache Beam:
Java
FROM openjdk:8
# Copy files from official SDK image, including script/dependencies.
COPY --from=apache/beam_java8_sdk:2.67.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.67.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.67.0 /opt/apache/beam /opt/apache/beam
# Set the entrypoint to Apache Beam SDK launcher.
ENTRYPOINT ["/opt/apache/beam/boot"]
En este ejemplo se presupone que se han instalado las dependencias necesarias (en este caso, Python 3.10 y pip
) en la imagen base. Instalar el SDK de Apache Beam en la imagen asegura que esta tenga las dependencias del SDK necesarias y reduce el tiempo de inicio del trabajador.
Importante: La versión del SDK especificada en las instrucciones de RUN
y COPY
debe coincidir con la versión utilizada para iniciar la canalización.
Go
FROM golang:latest
# Copy files from official SDK image, including script/dependencies.
COPY --from=apache/beam_go_sdk:2.67.0 /opt/apache/beam /opt/apache/beam
# Set the entrypoint to Apache Beam SDK launcher.
ENTRYPOINT ["/opt/apache/beam/boot"]
Modificar el punto de entrada del contenedor
Si tu contenedor ejecuta una secuencia de comandos personalizada durante el inicio del contenedor, la secuencia de comandos debe terminar con la ejecución de /opt/apache/beam/boot
. Los argumentos que transmite Dataflow durante el inicio del contenedor deben transmitirse a la secuencia de comandos de arranque predeterminada. En el siguiente ejemplo se muestra una secuencia de comandos de inicio personalizada que llama a la secuencia de comandos de arranque predeterminada:
#!/bin/bash
echo "This is my custom script"
# ...
# Pass command arguments to the default boot script.
/opt/apache/beam/boot "$@"
En tu Dockerfile, define ENTRYPOINT
para llamar a tu secuencia de comandos:
Java
FROM apache/beam_java8_sdk:2.67.0
COPY script.sh path/to/my/script.sh
ENTRYPOINT [ "path/to/my/script.sh" ]
Python
FROM apache/beam_python3.10_sdk:2.67.0
COPY script.sh path/to/my/script.sh
ENTRYPOINT [ "path/to/my/script.sh" ]
Go
FROM apache/beam_go_sdk:2.67.0
COPY script.sh path/to/my/script.sh
ENTRYPOINT [ "path/to/my/script.sh" ]
Crea y envía la imagen
Puedes usar Cloud Build o Docker para compilar tu imagen de contenedor y enviarla a un repositorio de Artifact Registry.
Cloud Build
Para compilar el archivo y enviarlo a tu repositorio de Artifact Registry, ejecuta el 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
Haz los cambios siguientes:
REGION
: la región en la que se desplegará la tarea de Dataflow. El valor de la variableREGION
debe ser un nombre de región válido.PROJECT_ID
: el nombre del proyecto o el nombre de usuario.REPOSITORY
: el nombre del repositorio de imágenes.FILE_NAME
: el nombre de tu Dockerfile.TAG
: la etiqueta de imagen. Especifica siempre un SHA o una etiqueta de contenedor con versión. No uses la etiqueta:latest
ni una etiqueta mutable.
Preinstalar dependencias de Python
Esta sección se aplica a las canalizaciones de Python.
Cuando inicias una tarea de Dataflow de Python, puedes especificar dependencias adicionales mediante la opción --requirements_file
o --extra_packages
en el tiempo de ejecución. Para obtener más información, consulta Gestión de dependencias de flujos de trabajo de Python.
Se instalan dependencias adicionales en cada contenedor de trabajador de Dataflow. Cuando se inicia la tarea por primera vez y durante el escalado automático, la instalación de dependencias suele provocar un uso elevado de la CPU y un periodo de calentamiento prolongado en todos los trabajadores de Dataflow que se hayan iniciado recientemente.
Para evitar instalaciones repetitivas de dependencias, puedes crear previamente una imagen de contenedor del SDK de Python personalizada con las dependencias preinstaladas. Puedes realizar este paso en tiempo de compilación mediante un archivo Dockerfile o en tiempo de ejecución al enviar el trabajo.
Los workers crean un nuevo entorno virtual de Python cuando inician el contenedor. Por este motivo, instala las dependencias en el entorno de Python predeterminado (global) en lugar de crear un entorno virtual. Si activas un entorno virtual en tu imagen de contenedor, es posible que este entorno no se active cuando se inicie el trabajo. Para obtener más información, consulta Problemas habituales.
Preinstalar mediante un Dockerfile
Para añadir dependencias adicionales directamente a tu contenedor personalizado de Python, usa los siguientes comandos:
FROM apache/beam_python3.10_sdk:2.67.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
Envía el trabajo con las opciones de canalización --sdk_container_image
y --sdk_location
.
La opción --sdk_location
evita que el SDK se descargue cuando se inicie el trabajo.
El SDK se obtiene directamente de la imagen del contenedor.
En el siguiente ejemplo se ejecuta la pipeline de ejemplo 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
Haz los cambios siguientes:
- INPUT_FILE: un archivo de entrada para el flujo de procesamiento
- OUTPUT_FILE: ruta en la que escribir la salida.
- PROJECT_ID: el ID de proyecto de Google Cloud Platform
- REGION: la región en la que se desplegará tu tarea de Dataflow
- TEMP_LOCATION: la ruta de Cloud Storage para que Dataflow almacene los archivos de trabajo temporales
- IMAGE_URI: el URI de la imagen de contenedor personalizada
Crear una imagen de contenedor antes de enviar el trabajo
Si compilas una imagen de contenedor previamente, podrás preinstalar las dependencias de la canalización antes de que se inicie el trabajo. No es necesario que cree una imagen de contenedor personalizada.
Para precompilar un contenedor con dependencias de Python adicionales al enviar un trabajo, usa las siguientes opciones de canalización:
--prebuild_sdk_container_engine=[cloud_build | local_docker]
. Cuando se define esta marca, Apache Beam genera un contenedor personalizado e instala todas las dependencias especificadas por las opciones--requirements_file
y--extra_packages
. Esta marca admite los siguientes valores:cloud_build
. Usa Cloud Build para compilar el contenedor. La API de Cloud Build debe estar habilitada en tu proyecto.local_docker
. Usa tu instalación local de Docker para compilar el contenedor.
--docker_registry_push_url=IMAGE_PATH
. SustituyeIMAGE_PATH
por una carpeta de Artifact Registry.--sdk_location=container
. Esta opción impide que los trabajadores descarguen el SDK cuando se inicie el trabajo. En su lugar, el SDK se obtiene directamente de la imagen del contenedor.
En el siguiente ejemplo se usa Cloud Build para precompilar la imagen:
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 función de compilación previa requiere la versión 2.25.0 o una posterior del SDK de Apache Beam para Python.
El flujo de trabajo de precompilación de la imagen de contenedor del SDK usa la imagen transferida mediante la opción de canalización --sdk_container_image
como imagen base. Si no se define la opción, se usará una imagen de Apache Beam como imagen base de forma predeterminada.
Puedes reutilizar una imagen de contenedor de SDK de Python precompilada en otro trabajo con las mismas dependencias y versión del SDK.
Para reutilizar la imagen, pasa la URL de la imagen de contenedor prediseñada al otro trabajo
mediante la opción de canalización --sdk_container_image
. Quita las opciones de dependencia --requirements_file
, --extra_packages
y --setup_file
.
Si no tienes previsto volver a usar la imagen, elimínala cuando se complete el trabajo. Puede eliminar la imagen con la CLI de gcloud o en las páginas de Artifact Registry de la Google Cloud consola.
Si la imagen está almacenada en Artifact Registry, usa el comando artifacts docker images delete
:
gcloud artifacts docker images delete IMAGE --delete-tags
Problemas más comunes
Si tu trabajo tiene dependencias de Python adicionales de un mirror privado de PyPi y no se puede extraer mediante un trabajo de Cloud Build remoto, prueba a usar la opción de Docker local o a compilar el contenedor con un Dockerfile.
Si la tarea de Cloud Build falla con el error
docker exit code 137
, significa que se ha quedado sin memoria, posiblemente debido al tamaño de las dependencias que se están instalando. Usa un tipo de máquina de trabajador de Cloud Build más grande. Para ello, pasa--cloud_build_machine_type=machine_type
, donde machine_type es una de las siguientes opciones:n1-highcpu-8
n1-highcpu-32
e2-highcpu-8
e2-highcpu-32
De forma predeterminada, Cloud Build usa el tipo de máquina
e2-medium
.En Apache Beam 2.44.0 y versiones posteriores, los trabajadores crean un entorno virtual al iniciar un contenedor personalizado. Si el contenedor crea su propio entorno virtual para instalar las dependencias, estas se descartarán. Este comportamiento puede provocar errores como los siguientes:
ModuleNotFoundError: No module named '<dependency name>'
Para evitar este problema, instala las dependencias en el entorno de Python predeterminado (global). Como solución alternativa, inhabilita este comportamiento en Beam 2.48.0 y versiones posteriores configurando la siguiente variable de entorno en tu imagen de contenedor:
ENV RUN_PYTHON_SDK_IN_DEFAULT_ENVIRONMENT=1
Siguientes pasos
- Para obtener más información sobre cómo escribir archivos Dockerfile, consulta las prácticas recomendadas para escribir archivos Dockerfile.
- Consulta cómo ejecutar un trabajo de Dataflow en un contenedor personalizado.