容器環境

Beam SDK 執行階段環境可以使用 容器化,並透過 Docker 來隔離它與其他執行階段系統。若要進一步了解容器環境,請閱讀 Beam SDK Harness 容器合約

預先建置的 SDK 容器映像會根據 Beam 版本發行時每個支援的語言來推送至 Docker Hub

自訂容器

您可能因為許多原因而想要自訂容器映像,包括

本指南說明如何為 Beam SDK 建立和使用自訂容器。

先決條件

注意:在 2020 年 11 月 20 日,Docker Hub 對於匿名和免費驗證使用實施了 速率限制,這可能會影響多次提取容器的較大型管線。

為了獲得最佳的使用者體驗,我們也建議您使用最新發行的 Beam 版本。

建立並推送自訂容器

Beam SDK 容器映像是根據簽入 Github 儲存庫的 Dockerfile 所建立,並針對每個版本發佈到 Docker Hub。您可以使用以下三種方式之一來建立自訂容器

  1. 根據已發行的容器映像撰寫新的 Dockerfile。這足以對映像進行簡單的加入,例如新增成品或環境變數。
  2. 修改 Beam 中的來源 Dockerfile。此方法需要從 Beam 來源建置,但允許對容器進行更大的自訂 (包括替換成品或基礎作業系統/語言版本)。
  3. 修改現有的容器映像以使其與 Apache Beam 執行器相容。當使用者從現有的映像開始,並將映像設定為與 Apache Beam 執行器相容時,會使用此方法。

根據現有已發佈的容器映像撰寫新的 Dockerfile

  1. 使用 FROM 指令建立指定基礎映像的新 Dockerfile。
FROM apache/beam_python3.7_sdk:2.25.0

ENV FOO=bar
COPY /src/path/to/file /dest/path/to/file/

這個 Dockerfile 使用標記為 (SDK 版本) 2.25.0 的預先建置 Python 3.7 SDK 容器映像 beam_python3.7_sdk,並將額外的環境變數和檔案新增至映像。

  1. 使用 Docker 建置推送 映像。
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}" .
  1. 如果您的執行器在遠端執行,請重新標記映像並將其 推送 到適當的儲存庫。
docker push "${IMAGE_NAME}:${TAG}"
  1. 推送容器映像之後,請驗證遠端映像 ID 和摘要與 docker builddocker images 的輸出中的本機映像 ID 和摘要相符。

修改 Beam 中的來源 Dockerfile

此方法需要從 Beam 來源建置映像成品。如需設定開發環境的其他指示,請參閱貢獻指南

注意:建議您從與執行管線的 SDK 版本相同的穩定發行分支 (release-X.XX.X) 開始。SDK 版本中的差異可能會導致意外的錯誤。

  1. 複製 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
  1. 自訂給定語言的 Dockerfile,通常位於 sdks/<language>/container/Dockerfile 目錄中 (例如,Python 的 Dockerfile)。

  2. 返回根 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
  1. 執行 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         ...
  1. 如果您的執行器在遠端執行,請重新標記映像並將其 推送 到您的儲存庫。如果您以其他參數提供自訂儲存庫/標記,則可以跳過此步驟。
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}"
  1. 推送容器映像之後,請驗證遠端映像 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 Runner 相容的新自訂映像檔最簡單的方法是使用多階段建置程序。這會將必要的成品從預設的 Apache Beam 基本映像檔複製過來,以建置您的自訂容器映像檔。

  1. 將必要的成品從 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 相依性,並縮短 Worker 的啟動時間。RUN 指令中指定的版本必須與用於啟動管道的版本相符。
請確保基本映像檔中指定的 Python 或 Java 執行階段版本與用於執行管道的版本相同。

注意:任何額外的 Python 相依性都應安裝在自訂映像檔的全域 Python 環境中。

  1. 使用 Docker 建置推送 映像。
  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}" .
  1. 如果您的 Runner 是遠端執行,請重新標記映像檔並將映像檔推送到您的儲存庫。
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,由 Portable Runner 或支援 PortableRunner 旗標的 Runner 支援。其他 Runner(例如 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 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 管道時遇到意外錯誤時,需要考慮的一些常見問題。