Dataflow를 위한 커스텀 컨테이너 이미지 빌드

이 문서에서는 Dataflow 작업의 커스텀 컨테이너 이미지를 만드는 방법을 설명합니다.

요구사항

Dataflow를 위한 커스텀 컨테이너 이미지는 다음 요구사항을 충족해야 합니다.

  • Apache Beam SDK 및 필요한 종속 항목이 설치되어 있어야 합니다. 기본 Apache Beam SDK 이미지로 시작하는 것이 좋습니다. 자세한 내용은 이 문서에서 기본 이미지 선택을 참조하세요.
  • /opt/apache/beam/boot 스크립트는 컨테이너 시작 중 마지막 단계로 실행되어야 합니다. 이 스크립트는 작업자 환경을 초기화하고 SDK 작업자 프로세스를 시작합니다. 이 스크립트는 Apache Beam SDK 이미지의 기본 ENTRYPOINT입니다. 하지만 다른 기본 이미지를 사용하거나 기본 ENTRYPOINT를 재정의할 경우 스크립트를 명시적으로 실행해야 합니다. 자세한 내용은 이 문서에서 컨테이너 진입점 수정을 참조하세요.
  • 컨테이너 이미지는 Dataflow 작업에 대한 작업자 VM 아키텍처를 지원해야 합니다. ARM VM에서 커스텀 컨테이너를 사용하려면 다중 아키텍처 이미지를 빌드하는 것이 좋습니다. 자세한 내용은 다중 아키텍처 컨테이너 이미지 빌드를 참조하세요.

시작하기 전에

  1. 설치된 Apache Beam SDK 버전이 Runner v2 및 언어 버전을 지원하는지 확인합니다. 자세한 내용은 Apache Beam SDK 설치를 참조하세요.

  2. 컨테이너 이미지를 로컬에서 테스트하려면 Docker를 설치해야 합니다. 자세한 내용은 Docker 가져오기를 참조하세요.

  3. Artifact Registry 저장소를 만듭니다. Docker 이미지 형식을 지정합니다. 저장소에 최소한 Artifact Registry 작성자 액세스 권한이 있어야 합니다.

    새 저장소를 만들려면 gcloud artifacts repositories create 명령어를 실행합니다.

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

    다음을 바꿉니다.

    • REPOSITORY: 저장소 이름입니다. 저장소 이름은 프로젝트의 각 위치에 대해 고유해야 합니다.
    • REGION: Dataflow 작업을 배포할 리전입니다. 명령어를 실행할 위치에 가까운 Dataflow 리전을 선택합니다. 값은 유효한 리전 이름이어야 합니다. 리전과 위치에 대한 자세한 내용은 Dataflow 위치를 참고하세요.

    이 예시에서는 --async 플래그를 사용합니다. 작업이 완료될 때까지 기다리지 않고 명령어가 즉시 결과를 반환합니다.

  4. Artifact Registry에 대해 요청을 인증하도록 Docker를 구성하려면 gcloud auth configure-docker 명령어를 실행합니다.

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

    이 명령어는 Docker 구성을 업데이트합니다. 이제 Google Cloud 프로젝트의 Artifact Registry와 연결하여 이미지를 내보낼 수 있습니다.

기본 이미지 선택

Apache Beam SDK 이미지를 기본 컨테이너 이미지로 사용해서 시작하는 것이 좋습니다. 이러한 이미지는 Docker Hub에 대한 Apache Beam 출시와 함께 제공됩니다.

Apache Beam 기본 이미지 사용

Apache Beam SDK 이미지를 기본 이미지로 사용하려면 FROM 안내의 컨테이너 이미지를 지정한 후 사용자 고유의 맞춤설정을 추가합니다.

자바

이 예시에서는 Apache Beam SDK 버전 2.61.0과 Java 8을 사용합니다.

FROM apache/beam_java8_sdk:2.61.0

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

커스텀 컨테이너의 런타임 버전은 파이프라인을 시작하는 데 사용할 런타임과 일치해야 합니다. 예를 들어 로컬 Java 11 환경에서 파이프라인을 시작하는 경우 FROM 줄은 Java 11 환경을 지정해야 합니다(apache/beam_java11_sdk:...).

Python

이 예시에서는 Apache Beam SDK 버전 2.61.0과 Python 3.10을 사용합니다.

FROM apache/beam_python3.10_sdk:2.61.0

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

커스텀 컨테이너의 런타임 버전은 파이프라인을 시작하는 데 사용할 런타임과 일치해야 합니다. 예를 들어 로컬 Python 3.10 환경에서 파이프라인을 시작하는 경우 FROM 줄은 Python 3.10 환경을 지정해야 합니다(apache/beam_python3.10_sdk:...).

Go

이 예시에서는 Apache Beam SDK 버전 2.61.0과 Go를 사용합니다.

FROM apache/beam_go_sdk:2.61.0

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

커스텀 기본 이미지 사용

