Dataflow에서 커스텀 컨테이너 사용

이 페이지에서는 커스텀 컨테이너 이미지를 제공하여 Dataflow 파이프라인에서 사용자 코드의 런타임 환경을 맞춤설정하는 방법을 설명합니다. 커스텀 컨테이너는 Dataflow Runner v2를 사용하는 파이프라인에서 지원됩니다.

Dataflow는 작업자 VM을 시작할 때 Docker 컨테이너 이미지를 사용하여 작업자에서 컨테이너화된 SDK 프로세스를 시작합니다. 기본 Apache Beam 이미지 중 하나를 사용하는 대신 커스텀 컨테이너 이미지를 지정할 수 있습니다. 커스텀 컨테이너 이미지를 지정하면 Dataflow는 지정된 이미지를 가져오는 작업자를 시작합니다. 커스텀 컨테이너를 사용할 수 있는 이유는 다음과 같습니다.

  • 파이프라인 종속 항목을 사전 설치하여 작업자 시작 시간 단축
  • 공개 저장소에서 사용할 수 없는 파이프라인 종속 항목 사전 설치
  • 큰 파일을 미리 스테이징하여 작업자 시작 시간 단축
  • 백그라운드에서 타사 소프트웨어 실행
  • 실행 환경 맞춤설정

커스텀 컨테이너에 대한 상세 설명은 Apache Beam 커스텀 컨테이너 가이드를 참조하세요.

시작하기 전에

Runner v2를 지원하는 Apache Beam SDK 버전과 사용할 언어 버전을 설치했는지 확인합니다.

그리고 나면 다음 파이프라인 옵션을 사용하여 커스텀 컨테이너를 사용 설정할 수 있습니다.

자바

--experiments=use_runner_v2를 사용하여 Runner v2를 사용 설정합니다.

--sdkContainerImage를 사용하여 자바 런타임용 고객 컨테이너 이미지를 지정합니다.

Python

SDK 버전 2.30.0 이상을 사용하는 경우 파이프라인 옵션 --sdk_container_image를 사용합니다.

이전 버전의 SDK에는 파이프라인 옵션 --worker_harness_container_image를 사용합니다.

자세한 내용은 Apache Beam SDK 설치 가이드를 참조하세요.

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

기본 SDK 컨테이너 이미지

처음에는 기본 Apache Beam SDK 이미지를 기본 컨테이너 이미지로 사용하는 것이 좋습니다. 기본 이미지는 DockerHub에 대한 Apache Beam 출시와 함께 제공됩니다.

컨테이너 이미지 만들기 및 빌드

이 섹션에서는 커스텀 SDK 컨테이너 이미지를 만드는 다양한 방법에 대한 예시를 제공합니다.

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

  • Apache Beam SDK 및 필요한 종속 항목가 설치되어 있어야 합니다.
  • 기본 ENTRYPOINT 스크립트(기본 컨테이너의 경우 /opt/apache/beam/boot)는 컨테이너 시작 중에 마지막 단계로 실행됩니다. 자세한 내용은 컨테이너 진입점 수정을 참조하세요.

Apache Beam 기본 이미지 사용

커스텀 컨테이너 이미지를 만들려면 Apache Beam 이미지를 상위 이미지로 지정하고 자체 맞춤설정을 추가합니다. Dockerfile 작성에 대한 자세한 내용은 Dockerfile 작성 권장사항을 참조하세요.

  1. FROM 명령어를 사용하여 기본 이미지를 지정하여 새 Dockerfile을 만듭니다.

    자바

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

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

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

    Python

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

    FROM apache/beam_python3.8_sdk:2.34.0
    
    # Make your customizations here, for example:
    ENV FOO=/bar
    COPY path/to/myfile ./
    

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

  2. 하위 이미지를 빌드하고 이 이미지를 Container Registry에 푸시합니다.

    Cloud Build

    export PROJECT=PROJECT
    export REPO=REPO
    export TAG=TAG
    export IMAGE_URI=gcr.io/$PROJECT/$REPO:$TAG
    gcloud builds submit . --tag $IMAGE_URI
    

    Docker

    export PROJECT=PROJECT
    export REPO=REPO
    export TAG=TAG
    export IMAGE_URI=gcr.io/$PROJECT/$REPO:$TAG
    docker build . --tag $IMAGE_URI
    docker push $IMAGE_URI
    

    다음을 바꿉니다.

    • PROJECT: 프로젝트 이름 또는 사용자 이름
    • REPO: 이미지 저장소 이름
    • TAG: 이미지 태그(일반적으로 latest)

