Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
Verwendung von YuniKorn als benutzerdefiniertem Scheduler für Apache Spark in Amazon EMR in EKS
Mit Amazon EMR in EKS können Sie Spark-Operator oder Spark-Submit verwenden, um Spark-Aufträge mit benutzerdefinierten Kubernetes-Schedulern auszuführen. In diesem Tutorial erfahren Sie, wie Sie Spark-Aufträge mit einem YuniKorn-Planer in einer benutzerdefinierten Warteschlange und Gruppenplanung ausführen.
Übersicht
Apache YuniKorn
Erstellen Sie Ihren Cluster und richten Sie ihn für YuniKorn ein
Führen Sie die folgenden Schritte aus, um einen Amazon-EKS-Cluster bereitzustellen. Sie können die AWS-Region (region
) und Availability Zones (availabilityZones
) ändern.
-
Definieren Sie den Amazon-EKS-Cluster:
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 -
Erstellen Sie den Cluster:
eksctl create cluster -f eks-cluster.yaml
-
Erstellen Sie den Namespace
spark-job
, in dem Sie den Spark-Auftrag ausführen werden:kubectl create namespace spark-job
-
Erstellen Sie als Nächstes eine Kubernetes-Rolle und eine Rollenbindung. Dies ist für das Servicekonto erforderlich, das der Spark-Auftraglauf verwendet.
-
Definieren Sie das Servicekonto, die Rolle und die Rollenbindung für Spark-Aufträge.
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
-
Wenden Sie die Kubernetes-Rollen- und Rollenbindungsdefinition mit dem folgenden Befehl an:
kubectl apply -f emr-job-execution-rbac.yaml
-
YuniKorn installieren und einrichten
-
Verwenden Sie den folgenden kubectl-Befehl, um einen
yunikorn
-Namespace für die Bereitstellung des Yunikorn-Planers zu erstellen:kubectl create namespace yunikorn
-
Um den Planer zu installieren, führen Sie die folgenden Helm-Befehle aus:
helm repo add yunikorn https://apache.github.io/yunikorn-release
helm repo update
helm install yunikorn yunikorn/yunikorn --namespace yunikorn
Führen Sie eine Spark-Anwendung mit YuniKorn-Planer und dem Spark-Operator aus
-
Sofern noch nicht geschehen, stellen Sie sicher, dass Sie folgende Voraussetzungen erfüllen:
-
Erstellen Sie Ihren Cluster und richten Sie ihn für YuniKorn ein
-
Den Spark-Operator installieren
Geben Sie bei der Ausführung des
helm install spark-operator-demo
-Befehls die folgenden Argumente an:--set batchScheduler.enable=true --set webhook.enable=true
-
-
Erstellen Sie eine
SparkApplication
-Definitionsdateispark-pi.yaml
.Um YuniKorn als Planer für Ihre Aufträge zu verwenden, müssen Sie Ihrer Anwendungsdefinition bestimmte Anmerkungen und Labels hinzufügen. Die Anmerkungen und Beschriftungen spezifizieren die Warteschlange für Ihren Auftrag und die Planungsstrategie, die Sie verwenden möchten.
Im folgenden Beispiel
schedulingPolicyParameters
richtet die Anmerkung die Gruppenplanung für die Anwendung ein. Anschließend werden im Beispiel Aufgabengruppen oder „Gruppen“ von Aufgaben erstellt, um die Mindestkapazität anzugeben, die verfügbar sein muss, bevor die Pods für den Start der Auftragsausführung geplant werden. Und schließlich gibt es in der Aufgabengruppendefinition an, dass Knotengruppen mit der"app": "spark"
-Bezeichnung verwendet werden sollen, wie im Erstellen Sie Ihren Cluster und richten Sie ihn für YuniKorn ein-Abschnitt definiert.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" -
Senden Sie die Spark-Anwendung mit dem folgenden Befehl. Dadurch wird auch ein
SparkApplication
-Objekt mit dem Namenspark-pi
erstellt:kubectl apply -f spark-pi.yaml
-
Überprüfen Sie die Ereignisse für das
SparkApplication
-Objekt mit dem folgenden Befehl:kubectl describe sparkapplication spark-pi --namespace spark-job
Das erste Pod-Ereignis zeigt, dass YuniKorn die Pods geplant hat:
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
Ausführung einer Spark-Anwendung mit dem YuniKorn-Planer mit spark-submit
-
Führen Sie zunächst die Schritte in diesem Spark-Submit für Amazon einrichten am EMR EKS-Abschnitt durch.
-
Legen Sie die Werte der folgenden Umgebungsvariablen fest:
export SPARK_HOME=spark-home export MASTER_URL=k8s://
Amazon-EKS-cluster-endpoint
-
Senden Sie die Spark-Anwendung mit dem folgenden Befehl:
Im folgenden Beispiel
schedulingPolicyParameters
richtet die Anmerkung die Gruppenplanung für die Anwendung ein. Anschließend werden im Beispiel Aufgabengruppen oder „Gruppen“ von Aufgaben erstellt, um die Mindestkapazität anzugeben, die verfügbar sein muss, bevor die Pods für den Start der Auftragsausführung geplant werden. Und schließlich gibt es in der Aufgabengruppendefinition an, dass Knotengruppen mit der"app": "spark"
-Bezeichnung verwendet werden sollen, wie im Erstellen Sie Ihren Cluster und richten Sie ihn für YuniKorn ein-Abschnitt definiert.$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 -
Überprüfen Sie die Ereignisse für das
SparkApplication
-Objekt mit dem folgenden Befehl:kubectl describe pod
spark-driver-pod
--namespace spark-jobDas erste Pod-Ereignis zeigt, dass YuniKorn die Pods geplant hat:
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