다른 기본 이미지를 사용하거나 기본 Apache Beam 이미지의 일부 측면(예: OS 버전 또는 패치)을 수정해야 하는 경우에는 다단계 빌드 프로세스를 사용합니다. 기본 Apache Beam 기본 이미지에서 필요한 아티팩트를 복사합니다.

/opt/apache/beam/boot 스크립트를 실행하도록 ENTRYPOINT를 설정합니다. 그러면 작업자 환경이 초기화되고 SDK 작업자 프로세스가 시작됩니다. 이 진입점을 설정하지 않으면 Dataflow 작업자가 올바르게 시작되지 않습니다.

다음 예시에서는 Apache Beam SDK에서 파일을 복사하는 Dockerfile을 보여줍니다.

자바

FROM openjdk:8

# Copy files from official SDK image, including script/dependencies.
COPY --from=apache/beam_java8_sdk:2.61.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.61.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.61.0 /opt/apache/beam /opt/apache/beam

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

이 예시에서는 필요한 종속 항목(이 경우 Python 3.10 및 pip)이 기존 기본 이미지에 설치되어 있다고 가정합니다. Apache Beam SDK를 이미지에 설치하면 이미지에 필요한 SDK 종속 항목이 포함되며 작업자 시작 시간이 줄어듭니다.

중요: RUNCOPY 안내에 지정된 SDK 버전은 파이프라인을 실행하는 데 사용된 버전과 일치해야 합니다.

Go

FROM golang:latest

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

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

컨테이너 진입점 수정

컨테이너가 컨테이너 시작 중 커스텀 스크립트를 실행하는 경우 스크립트가 /opt/apache/beam/boot 실행으로 종료되어야 합니다. 컨테이너 시작 중 Dataflow에서 전달된 인수는 기본 부팅 스크립트에 전달되어야 합니다. 다음 예시는 기본 부팅 스크립트를 호출하는 커스텀 시작 스크립트를 보여줍니다.

#!/bin/bash

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

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

Dockerfile에서 스크립트를 호출하도록 ENTRYPOINT를 설정합니다.

자바

FROM apache/beam_java8_sdk:2.61.0

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

Python

FROM apache/beam_python3.10_sdk:2.61.0

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

Go

FROM apache/beam_go_sdk:2.61.0

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

이미지 빌드 및 푸시

Cloud Build 또는 Docker를 사용해서 컨테이너 이미지를 빌드하고 Artifact Registry 저장소에 푸시합니다.

Cloud Build

파일을 빌드하고 Artifact Registry 저장소에 푸시하려면 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

다음을 바꿉니다.

  • REGION: Dataflow 작업을 배포할 리전입니다. REGION 변수 값은 유효한 리전 이름이어야 합니다.
  • PROJECT_ID: 프로젝트 이름 또는 사용자 이름입니다.
  • REPOSITORY: 이미지 저장소 이름입니다.
  • FILE_NAME: Dockerfile의 이름입니다.
  • TAG: 이미지 태그입니다. 항상 버전이 지정된 컨테이너 SHA 또는 태그를 지정합니다. :latest 태그 또는 변경 가능한 태그를 사용하지 마세요.

Python 종속 항목 사전 설치

이 섹션은 Python 파이프라인에 적용됩니다.

Python Dataflow 작업을 실행할 때는 런타임에 --requirements_file 또는 --extra_packages 옵션을 사용해서 추가적인 종속 항목을 지정할 수 있습니다. 자세한 내용은 Python 파이프라인 종속 항목 관리를 참조하세요. 추가 종속 항목은 각 Dataflow 작업자 컨테이너에 설치됩니다. 작업이 처음 시작될 때 그리고 자동 확장 중에 종속 항목 설치는 새로 시작된 모든 Dataflow 작업자에서 높은 CPU 사용량과 긴 준비 기간으로 이어지는 경우가 많습니다.

반복적인 종속 항목 설치를 방지하려면 종속 항목이 사전 설치되어 있는 커스텀 Python SDK 컨테이너 이미지를 사전 빌드할 수 있습니다. 이 단계는 빌드 시에 Dockerfile을 사용해서 수행하거나 런타임에 작업을 제출할 때 수행할 수 있습니다.

작업자는 컨테이너를 시작할 때 새로운 가상 Python 환경을 만듭니다. 이러한 이유로 가상 환경을 만드는 대신 종속 항목을 기본(전역) Python 환경에 설치합니다. 컨테이너 이미지에서 가상 환경을 활성화하면 작업이 시작될 때 이 환경이 활성화되지 않을 수 있습니다. 자세한 내용은 일반적인 문제를 참조하세요.

Dockerfile을 사용하여 사전 설치

Python 커스텀 컨테이너에 직접 종속 항목을 추가하려면 다음 명령어를 사용합니다.

FROM apache/beam_python3.10_sdk:2.61.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

--sdk_container_image--sdk_location 파이프라인 옵션을 사용하여 작업을 제출합니다. --sdk_location 옵션은 작업 시작 시 SDK가 다운로드되지 않도록 합니다. SDK가 컨테이너 이미지에서 직접 검색됩니다.