커스텀 기본 이미지 또는 다중 단계 빌드 사용

기존 기본 이미지가 있거나 기본 Apache Beam 이미지의 기본 요소(OS 버전, 패치 등) 중 일부를 수정해야 하는 경우, 다단계 빌드 프로세스를 사용하여 기본 Apache Beam 기본 이미지에서 필요한 아티팩트를 복사하고 커스텀 컨테이너 이미지를 제공합니다.

다음은 Apache Beam SDK에서 파일을 복사하는 Dockerfile의 예시입니다.

자바

FROM openjdk:8

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

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

Python

FROM python:3.8-slim

# Install SDK.
RUN pip install --no-cache-dir apache-beam[gcp]==2.34.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.8_sdk:2.34.0 /opt/apache/beam /opt/apache/beam

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

이 예시에서는 필요한 종속 항목(이 경우 Python 3.8 및 pip)이 기존 기본 이미지에 설치되어 있다고 가정합니다. Apache Beam SDK를 이미지에 설치하면 이미지에 필요한 SDK 종속 항목이 포함되며 작업자 시작 시간이 줄어듭니다. RUN 명령어에 지정된 버전은 파이프라인을 실행하는 데 사용된 버전과 일치해야 합니다.

컨테이너 진입점 수정

커스텀 컨테이너는 작업자 환경을 초기화하고 SDK 작업자 프로세스를 시작하는 기본 ENTRYPOINT 스크립트 /opt/apache/beam/boot를 실행해야 합니다. 이 진입점을 설정하지 않으면 작업자가 제대로 시작되지 않습니다.

컨테이너 시작 시 자체 스크립트를 실행해야 하는 경우 이미지 ENTRYPOINT가 이 작업자 SDK 프로세스를 올바르게 시작하며 이 스크립트에 Dataflow 인수가 전달되는지 확인해야 합니다.

즉 커스텀 ENTRYPOINT는 실행 중인 /opt/apache/beam/boot로 끝내야 하며 컨테이너 시작 시 Dataflow에서 전달하는 모든 필수 인수는 기본 부팅 스크립트에 올바르게 전달됩니다. 이렇게 하려면 /opt/apache/beam/boot를 실행하는 커스텀 스크립트를 만들면 됩니다.

#!/bin/bash

echo "This is my custom script"

# ...

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

그런 다음 기본 ENTRYPOINT를 재정의합니다. 예시 Dockerfile:

자바

FROM apache/beam_java8_sdk:2.34.0

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

Python

FROM apache/beam_python3.8_sdk:2.34.0

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

커스텀 컨테이너를 사용하여 작업 실행

이 섹션에서는 테스트용 로컬 실행기와 Dataflow 모두에서 커스텀 컨테이너로 파이프라인을 실행하는 방법을 설명합니다. 컨테이너 이미지 및 파이프라인을 이미 확인한 경우 Dataflow 작업 실행으로 건너뜁니다.

시작하기 전에

파이프라인을 실행할 때는 커스텀 컨테이너 이미지의 SDK와 동일한 버전 및 언어 버전의 Apache Beam SDK를 사용해야 합니다. 이렇게 하면 호환되지 않는 종속 항목 또는 SDK로 인해 예상치 못한 오류가 발생하지 않습니다.

로컬에서 테스트

