容器环境
Beam SDK 运行时环境可以使用 容器化 与 Docker 隔离它与其他运行时系统。要了解有关容器环境的更多信息,请阅读 Beam SDK 运行容器契约。
预构建的 SDK 容器镜像在 Beam 版本发布时根据支持的语言发布并推送到 Docker Hub。
自定义容器
您可能出于多种原因想要自定义容器镜像,包括
- 预安装其他依赖项
- 在工作环境中启动第三方软件
- 进一步自定义执行环境
本指南介绍如何为 Beam SDK 创建和使用自定义容器。
先决条件
- 本指南需要使用 Docker 构建镜像。 在本地安装 Docker。一些 CI/CD 平台(如 Google Cloud Build)还提供使用 Docker 构建镜像的功能。
- 对于远程执行引擎/运行器,请使用容器注册表来托管您的自定义容器镜像。选项包括 Docker Hub 或“自托管”存储库,包括特定于云的容器注册表,如 Google Container Registry (GCR) 或 Amazon Elastic Container Registry (ECR)。确保您的注册表可以被您的执行引擎或运行器访问。
注意:2020 年 11 月 20 日,Docker Hub 对匿名和免费经过身份验证的使用实施了 速率限制,这可能会影响多次拉取容器的大型管道。
为了获得最佳的用户体验,我们还建议您使用 Beam 的最新发布版本。
构建和推送自定义容器
Beam SDK 容器镜像 是从签入 Github 存储库的 Dockerfile 构建的,并在每次发布时发布到 Docker Hub。您可以通过以下三种方式之一构建自定义容器
- 编写新的 基于已发布容器镜像的 Dockerfile。这足以满足对镜像的简单添加,例如添加工件或环境变量。
- 修改 Beam 中的源 Dockerfile。此方法需要从 Beam 源代码构建,但允许更大程度地自定义容器(包括替换工件或基本操作系统/语言版本)。
- 修改 现有容器镜像以使其与 Apache Beam 运行器兼容。当用户从现有镜像开始并配置镜像以使其与 Apache Beam 运行器兼容时,使用此方法。
编写基于现有发布的容器镜像的新 Dockerfile
- 创建一个新的 Dockerfile,使用 FROM 指令 指定基本镜像。
FROM apache/beam_python3.7_sdk:2.25.0
ENV FOO=bar
COPY /src/path/to/file /dest/path/to/file/
此 Dockerfile
使用预构建的 Python 3.7 SDK 容器镜像 beam_python3.7_sdk
,标签为(SDK 版本)2.25.0
,并将其他环境变量和文件添加到镜像中。
export BASE_IMAGE="apache/beam_python3.7_sdk:2.25.0"
export IMAGE_NAME="myremoterepo/mybeamsdk"
# Avoid using `latest` with custom containers to make reproducing failures easier.
export TAG="mybeamsdk-versioned-tag"
# Optional - pull the base image into your local Docker daemon to ensure
# you have the most up-to-date version of the base image locally.
docker pull "${BASE_IMAGE}"
docker build -f Dockerfile -t "${IMAGE_NAME}:${TAG}" .
- 如果您的运行器在远程运行,请重新标记并将镜像 推送到 适当的存储库。
docker push "${IMAGE_NAME}:${TAG}"
- 推送容器镜像后,验证远程镜像 ID 和摘要是否与本地镜像 ID 和摘要匹配,本地镜像 ID 和摘要是在
docker build
或docker images
的输出中。
修改 Beam 中的源 Dockerfile
此方法需要从 Beam 源代码构建镜像工件。有关设置开发环境的更多说明,请参阅 贡献指南。
注意:建议您从与要运行管道的 SDK 版本相同的稳定发布分支 (
release-X.XX.X
) 开始。SDK 版本的不同可能会导致意外错误。
- 克隆
beam
存储库。
export BEAM_SDK_VERSION="2.26.0"
git clone https://github.com/apache/beam.git
cd beam
# Save current directory as working directory
export BEAM_WORKDIR=$PWD
git checkout origin/release-$BEAM_SDK_VERSION
自定义特定语言的
Dockerfile
,通常是sdks/<language>/container/Dockerfile
目录(例如,Python 的 Dockerfile)。返回到根 Beam 目录并运行 Gradle
docker
目标以构建您的镜像。
cd $BEAM_WORKDIR
# The default repository of each SDK
./gradlew :sdks:java:container:java11:docker
./gradlew :sdks:java:container:java17:docker
./gradlew :sdks:java:container:java21:docker
./gradlew :sdks:go:container:docker
./gradlew :sdks:python:container:py39:docker
./gradlew :sdks:python:container:py310:docker
./gradlew :sdks:python:container:py311:docker
./gradlew :sdks:python:container:py312:docker
# Shortcut for building all Python SDKs
./gradlew :sdks:python:container:buildAll
- 通过运行
docker images
验证您构建的镜像是否已创建。
$> docker images --digests
REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
apache/beam_java8_sdk latest sha256:... ... 1 min ago ...
apache/beam_java11_sdk latest sha256:... ... 1 min ago ...
apache/beam_java17_sdk latest sha256:... ... 1 min ago ...
apache/beam_python3.6_sdk latest sha256:... ... 1 min ago ...
apache/beam_python3.7_sdk latest sha256:... ... 1 min ago ...
apache/beam_python3.8_sdk latest sha256:... ... 1 min ago ...
apache/beam_python3.9_sdk latest sha256:... ... 1 min ago ...
apache/beam_python3.10_sdk latest sha256:... ... 1 min ago ...
apache/beam_go_sdk latest sha256:... ... 1 min ago ...
export BEAM_SDK_VERSION="2.26.0"
export IMAGE_NAME="gcr.io/my-gcp-project/beam_python3.7_sdk"
export TAG="${BEAM_SDK_VERSION}-custom"
docker tag apache/beam_python3.7_sdk "${IMAGE_NAME}:${TAG}"
docker push "${IMAGE_NAME}:${TAG}"
- 推送容器镜像后,验证远程镜像 ID 和摘要是否与
docker_images --digests
输出的本地镜像 ID 和摘要匹配。
其他构建参数
docker Gradle 任务定义了默认镜像存储库,并且 标签 是在 gradle.properties 中定义的 SDK 版本。默认存储库是 Docker Hub 的 apache
命名空间,默认标签是在 gradle.properties 中定义的 SDK 版本。
您可以通过向构建任务提供参数来指定构建镜像的不同存储库或标签。例如
./gradlew :sdks:python:container:py36:docker -Pdocker-repository-root="example-repo" -Pdocker-tag="2.26.0-custom"
构建 Python 3.6 容器并将其标记为 example-repo/beam_python3.6_sdk:2.26.0-custom
。
从 Beam 2.21.0 开始,引入了 docker-pull-licenses
标志,用于将第三方依赖项的许可证/通知添加到 docker 镜像中。例如
./gradlew :sdks:java:container:java11:docker -Pdocker-pull-licenses
在 /opt/apache/beam/third_party_licenses/
中创建具有适当许可证的 Java 11 SDK 镜像。
默认情况下,不会将许可证/通知添加到 docker 镜像中。
修改现有容器镜像以使其与 Apache Beam 运行器兼容
Beam 提供了一种使用自定义容器镜像的方法。构建与 Apache Beam 运行器兼容的自定义镜像最简单的方法是使用多阶段构建过程。这将从默认的 Apache Beam 基础镜像中复制必要的工件,以构建您的自定义容器镜像。
- 从 Apache Beam 基础镜像复制必要的工件到您的镜像。
# This can be any container image,
FROM python:3.8-bookworm
# Install SDK. (needed for Python SDK)
RUN pip install --no-cache-dir apache-beam[gcp]==2.52.0
# Copy files from official SDK image, including script/dependencies.
COPY --from=apache/beam_python3.8_sdk:2.52.0 /opt/apache/beam /opt/apache/beam
# Perform any additional customizations if desired
# Set the entrypoint to Apache Beam SDK launcher.
ENTRYPOINT ["/opt/apache/beam/boot"]
注意:此示例假设在现有基础镜像上已经安装了必要的依赖项(在本例中为 Python 3.8 和 pip)。将 Apache Beam SDK 安装到镜像中将确保镜像具有必要的 SDK 依赖项,并减少工作程序启动时间。在
RUN
指令中指定的版本必须与启动管道使用的版本匹配。
确保基础镜像中指定的 Python 或 Java 运行时版本与运行管道使用的版本相同。
注意:任何额外的 Python 依赖项都应该安装在自定义镜像中的全局 Python 环境中。
export BASE_IMAGE="apache/beam_python3.8_sdk:2.52.0"
export IMAGE_NAME="myremoterepo/mybeamsdk"
export TAG="latest"
# Optional - pull the base image into your local Docker daemon to ensure
# you have the most up-to-date version of the base image locally.
docker pull "${BASE_IMAGE}"
docker build -f Dockerfile -t "${IMAGE_NAME}:${TAG}" .
- 如果您的运行器在远程运行,请重新标记镜像并推送镜像到您的仓库。
docker push "${IMAGE_NAME}:${TAG}"
从头开始构建兼容的容器镜像(Go)
从 2.55.0 版本开始,Beam Go SDK 已切换到使用distroless 镜像作为基础。这些镜像通过不包含常见工具和实用程序来减少安全攻击面。这可能会导致使用上述方法之一自定义镜像时出现困难。作为一种回退方法,可以通过构建匹配的引导加载程序并将其设置为容器的入口点,从头开始构建自定义镜像。
例如,如果更倾向于使用 alpine 作为容器操作系统,您的多阶段 docker 文件可能如下所示
FROM golang:latest-alpine AS build_base
# Set the Current Working Directory inside the container
WORKDIR /tmp/beam
# Build the Beam Go bootloader, to the local directory, matching your Beam version.
# Similar go targets exist for other SDK languages.
RUN GOBIN=`pwd` go install github.com/apache/beam/sdks/v2/go/container@v2.53.0
# Set the real base image.
FROM alpine:3.9
RUN apk add ca-certificates
# The following are required for the container to operate correctly.
# Copy the boot loader `container` to the image.
COPY --from=build_base /tmp/beam/container /opt/apache/beam/boot
# Set the container to use the newly built boot loader.
ENTRYPOINT ["/opt/apache/beam/boot"]
如上修改现有基础镜像时一样,构建并推送新镜像。
注意:Java 和 Python 需要额外的依赖项,例如它们的运行时和 SDK 包,才能形成有效的容器镜像。引导加载程序不足以创建这些 SDK 的自定义容器。
使用自定义容器镜像运行管道
提供容器镜像的常见方法需要使用 PortableRunner 标志--environment_config
,如 PortableRunner 或支持 PortableRunner 标志的运行器所支持。其他运行器,例如 Dataflow,支持使用不同的标志指定容器。
export IMAGE="my-repo/beam_python_sdk_custom"
export TAG="X.Y.Z"
export IMAGE_URL="${IMAGE}:${TAG}"
python -m apache_beam.examples.wordcount \
--input=/path/to/inputfile \
--output /path/to/write/counts \
--runner=PortableRunner \
--job_endpoint=embed \
--environment_type="DOCKER" \
--environment_config="${IMAGE_URL}"
export IMAGE="my-repo/beam_python_sdk_custom"
export TAG="X.Y.Z"
export IMAGE_URL = "${IMAGE}:${TAG}"
# Run a pipeline using the FlinkRunner which starts a Flink job server.
python -m apache_beam.examples.wordcount \
--input=/path/to/inputfile \
--output=path/to/write/counts \
--runner=FlinkRunner \
# When running batch jobs locally, we need to reuse the container.
--environment_cache_millis=10000 \
--environment_type="DOCKER" \
--environment_config="${IMAGE_URL}"
export IMAGE="my-repo/beam_python_sdk_custom"
export TAG="X.Y.Z"
export IMAGE_URL = "${IMAGE}:${TAG}"
# Run a pipeline using the SparkRunner which starts the Spark job server
python -m apache_beam.examples.wordcount \
--input=/path/to/inputfile \
--output=path/to/write/counts \
--runner=SparkRunner \
# When running batch jobs locally, we need to reuse the container.
--environment_cache_millis=10000 \
--environment_type="DOCKER" \
--environment_config="${IMAGE_URL}"
export GCS_PATH="gs://my-gcs-bucket"
export GCP_PROJECT="my-gcp-project"
export REGION="us-central1"
# By default, the Dataflow runner has access to the GCR images
# under the same project.
export IMAGE="my-repo/beam_python_sdk_custom"
export TAG="X.Y.Z"
export IMAGE_URL = "${IMAGE}:${TAG}"
# Run a pipeline on Dataflow.
# This is a Python batch pipeline, so to run on Dataflow Runner V2
# you must specify the experiment "use_runner_v2"
python -m apache_beam.examples.wordcount \
--input gs://dataflow-samples/shakespeare/kinglear.txt \
--output "${GCS_PATH}/counts" \
--runner DataflowRunner \
--project $GCP_PROJECT \
--region $REGION \
--temp_location "${GCS_PATH}/tmp/" \
--experiment=use_runner_v2 \
--sdk_container_image=$IMAGE_URL
避免在自定义镜像中使用标签:latest
。使用日期或唯一标识符标记您的构建。如果出现问题,使用这种类型的标签可能会使您能够将管道执行回滚到以前已知的工作配置,并允许您检查更改。
故障排除
以下部分描述了一些在使用自定义容器运行 Beam 管道时遇到意外错误时需要考虑的常见问题。
- 容器 SDK 和管道 SDK 之间的语言和 SDK 版本差异可能会导致由于不兼容而出现意外错误。为了获得最佳效果,请确保为您的基础容器和运行管道时使用相同的稳定 SDK 版本。
- 如果您在使用远程容器时遇到意外错误,请确保您的容器存在于远程仓库中,并且可以被任何第三方服务访问(如果需要)。
- 本地运行器尝试拉取远程镜像,并默认使用本地镜像。如果无法在本地(通过 docker 守护程序)拉取镜像,您可能会看到类似以下的日志消息
Error response from daemon: manifest for remote.repo/beam_python3.7_sdk:2.25.0-custom not found: manifest unknown: ... INFO:apache_beam.runners.portability.fn_api_runner.worker_handlers:Unable to pull image...
最后更新时间:2024/10/31
您是否找到了所有需要的内容?
这些信息是否有用且清晰?您想更改什么内容吗?请告诉我们!