다음 예시에서는 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

다음을 바꿉니다.

  • INPUT_FILE: 파이프라인의 입력 파일입니다.
  • OUTPUT_FILE: 출력을 기록할 경로입니다.
  • PROJECT_ID: Google Cloud 프로젝트 ID입니다.
  • REGION: Dataflow 작업을 배포할 리전입니다.
  • TEMP_LOCATION: 임시 작업 파일을 스테이징할 Dataflow의 Cloud Storage 경로입니다.
  • IMAGE_URI: 커스텀 컨테이너 이미지 URI입니다.

작업 제출 시 컨테이너 이미지 사전 빌드

컨테이너 이미지를 사전 빌드하면 작업 시작 전에 파이프라인 종속 항목을 사전 설치할 수 있습니다. 커스텀 컨테이너 이미지를 빌드할 필요가 없습니다.

작업을 제출할 때 추가적인 Python 종속 항목으로 컨테이너를 사전 빌드하려면 다음 파이프라인 옵션을 사용합니다.

  • --prebuild_sdk_container_engine=[cloud_build | local_docker]. 이 플래그를 설정하면 Apache Beam이 커스텀 컨테이너를 생성하고 --requirements_file--extra_packages 옵션으로 지정된 모든 종속 항목을 설치합니다. 이 플래그는 다음 값을 지원합니다.

    • cloud_build. Cloud Build를 사용해서 컨테이너를 빌드합니다. 프로젝트에서 Cloud Build API를 사용 설정해야 합니다.
    • local_docker. 로컬 Docker 설치를 사용해서 컨테이너를 빌드합니다.
  • --docker_registry_push_url=IMAGE_PATH. IMAGE_PATH를 Artifact Registry 폴더로 바꿉니다.

  • --sdk_location=container. 이 옵션은 작업 실행 시 작업자가 SDK를 다운로드하지 않도록 방지합니다. 대신 SDK가 컨테이너 이미지에서 직접 검색됩니다.

다음 예시는 Cloud Build를 사용해서 이미지를 사전 빌드합니다.

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

사전 빌드 기능을 위해서는 Python용 Apache Beam SDK 버전 2.25.0 이상이 필요합니다.

SDK 컨테이너 이미지 사전 빌드 워크플로에서는 --sdk_container_image 파이프라인 옵션을 사용하여 전달된 이미지를 기본 이미지로 사용합니다. 이 옵션이 설정되어 있지 않으면 기본적으로 Apache Beam 이미지가 기본 이미지로 사용됩니다.

동일한 종속 항목 및 SDK 버전을 포함하는 사전 빌드된 Python SDK 컨테이너 이미지를 다른 작업에 재사용할 수 있습니다. 이미지를 재사용하려면 --sdk_container_image 파이프라인 옵션을 사용하여 사전 빌드된 컨테이너 이미지 URL을 다른 작업에 전달합니다. --requirements_file, --extra_packages, --setup_file 종속 항목 옵션을 삭제합니다.

이미지를 다시 사용하지 않으려면 작업이 완료된 후 이미지를 삭제합니다. gcloud CLI를 사용하거나 Google Cloud 콘솔의 Artifact Registry 페이지에서 이미지를 삭제할 수 있습니다.

이미지가 Artifact Registry에 저장되어 있으면 artifacts docker images delete 명령어를 사용하세요.

   gcloud artifacts docker images delete IMAGE --delete-tags

일반적인 문제

  • 작업에 비공개 PyPi 미러의 추가 Python 종속 항목이 있고 원격 Cloud Build 작업으로 가져올 수 없는 경우 로컬 Docker 옵션을 사용하거나 Dockerfile을 사용하여 컨테이너를 빌드해 보세요.

  • Cloud Build 작업이 docker exit code 137로 인해 실패하는 경우 빌드 작업의 메모리가 부족하다는 의미이며, 설치되는 종속 항목의 크기로 인해 발생했을 가능성이 있습니다. --cloud_build_machine_type=machine_type을 전달하여 더 큰 Cloud Build 작업자 머신 유형을 사용합니다. 여기서 machine_type은 다음 옵션 중 하나입니다.

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

    기본적으로 Cloud Build는 머신 유형 e2-medium을 사용합니다.

  • Apache Beam 2.44.0 이상에서 작업자는 커스텀 컨테이너를 시작할 때 가상 환경을 만듭니다. 컨테이너에서 자체 가상 환경을 만들어 종속 항목을 설치하면 해당 종속 항목은 삭제됩니다. 이 동작으로 인해 다음과 같은 오류가 발생할 수 있습니다.

    ModuleNotFoundError: No module named '<dependency name>'

    이 문제를 방지하려면 종속 항목을 기본(전역) Python 환경에 설치합니다. 이 문제를 해결하려면 컨테이너 이미지에 다음 환경 변수를 설정하여 Beam 2.48.0 이상에서 이 동작을 중지합니다.

    ENV RUN_PYTHON_SDK_IN_DEFAULT_ENVIRONMENT=1

다음 단계