Apache Beam 관련 사용 방법에 대한 자세한 내용은 커스텀 컨테이너 이미지로 파이프라인 실행에 대한 Apache Beam 가이드를 참조하세요.

PortableRunner를 사용한 기본 테스트

원격 컨테이너 이미지를 가져올 수 있으며 Apache Beam PortableRunner를 사용하여 간단한 파이프라인을 실행할 수 있는지 확인합니다.

다음은 예시 파이프라인을 실행합니다.

자바

mvn compile exec:java -Dexec.mainClass=com.example.package.MyClassWithMain \
    -Dexec.args="--runner=PortableRunner \
    --job_endpoint=embed \
    --environment_type=DOCKER \
    --environment_config=IMAGE_URI \
    --inputFile=INPUT_FILE \
    --output=OUTPUT_FILE"

Python

python path/to/my/pipeline.py \
  --runner=PortableRunner \
  --job_endpoint=embed \
  --environment_type=DOCKER \
  --environment_config=IMAGE_URI \
  --input=INPUT_FILE \
  --output=OUTPUT_FILE

다음을 바꿉니다.

  • IMAGE_URI: 커스텀 컨테이너 이미지 URI. 변수가 여전히 범위 내에 있는 경우 이전 단계에서 구성된 셸 변수 $IMAGE_URI를 사용할 수 있습니다.
  • INPUT_FILE: 텍스트 파일로 읽을 수 있는 입력 파일. 컨테이너 이미지 또는 원격 파일에 미리 로드된
    SDK 하네스 컨테이너 이미지가 이 파일에 액세스할 수 있어야 합니다.
  • OUTPUT_FILE: 출력을 쓸 파일 경로입니다. 이 경로는 원격 경로 또는 컨테이너의 로컬 경로입니다.

파이프라인이 성공적으로 완료되면 콘솔 로그를 보고 파이프라인이 성공적으로 완료되었는지, $IMAGE_URI로 지정된 원격 이미지가 사용되었는지 확인합니다.

실행 후 컨테이너에 저장된 파일은 로컬 파일 시스템에 존재하지 않으며 컨테이너가 중지됩니다. docker cp를 사용하여 중지된 컨테이너 파일 시스템에서 파일을 복사할 수 있습니다.

다른 방법은 다음과 같습니다.

  • Cloud Storage와 같은 원격 파일 시스템에 출력을 제공합니다. 이를 위해 사용자 인증 정보 파일 또는 애플리케이션 기본 사용자 인증 정보를 포함하여 테스트 목적으로 액세스를 수동 구성해야 할 수 있습니다.
  • 빠른 디버깅을 위해 임시 로깅을 추가합니다.

Direct Runner 사용

컨테이너 이미지와 파이프라인에 대해 심층적인 로컬 테스트를 진행하려면 Apache Beam DirectRunner를 사용합니다.

컨테이너 이미지와 일치하는 로컬 환경에서 테스트하거나 실행 중인 컨테이너에서 파이프라인을 실행하면 컨테이너와 독립적으로 파이프라인을 확인할 수 있습니다.

자바

docker run -it --entrypoint "/bin/bash" $IMAGE_URI
...
# On docker container:
root@4f041a451ef3:/#  mvn compile exec:java -Dexec.mainClass=com.example.package.MyClassWithMain ...

Python

docker run -it --entrypoint "/bin/bash" $IMAGE_URI
...
# On docker container:
root@4f041a451ef3:/#  python path/to/my/pipeline.py ...

이 예시에서는 모든 파이프라인 파일(파이프라인 자체 포함)이 커스텀 컨테이너 자체에 있거나, 로컬 파일 시스템에서 마운트되었거나, Apache Beam 및 컨테이너에서 원격으로 액세스할 수 있다고 가정합니다. 예를 들어 Maven(mvn)을 사용하여 위의 자바 예시를 실행하려면 컨테이너에 스테이징된 Maven 및 종속 항목이 있어야 합니다. 자세한 내용은 스토리지docker run에 대한 Docker 문서를 참조하세요.

