기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
Amazon EMR on EKS에서 Apache Spark의 사용자 지정 스케줄러로 YuniKorn 사용
Amazon EMR on EKS을 사용하면 Spark 운영자 또는 spark-submit을 사용하여 Kubernetes 사용자 지정 스케줄러로 Spark 작업을 실행할 수 있습니다. 이 자습서에서는 사용자 지정 대기열 및 단체 예약(gang scheduling)에서 Volcano 스케줄러를 통해 Spark 작업을 실행하는 방법을 다룹니다.
개요
Apache Yunikorn
클러스터를 생성하고 YuniKorn 설정
다음 단계에 따라 Amazon ECS 클러스터를 배포합니다. AWS 리전(region
) 및 가용 영역(availabilityZones
)을 변경할 수 있습니다.
-
Amazon EKS 클러스터를 정의합니다.
cat <<EOF >eks-cluster.yaml --- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: emr-eks-cluster region:
eu-west-1
vpc: clusterEndpoints: publicAccess: true privateAccess: true iam: withOIDC: true nodeGroups: - name: spark-jobs labels: { app: spark } instanceType: m5.xlarge desiredCapacity: 2 minSize: 2 maxSize: 3 availabilityZones: ["eu-west-1a"
] EOF -
클러스터를 생성합니다.
eksctl create cluster -f eks-cluster.yaml
-
Spark 작업을 실행할
spark-job
네임스페이스를 생성합니다.kubectl create namespace spark-job
-
다음으로 Kubernetes 역할 및 역할 바인딩을 생성합니다. 이는 Spark 작업 실행에서 사용하는 서비스 계정에 필요합니다.
-
Spark 작업에 대한 서비스 계정, 역할 및 역할 바인딩을 정의합니다.
cat <<EOF >emr-job-execution-rbac.yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: spark-sa namespace: spark-job automountServiceAccountToken: false --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: spark-role namespace: spark-job rules: - apiGroups: ["", "batch","extensions"] resources: ["configmaps","serviceaccounts","events","pods","pods/exec","pods/log","pods/portforward","secrets","services","persistentvolumeclaims"] verbs: ["create","delete","get","list","patch","update","watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: spark-sa-rb namespace: spark-job roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: spark-role subjects: - kind: ServiceAccount name: spark-sa namespace: spark-job EOF
-
다음 명령을 사용하여 Kubernetes 역할 및 역할 바인딩 정의를 적용합니다.
kubectl apply -f emr-job-execution-rbac.yaml
-
YuniKorn 설치 및 설정
-
다음 kubectl 명령을 사용하여 Yunikorn 스케줄러를 배포하기 위해 네임스페이스(
yunikorn
)를 생성합니다.kubectl create namespace yunikorn
-
스케줄러를 설치하려면 다음 Helm 명령을 실행합니다.
helm repo add yunikorn https://apache.github.io/yunikorn-release
helm repo update
helm install yunikorn yunikorn/yunikorn --namespace yunikorn
Spark 운영자를 사용하여 YuniKorn 스케줄러에서 Spark 애플리케이션 실행
-
아직 실행하지 않았다면, 다음 단계를 완료하여 설정합니다.
-
helm install spark-operator-demo
명령을 실행할 때 다음 인수를 포함합니다.--set batchScheduler.enable=true --set webhook.enable=true
-
SparkApplication
정의 파일spark-pi.yaml
을 생성합니다.YuniKorn을 작업 스케줄러로 사용하려면 애플리케이션 정의에 특정 주석과 레이블을 추가해야 합니다. 주석과 레이블은 작업 대기열 및 사용하려는 예약 전략을 지정합니다.
다음 예제에서는
schedulingPolicyParameters
주석을 사용하여 애플리케이션에 대한 단체 예약을 설정합니다. 그런 다음, 이 예제에서는 작업 그룹(즉 작업 '단체')을 생성하여 작업 실행을 위해 포드를 예약하기 전에 사용할 수 있어야 하는 최소 용량을 지정합니다. 마지막으로, 클러스터를 생성하고 YuniKorn 설정 섹션에 정의된 대로 작업 그룹 정의에서"app": "spark"
레이블의 노드 그룹을 사용하도록 지정합니다.apiVersion: "sparkoperator.k8s.io/v1beta2" kind: SparkApplication metadata: name: spark-pi namespace: spark-job spec: type: Scala mode: cluster image: "895885662937.dkr.ecr.
us-west-2
.amazonaws.com/spark/emr-6.10.0:latest
" imagePullPolicy: Always mainClass: org.apache.spark.examples.SparkPi mainApplicationFile: "local:///usr/lib/spark/examples/jars/spark-examples.jar" sparkVersion: "3.3.1" restartPolicy: type: Never volumes: - name: "test-volume" hostPath: path: "/tmp" type: Directory driver: cores: 1 coreLimit: "1200m" memory: "512m" labels: version: 3.3.1 annotations: yunikorn.apache.org/schedulingPolicyParameters: "placeholderTimeoutSeconds=30 gangSchedulingStyle=Hard" yunikorn.apache.org/task-group-name: "spark-driver" yunikorn.apache.org/task-groups: |- [{ "name": "spark-driver", "minMember": 1, "minResource": { "cpu": "1200m", "memory": "1Gi" }, "nodeSelector": { "app": "spark" } }, { "name": "spark-executor", "minMember": 1, "minResource": { "cpu": "1200m", "memory": "1Gi" }, "nodeSelector": { "app": "spark" } }] serviceAccount: spark-sa volumeMounts: - name: "test-volume
" mountPath: "/tmp" executor: cores: 1 instances: 1 memory: "512m" labels: version: 3.3.1 annotations: yunikorn.apache.org/task-group-name: "spark-executor" volumeMounts: - name: "test-volume
" mountPath: "/tmp" -
다음 명령을 사용하여 Spark 애플리케이션을 제출합니다. 이렇게 하면
spark-pi
라고 하는SparkApplication
객체도 생성됩니다.kubectl apply -f spark-pi.yaml
-
다음 명령을 사용하여
SparkApplication
객체에 대한 이벤트를 확인합니다.kubectl describe sparkapplication spark-pi --namespace spark-job
첫 번째 포드 이벤트는 YuniKorn에서 해당 포드를 예약했음을 보여줍니다.
Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduling 3m12s yunikorn spark-operator/org-apache-spark-examples-sparkpi-2a777a88b98b8a95-driver is queued and waiting for allocation Normal GangScheduling 3m12s yunikorn Pod belongs to the taskGroup spark-driver, it will be scheduled as a gang member Normal Scheduled 3m10s yunikorn Successfully assigned spark Normal PodBindSuccessful 3m10s yunikorn Pod spark-operator/ Normal TaskCompleted 2m3s yunikorn Task spark-operator/ Normal Pulling 3m10s kubelet Pulling
spark-submit
을 사용하여 YuniKorn 스케줄러에서 Spark 애플리케이션 실행
-
먼저, Amazon에서 스파크 서브미션 설정하기 EMR EKS 섹션에 나온 단계를 완료합니다.
-
다음과 같은 환경 변수의 값을 설정합니다.
export SPARK_HOME=spark-home export MASTER_URL=k8s://
Amazon-EKS-cluster-endpoint
-
다음 명령을 사용하여 Spark 애플리케이션을 제출합니다.
다음 예제에서는
schedulingPolicyParameters
주석을 사용하여 애플리케이션에 대한 단체 예약을 설정합니다. 그런 다음, 이 예제에서는 작업 그룹(즉 작업 '단체')을 생성하여 작업 실행을 위해 포드를 예약하기 전에 사용할 수 있어야 하는 최소 용량을 지정합니다. 마지막으로, 클러스터를 생성하고 YuniKorn 설정 섹션에 정의된 대로 작업 그룹 정의에서"app": "spark"
레이블의 노드 그룹을 사용하도록 지정합니다.$SPARK_HOME/bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --master $MASTER_URL \ --conf spark.kubernetes.container.image=895885662937.dkr.ecr.
us-west-2
.amazonaws.com/spark/emr-6.10.0:latest
\ --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark-sa \ --deploy-mode cluster \ --conf spark.kubernetes.namespace=spark-job \ --conf spark.kubernetes.scheduler.name=yunikorn \ --conf spark.kubernetes.driver.annotation.yunikorn.apache.org/schedulingPolicyParameters="placeholderTimeoutSeconds=30 gangSchedulingStyle=Hard" \ --conf spark.kubernetes.driver.annotation.yunikorn.apache.org/task-group-name="spark-driver" \ --conf spark.kubernetes.executor.annotation.yunikorn.apache.org/task-group-name="spark-executor" \ --conf spark.kubernetes.driver.annotation.yunikorn.apache.org/task-groups='[{ "name": "spark-driver", "minMember": 1, "minResource": { "cpu": "1200m", "memory": "1Gi" }, "nodeSelector": { "app": "spark" } }, { "name": "spark-executor", "minMember": 1, "minResource": { "cpu": "1200m", "memory": "1Gi" }, "nodeSelector": { "app": "spark" } }]' \ local:///usr/lib/spark/examples/jars/spark-examples.jar 20 -
다음 명령을 사용하여
SparkApplication
객체에 대한 이벤트를 확인합니다.kubectl describe pod
spark-driver-pod
--namespace spark-job첫 번째 포드 이벤트는 YuniKorn에서 해당 포드를 예약했음을 보여줍니다.
Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduling 3m12s yunikorn spark-operator/org-apache-spark-examples-sparkpi-2a777a88b98b8a95-driver is queued and waiting for allocation Normal GangScheduling 3m12s yunikorn Pod belongs to the taskGroup spark-driver, it will be scheduled as a gang member Normal Scheduled 3m10s yunikorn Successfully assigned spark Normal PodBindSuccessful 3m10s yunikorn Pod spark-operator/ Normal TaskCompleted 2m3s yunikorn Task spark-operator/ Normal Pulling 3m10s kubelet Pulling