在 Dataflow 中使用自定义容器

本页面介绍如何通过提供自定义容器映像来自定义 Dataflow 流水线中的 Python 用户代码的运行时环境。只有使用 Dataflow Runner v2 的可移植的流水线才支持自定义容器。

Dataflow 在启动工作器虚拟机时,会使用 Docker 容器映像。您可以指定自定义容器映像,而不使用默认的 Apache Beam 映像。您指定自定义容器映像后,Dataflow 会启动拉取指定映像的工作器。以下是您可能需要使用自定义容器的一些原因:

  • 预安装流水线依赖项以减少工作器启动时间。
  • 预安装公共代码库中不提供的流水线依赖项。
  • 在后台启动第三方软件。
  • 自定义执行环境。

如需深入了解自定义容器,请参阅 Apache Beam 自定义容器指南

准备工作

验证您是否安装了 Apache Beam SDK 2.25.0 或更高版本。检查此 Apache Beam SDK 版本是否支持您的 Python 版本。如需了解详情,请参阅安装 Apache Beam SDK 指南。

确保您已安装 Docker 以在本地测试容器映像。如需了解详情,请参阅获取 Docker

创建和构建容器映像

在此示例中,我们使用 Python 3.8 和 Apache Beam SDK 2.25.0 版。要创建自定义容器映像,请将 Apache Beam 映像指定为父映像,并添加您自己的自定义项。

  1. 创建新的 Dockerfile,将 apache/beam_python3.8_sdk:2.25.0 指定为父映像并添加任何自定义项。如需详细了解如何编写 Dockerfile,请参阅编写 Dockerfile 的最佳做法
    FROM apache/beam_python3.8_sdk:2.25.0
    # Make your customizations here, for example:
    ENV FOO=/bar
    COPY path/to/myfile ./
  2. 构建子映像并将此映像推送到 Container Registry。

    Cloud Build

    export PROJECT=PROJECT
    export REPO=REPO
    export TAG=TAG
    export REGISTRY_HOST=HOST
    export IMAGE_URI=$REGISTRY_HOST/$PROJECT/$REPO:$TAG
    
    gcloud builds submit --tag $IMAGE_URI

    Docker

    export PROJECT=PROJECT
    export REPO=REPO
    export TAG=TAG
    export REGISTRY_HOST=HOST
    export IMAGE_URI=$REGISTRY_HOST/$PROJECT/$REPO:$TAG
    
    docker build -f Dockerfile -t $IMAGE_URI ./
    docker push $IMAGE_URI
    请替换以下内容:
    • PROJECT:项目名称或用户名。
    • REPO:映像代码库名称。
    • TAG:映像标记。
    • HOST:映像注册表主机名,例如 gcr.io

使用自定义容器运行作业

运行流水线时,请使用自定义容器映像中所包含的 Python 版本和 Apache Beam SDK 版本,以避免意外错误。

在本地测试

使用 PortableRunner 运行 Apache Beam wordcount 示例,在本地测试容器映像:

python -m apache_beam.examples.wordcount \
  --input=INPUT_FILE \
  --output=OUTPUT_FILE \
  --runner=PortableRunner \
  --job_endpoint=embed \
  --environment_type=DOCKER \
  --environment_config=$IMAGE_URI

请替换以下内容:

  • INPUT_FILE:可以读取为文本文件的输入文件。此文件必须可供 SDK 自动化框架的
    容器映像访问,它已预加载到容器映像中或者是一个远程文件。
  • OUTPUT_FILE:要将输出写入其中的文件路径。此路径可以是远程路径,也可以是容器上的本地路径。
  • $IMAGE_URI:自定义容器映像 URI。如果上一步中构建的 shell 变量 $IMAGE_URI 仍然在适用范围内,您可以使用该变量。

流水线成功完成后,查看控制台日志以验证流水线是否成功完成以及是否使用了由 $IMAGE_URI 指定的远程映像

此本地测试旨在验证实际的容器映像本身。流水线本身应该在本步骤之前在没有容器映像的情况下进行验证,例如,使用 DirectRunner 来验证。容器的隔离特性阻止访问本地文件系统和环境变量等本地配置。

这意味着容器本身无法访问本地输入文件或凭据文件以及本地环境变量,例如用于设置应用默认凭据的环境变量。本地输出将会写入容器文件系统,并且在容器关闭和流水线运行后便无法访问。

如果需要永久保留这些输出,请提供远程文件系统作为输出路径,并确保在容器本身上设置对此远程文件系统的访问权限。添加临时日志记录对于调试需求也可能已经足够。

如需了解详情,请参阅关于使用自定义容器映像运行流水线的 Apache Beam 指南。

启动 Dataflow 作业

在 Dataflow 上启动 Apache Beam 流水线时,请指定容器映像的路径。如果您要启动批处理 Python 流水线,则必须设置 --experiment=use_runner_v2 标志。如果您要启动流处理 Python 流水线,则无需指定实验。例如,要使用自定义容器映像启动批处理字数统计示例,请使用以下命令:

python -m apache_beam.examples.wordcount \
  --input=INPUT_FILE \
  --output=OUTPUT_FILE \
  --project=PROJECT_ID \
  --region=REGION \
  --temp_location=TEMP_LOCATION \
  --runner=DataflowRunner \
  --experiment=use_runner_v2 \
  --worker_harness_container_image=$IMAGE_URI

请替换以下内容:

  • INPUT_FILE:运行示例时,Dataflow 读取的 Cloud Storage 输入文件路径。
  • OUTPUT_FILE:示例流水线写入的 Cloud Storage 输出文件路径。其中包含字数统计。
  • PROJECT_ID:您的 Google Cloud 项目的 ID。
  • REGION:用于部署 Dataflow 作业的区域端点。
  • TEMP_LOCATION:供 Dataflow 暂存流水线执行期间创建的临时作业文件的 Cloud Storage 路径。
  • $IMAGE_URI:自定义容器映像 URI。如果上一步中构建的 shell 变量 $IMAGE_URI 仍然在适用范围内,您可以使用该变量。

问题排查

本部分提供了相关说明,帮助您排查在 Dataflow 中与自定义容器交互时出现的常见问题。

在联系支持团队之前,请确保您已按照在本地测试和以下问题排查部分中的步骤排除与容器映像相关的问题。

查找容器日志

您可以使用日志浏览器找到与容器相关的错误消息的 Dataflow 工作器日志:

  1. 选择以下日志名称:

    • dataflow.googleapis.com/docker
    • dataflow.googleapis.com/kubelet
    • dataflow.googleapis.com/worker
  2. 选择 Dataflow Step 资源并指定 job_id

工作器无法启动

如果工作器无法启动或作业超时,请验证 Dataflow 能否拉取自定义容器映像。

使用以下查询,通过日志浏览器查询日志消息 Error Syncing pod... 的 Dataflow 日志:

resource.type="dataflow_step" AND jsonPayload.message:("$IMAGE_URI") AND severity="ERROR"

Dataflow 工作器必须能够访问该映像,以便工作器可以在启动时拉取映像。如果您使用 Container Registry 托管容器映像,则默认 Google Cloud 服务帐号已经可以访问同一项目中的映像。如果 Dataflow 无法拉取容器映像,则工作器无法启动。

如需了解详情,请参阅配置访问权限控制