기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
포드 템플릿 사용
Amazon EMR 버전 5.33.0 또는 6.3.0부터 Amazon EMR on EKS는 Spark의 포드 템플릿 기능을 지원합니다. 포드는 공유 스토리지 및 네트워크 리소스가 있는 하나 이상의 컨테이너로 구성된 그룹이자, 컨테이너 실행 방법에 대한 사양입니다. 포드 템플릿은 각 포드의 실행 방법을 결정하는 사양입니다. 포드 템플릿 파일을 사용하여 Spark 구성이 지원하지 않는 드라이버 또는 실행기 포드 구성을 정의할 수 있습니다. Spark의 포드 템플릿 기능에 대한 자세한 내용은 Pod Template
참고
포드 템플릿 기능은 드라이버 및 실행기 포드에서만 작동합니다. 포드 템플릿을 사용하여 작업 제출기 포드를 구성할 수 없습니다.
일반적인 시나리오
Amazon EMR on EKS에서 포드 템플릿을 사용해 공유 EKS 클러스터에서 Spark 작업을 실행하는 방법을 정의하고 비용을 절감하며 리소스 사용률과 성능을 개선할 수 있습니다.
-
비용을 절감하기 위해 Amazon EC2 스팟 인스턴스에서 실행하도록 Spark 실행기 작업을 예약하는 동시에, Amazon EC2 온디맨드 인스턴스에서 실행하도록 Spark 드라이버 작업을 예약할 수 있습니다.
-
리소스 사용률을 높이기 위해 동일한 EKS 클러스터에서 워크로드를 실행하는 여러 팀을 지원할 수 있습니다. 각 팀은 워크로드를 실행하기 위해 지정된 Amazon EC2 노드 그룹을 보유합니다. 포드 템플릿을 사용하여 해당 워크로드에 해당하는 허용 범위를 적용할 수 있습니다.
-
모니터링을 개선하기 위해 별도의 로깅 컨테이너를 실행하여 기존 모니터링 애플리케이션에 로그를 전달할 수 있습니다.
예를 들어, 다음 포드 템플릿 파일은 일반적인 사용 시나리오를 보여줍니다.
apiVersion: v1 kind: Pod spec: volumes: - name: source-data-volume emptyDir: {} - name: metrics-files-volume emptyDir: {} nodeSelector: eks.amazonaws.com/nodegroup: emr-containers-nodegroup containers: - name: spark-kubernetes-driver # This will be interpreted as driver Spark main container env: - name: RANDOM value: "random" volumeMounts: - name: shared-volume mountPath: /var/data - name: metrics-files-volume mountPath: /var/metrics/data - name: custom-side-car-container # Sidecar container image: <side_car_container_image> env: - name: RANDOM_SIDECAR value: random volumeMounts: - name: metrics-files-volume mountPath: /var/metrics/data command: - /bin/sh - '-c' - <command-to-upload-metrics-files> initContainers: - name: spark-init-container-driver # Init container image: <spark-pre-step-image> volumeMounts: - name: source-data-volume # Use EMR predefined volumes mountPath: /var/data command: - /bin/sh - '-c' - <command-to-download-dependency-jars>
포드 템플릿은 다음 작업을 완료합니다.
-
Spark 기본 컨테이너가 시작되기 전에 실행되는 새 init 컨테이너
를 추가합니다. init 컨테이너는 Spark 기본 컨테이너와 EmptyDir 볼륨 ( source-data-volume
)을 공유합니다. init 컨테이너를 통해 종속성 다운로드 또는 입력 데이터 생성과 같은 초기화 단계를 실행할 수 있습니다. 그러면 Spark 기본 컨테이너에서 데이터를 소비합니다. -
Spark 기본 컨테이너와 함께 실행되는 다른 sidecar 컨테이너
를 추가합니다. 두 컨테이너는 다른 EmptyDir
볼륨(metrics-files-volume
)을 공유합니다. Spark 작업은 Prometheus 지표와 같은 지표를 생성할 수 있습니다. 그러면 Spark 작업에서 지표을 파일에 넣고, 향후 분석을 위해 sidecar 컨테이너에서 파일을 자체 BI 시스템에 업로드하게 합니다. -
Spark 기본 컨테이너에 새 환경 변수를 추가합니다. 작업에서 환경 변수를 사용하게 할 수 있습니다.
-
노드 선택기
를 정의합니다. 그러면 포드는 emr-containers-nodegroup
노드 그룹에서만 예약됩니다. 그러면 작업과 팀 사이에서 컴퓨팅 리소스를 분리할 수 있습니다.
Amazon EMR on EKS에서 포드 템플릿 활성화
Amazon EMR on EKS에서 포드 템플릿 기능을 활성화하려면 Amazon S3의 포드 템플릿 파일을 가리키도록 Spark 속성 spark.kubernetes.driver.podTemplateFile
및 spark.kubernetes.executor.podTemplateFile
을 구성합니다. 그러면 Spark는 포드 템플릿 파일을 다운로드하고 이를 사용하여 드라이버 및 실행기 포드를 구성합니다.
참고
Spark는 작업 실행 역할을 사용하여 포드 템플릿을 로드하므로 작업 실행 역할에는 Amazon S3에 액세스하여 포드 템플릿을 로드할 수 있는 권한이 있어야 합니다. 자세한 내용은 작업 실행 역할 생성 단원을 참조하십시오.
다음 작업 실행 JSON 파일에서 볼 수 있듯이 SparkSubmitParameters
를 사용하여 포드 템플릿에 대한 Amazon S3 경로를 지정할 수 있습니다.
{ "name": "myjob", "virtualClusterId": "123456", "executionRoleArn": "iam_role_name_for_job_execution", "releaseLabel": "
release_label
", "jobDriver": { "sparkSubmitJobDriver": { "entryPoint": "entryPoint_location", "entryPointArguments": ["argument1
", "argument2
", ...], "sparkSubmitParameters": "--class <main_class> \ --conf spark.kubernetes.driver.podTemplateFile=s3://path_to_driver_pod_template
\ --conf spark.kubernetes.executor.podTemplateFile=s3://path_to_executor_pod_template
\ --conf spark.executor.instances=2 \ --conf spark.executor.memory=2G \ --conf spark.executor.cores=2 \ --conf spark.driver.cores=1" } } }
또는 다음 작업 실행 JSON 파일에서 볼 수 있듯이 configurationOverrides
를 사용하여 포드 템플릿에 대한 Amazon S3 경로를 지정할 수 있습니다.
{ "name": "myjob", "virtualClusterId": "123456", "executionRoleArn": "iam_role_name_for_job_execution", "releaseLabel": "
release_label
", "jobDriver": { "sparkSubmitJobDriver": { "entryPoint": "entryPoint_location", "entryPointArguments": ["argument1
", "argument2
", ...], "sparkSubmitParameters": "--class <main_class> \ --conf spark.executor.instances=2 \ --conf spark.executor.memory=2G \ --conf spark.executor.cores=2 \ --conf spark.driver.cores=1" } }, "configurationOverrides": { "applicationConfiguration": [ { "classification": "spark-defaults", "properties": { "spark.driver.memory":"2G", "spark.kubernetes.driver.podTemplateFile":"s3://path_to_driver_pod_template
", "spark.kubernetes.executor.podTemplateFile":"s3://path_to_executor_pod_template
" } } ] } }
참고
-
Amazon EMR on EKS에서 포드 템플릿 기능을 사용하는 경우 신뢰할 수 없는 애플리케이션 코드 격리와 같은 보안 지침을 준수해야 합니다. 자세한 내용은 Amazon EMR on EKS 보안 모범 사례 단원을 참조하십시오.
-
Spark 기본 컨테이너 이름은
spark.kubernetes.driver.podTemplateContainerName
및spark.kubernetes.executor.podTemplateContainerName
을 사용하여 변경할 수 없습니다. 해당 이름은spark-kubernetes-driver
및spark-kubernetes-executors
로 하드 코딩되기 때문입니다. Spark 기본 컨테이너를 사용자 지정하려면 이러한 하드 코딩된 이름을 사용하여 포드 템플릿에서 컨테이너를 지정해야 합니다.
포드 템플릿 필드
Amazon EMR on EKS에서 포드 템플릿을 구성할 때는 다음 필드 제한 사항을 고려합니다.
-
Amazon EMR on EKS는 적절한 작업 예약을 지원하기 위해 포드 템플릿에서 다음 필드만 허용합니다.
허용되는 포드 수준 필드는 다음과 같습니다.
-
apiVersion
-
kind
-
metadata
-
spec.activeDeadlineSeconds
-
spec.affinity
-
spec.containers
-
spec.enableServiceLinks
-
spec.ephemeralContainers
-
spec.hostAliases
-
spec.hostname
-
spec.imagePullSecrets
-
spec.initContainers
-
spec.nodeName
-
spec.nodeSelector
-
spec.overhead
-
spec.preemptionPolicy
-
spec.priority
-
spec.priorityClassName
-
spec.readinessGates
-
spec.runtimeClassName
-
spec.schedulerName
-
spec.subdomain
-
spec.terminationGracePeriodSeconds
-
spec.tolerations
-
spec.topologySpreadConstraints
-
spec.volumes
허용되는 Spark 기본 컨테이너 수준 필드는 다음과 같습니다.
-
env
-
envFrom
-
name
-
lifecycle
-
livenessProbe
-
readinessProbe
-
resources
-
startupProbe
-
stdin
-
stdinOnce
-
terminationMessagePath
-
terminationMessagePolicy
-
tty
-
volumeDevices
-
volumeMounts
-
workingDir
포드 템플릿에서 허용되지 않는 필드를 사용하면 Spark에서 예외가 발생하고 작업이 실패합니다. 다음 예제에서는 허용되지 않는 필드로 인해 Spark 컨트롤러 로그에 표시되는 오류 메시지를 보여줍니다.
Executor pod template validation failed. Field container.command in Spark main container not allowed but specified.
-
-
Amazon EMR on EKS에서는 포드 템플릿에서 다음 파라미터를 사전에 정의합니다. 포드 템플릿에서 지정하는 필드는 이 필드와 겹치지 않아야 합니다.
사전 정의된 볼륨 이름은 다음과 같습니다.
-
emr-container-communicate
-
config-volume
-
emr-container-application-log-dir
-
emr-container-event-log-dir
-
temp-data-dir
-
mnt-dir
-
home-dir
-
emr-container-s3
다음은 Spark 기본 컨테이너에만 적용되는 사전 정의된 볼륨 마운트입니다.
-
Name:
emr-container-communicate
, MountPath:/var/log/fluentd
-
Name:
emr-container-application-log-dir
, MountPath:/var/log/spark/user
-
Name:
emr-container-event-log-dir
, MountPath:/var/log/spark/apps
-
Name:
mnt-dir
, MountPath:/mnt
-
Name:
temp-data-dir
, MountPath:/tmp
-
Name:
home-dir
, MountPath:/home/hadoop
다음은 Spark 기본 컨테이너에만 적용되는 사전 정의된 환경 변수입니다.
-
SPARK_CONTAINER_ID
-
K8S_SPARK_LOG_URL_STDERR
-
K8S_SPARK_LOG_URL_STDOUT
-
SIDECAR_SIGNAL_FILE
참고
이러한 사전 정의된 볼륨을 계속 사용하고 추가 sidecar 컨테이너에 마운트할 수 있습니다. 예를 들어
emr-container-application-log-dir
을 사용하고 포드 템플릿에 정의된 sidecar 컨테이너에 이를 마운트할 수 있습니다.지정한 필드가 포드 템플릿의 사전 정의된 필드와 충돌하는 경우 Spark에서 예외가 발생하고 작업이 실패합니다. 다음 예제는 사전 정의된 필드와의 충돌로 인한 Spark 애플리케이션 로그에 표시되는 오류 메시지를 보여줍니다.
Defined volume mount path on main container must not overlap with reserved mount paths: [<reserved-paths>]
-
sidecar 컨테이너 관련 고려 사항
Amazon EMR은 Amazon EMR on EKS에서 프로비저닝하는 포드의 수명 주기를 제어합니다. sidecar 컨테이너는 Spark 기본 컨테이너와 동일한 수명 주기를 따라야 합니다. 추가 sidecar 컨테이너를 포드에 삽입하는 경우 Amazon EMR에서 정의하는 포드 수명 주기 관리와 통합하여 Spark 기본 컨테이너가 종료될 때 sidecar 컨테이너가 자체적으로 중지될 수 있도록 하는 것이 좋습니다.
비용을 줄이려면 작업이 완료된 후 sidecar 컨테이너가 있는 드라이버 포드가 계속 실행되지 않도록 하는 프로세스를 구현하는 것이 좋습니다. Spark 드라이버는 실행기가 완료되면 실행기 포드를 삭제합니다. 하지만 드라이버 프로그램이 완료되어도 추가 sidecar 컨테이너는 계속 실행됩니다. 포드 요금은 Amazon EMR on EKS가 드라이버 포드를 정리할 때까지 청구되며, 일반적으로 드라이버 Spark 기본 컨테이너가 완료된 후 1분 이내에 청구됩니다. 비용을 절감하기 위해 다음 섹션에 설명된 대로 Amazon EMR on EKS에서 이 드라이버 및 실행자 포드 모두에 대해 정의한 수명 주기 관리 메커니즘과 추가 sidecar 컨테이너를 통합할 수 있습니다.
드라이버 및 실행기 포드의 Spark 기본 컨테이너는 2초마다 heartbeat
를 /var/log/fluentd/main-container-terminated
파일에 전송합니다. Amazon EMR의 사전 정의된 emr-container-communicate
볼륨 마운트를 sidecar 컨테이너에 추가하면 sidecar 컨테이너의 하위 프로세스를 정의하여 이 파일의 마지막 수정 시간을 주기적으로 추적할 수 있습니다. 그런 다음, Spark 기본 컨테이너에서 오랫동안 heartbeat
를 중지한 것을 발견하면 하위 프로세스가 저절로 중지됩니다.
다음 예제는 하트비트 파일을 추적하고 자체적으로 중지하는 하위 프로세스를 보여줍니다. your_volume_mount
를 사용자 경로(사전 정의된 볼륨을 마운트한 경로)로 바꿉니다. 스크립트는 sidecar 컨테이너에서 사용하는 이미지 내에 번들로 제공됩니다. 포드 템플릿 파일에서 sub_process_script.sh
및 main_command
명령을 사용하여 sidecar 컨테이너를 지정할 수 있습니다.
MOUNT_PATH="
your_volume_mount
" FILE_TO_WATCH="$MOUNT_PATH/main-container-terminated" INITIAL_HEARTBEAT_TIMEOUT_THRESHOLD=60 HEARTBEAT_TIMEOUT_THRESHOLD=15 SLEEP_DURATION=10 function terminate_main_process() { # Stop main process } # Waiting for the first heartbeat sent by Spark main container echo "Waiting for file $FILE_TO_WATCH to appear..." start_wait=$(date +%s) while ! [[ -f "$FILE_TO_WATCH" ]]; do elapsed_wait=$(expr $(date +%s) - $start_wait) if [ "$elapsed_wait" -gt "$INITIAL_HEARTBEAT_TIMEOUT_THRESHOLD" ]; then echo "File $FILE_TO_WATCH not found after $INITIAL_HEARTBEAT_TIMEOUT_THRESHOLD seconds; aborting" terminate_main_process exit 1 fi sleep $SLEEP_DURATION; done; echo "Found file $FILE_TO_WATCH; watching for heartbeats..." while [[ -f "$FILE_TO_WATCH" ]]; do LAST_HEARTBEAT=$(stat -c %Y $FILE_TO_WATCH) ELAPSED_TIME_SINCE_AFTER_HEARTBEAT=$(expr $(date +%s) - $LAST_HEARTBEAT) if [ "$ELAPSED_TIME_SINCE_AFTER_HEARTBEAT" -gt "$HEARTBEAT_TIMEOUT_THRESHOLD" ]; then echo "Last heartbeat to file $FILE_TO_WATCH was more than $HEARTBEAT_TIMEOUT_THRESHOLD seconds ago at $LAST_HEARTBEAT; terminating" terminate_main_process exit 0 fi sleep $SLEEP_DURATION; done; echo "Outside of loop, main-container-terminated file no longer exists" # The file will be deleted once the fluentd container is terminated echo "The file $FILE_TO_WATCH doesn't exist any more;" terminate_main_process exit 0