DirectRunner 테스트의 목표는 기본 ENTRYPOINT로 컨테이너 실제 실행을 테스트하는 것이 아니라 커스텀 컨테이너 환경에서 파이프라인을 테스트하는 것입니다. ENTRYPOINT(예: docker run --entrypoint ...)를 수정하여 파이프라인을 직접 실행하거나 컨테이너에서 명령어를 수동으로 실행하도록 허용합니다.

Compute Engine에서 실행할 때 특정 구성에 의존하는 경우 이 컨테이너를 Compute Engine VM에서 직접 실행할 수 있습니다. 자세한 내용은 Compute Engine의 컨테이너를 참조하세요.

Dataflow 작업 실행

Dataflow에서 Apache Beam 파이프라인을 시작할 때 아래와 같이 컨테이너 이미지의 경로를 지정합니다.

자바

--sdkContainerImage를 사용하여 자바 런타임용 고객 컨테이너 이미지를 지정합니다.

--experiments=use_runner_v2를 사용하여 Runner v2를 사용 설정합니다.

Python

SDK 버전 2.30.0 이상을 사용하는 경우 파이프라인 옵션 --sdk_container_image를 사용합니다.

이전 버전의 SDK에는 파이프라인 옵션 --worker_harness_container_image를 사용합니다.

커스텀 컨테이너는 Dataflow Runner v2에서만 지원됩니다. 일괄 Python 파이프라인을 실행하는 경우 --experiments=use_runner_v2 플래그를 설정합니다. 스트리밍 Python 파이프라인을 시작하는 경우 스트리밍 Python 파이프라인은 기본적으로 Runner v2를 사용하므로 실험을 지정할 필요가 없습니다.

다음 예시에서는 커스텀 컨테이너로 일괄 wordcount 예시를 실행하는 방법을 보여줍니다.

자바

mvn compile exec:java -Dexec.mainClass=org.apache.beam.examples.WordCount \
   -Dexec.args="--runner=DataflowRunner \
                --inputFile=INPUT_FILE \
                --output=OUTPUT_FILE \
                --project=PROJECT_ID \
                --region=REGION \
                --gcpTempLocation=TEMP_LOCATION \
                --diskSizeGb=DISK_SIZE_GB \
                --experiments=use_runner_v2 \
                --sdkContainerImage=$IMAGE_URI"

Python

Python용 Apache Beam SDK 버전 2.30.0 이상을 사용하는 경우:

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 \
  --sdk_container_image=$IMAGE_URI

다음을 바꿉니다.

  • INPUT_FILE: 예시를 실행할 때 Dataflow가 읽은 Cloud Storage 입력 파일 경로
  • OUTPUT_FILE: 예시 파이프라인에서 기록하는 Cloud Storage 출력 파일 경로입니다. 여기에 단어 수가 포함됩니다.
  • PROJECT_IDGoogle Cloud 프로젝트의 ID
  • REGION: Dataflow 작업을 배포하기 위한 리전 엔드포인트
  • TEMP_LOCATION - 파이프라인 실행 중에 생성된 임시 작업 파일을 스테이징할 Dataflow의 Cloud Storage 경로
  • DISK_SIZE_GB: (선택사항): 컨테이너가 큰 경우 디스크 공간 부족을 방지하기 위해 기본 부팅 디스크 크기를 늘리는 것이 좋습니다.
  • $IMAGE_URI: 커스텀 컨테이너 이미지 URI. 변수가 여전히 범위 내에 있는 경우 이전 단계에서 구성된 셸 변수 $IMAGE_URI를 사용할 수 있습니다.

문제 해결하기

이 섹션에서는 Dataflow에서 커스텀 컨테이너를 사용할 때 발생하는 문제를 해결하는 방법을 안내합니다. 컨테이너나 작업자가 시작되지 않는 문제에 중점을 둡니다. 작업자가 작업을 시작할 수 있고 작업을 진행 중인 경우 파이프라인 문제 해결을 위한 일반 지침을 따르세요.

지원을 요청하기 전에 컨테이너 이미지와 관련된 문제가 없는지 다음과 같이 확인해 보세요.

  • 컨테이너 이미지를 로컬에서 테스트하는 단계를 따릅니다.
  • 작업 로그 또는 작업자 로그에서 오류를 검색하고, 발견된 오류를 일반적인 오류 안내에서 찾아봅니다.
  • 파이프라인을 시작하는 데 사용하는 Apache Beam SDK 버전 및 언어 버전이 커스텀 컨테이너 이미지의 SDK와 일치하는지 확인합니다.
  • 자바를 사용하는 경우 파이프라인을 시작하는 데 사용하는 자바 주 버전이 컨테이너 이미지에 설치된 버전과 일치하는지 확인합니다.
  • Python을 사용하는 경우 파이프라인을 실행하는 데 사용하는 Python 주-부 버전이 컨테이너 이미지에 설치된 버전과 일치하며 이미지에 충돌하는 종속 항목이 없는지 확인합니다. pip check를 실행하여 확인할 수 있습니다.

커스텀 컨테이너와 관련된 작업자 로그 찾기

로그 탐색기를 사용하면 컨테이너 관련 오류 메시지에 대한 Dataflow 작업자 로그를 찾을 수 있습니다.

  1. 로그 이름을 선택합니다. 커스텀 컨테이너 시작 오류는 다음 중 하나에 속할 가능성이 높습니다.

    • dataflow.googleapis.com/docker
    • dataflow.googleapis.com/kubelet
    • dataflow.googleapis.com/worker-startup
  2. Dataflow Step 리소스를 선택하고 job_id를 지정합니다.

특히 Error Syncing pod... 로그 메시지가 표시되는 경우 일반적인 오류 안내를 따라야 합니다. 로그 탐색기에서 다음 쿼리를 사용하면 Dataflow 작업자 로그에서 이러한 로그 메시지를 쿼리할 수 있습니다.

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

일반적인 문제

컨테이너 이미지를 가져올 수 없어 작업에 오류가 있거나 작업이 실패함

Dataflow 작업자가 커스텀 컨테이너 이미지에 액세스할 수 있어야 합니다. 잘못된 URL, 잘못 구성된 사용자 인증 정보 또는 네트워크 액세스 권한 누락으로 인해 작업자가 이미지를 가져올 수 없으면 작업자 시작이 실패합니다.

일괄 작업에서 어떠한 작업도 시작되지 않고 여러 작업자가 순차적으로 시작되지 못하면 Dataflow가 작업을 실패로 처리합니다. 그렇지 않으면 Dataflow는 오류를 로깅하지만 장기 실행 작업 상태를 유지하기 위해 추가적인 조치를 취하지 않습니다.

일반적인 오류 안내에 따라 문제의 원인 및 해결 방법을 찾으세요.

작업자가 시작되지 않거나 작업이 진행되지 않음

오류로 인해 SDK 컨테이너 시작에 실패한 경우, Dataflow에서 오류가 영구적이거나 치명적임을 인식하지 못하고 작업자 재시작을 계속 시도하여 실패가 반복되는 경우가 있습니다.

작업자 로그에서 구체적인 오류를 찾은 후 일반적인 오류 안내를 확인하세요.

명백한 오류는 없지만 dataflow.googleapis.com/kubelet[topologymanager] RemoveContainer INFO 수준 로그가 표시된다면 커스텀 컨테이너 이미지가 일찍 종료되어 장기 실행 작업자 SDK 프로세스가 시작되지 않은 경우입니다. 커스텀 ENTRYPOINT가 기본 부팅 스크립트 /opt/apache/beam/boot를 시작하지 않거나 이 스크립트에 인수를 적절하게 전달하지 않은 경우에 이 문제가 발생할 수 있습니다. 커스텀 ENTRYPOINT 수정을 참조하세요.