Verwendung von YuniKorn als benutzerdefiniertem Scheduler für Apache Spark in Amazon EMR in EKS - Amazon EMR

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 kann Sie bei der Verwaltung der Spark-Planung mit einer anwendungsorientierten Planung unterstützen, sodass Sie eine genaue Kontrolle über Ressourcenkontingente und Prioritäten haben. Bei der Gruppenplanung plant YuniKorn eine Anwendung nur dann, wenn die minimale Ressourcenanforderung für die Anwendung erfüllt werden kann. Weitere Informationen finden Sie unter Was ist Gruppenplanung auf der Apache-YuniKorn-Dokumentationsseite.

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.

  1. 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
  2. Erstellen Sie den Cluster:

    eksctl create cluster -f eks-cluster.yaml
  3. Erstellen Sie den Namespace spark-job, in dem Sie den Spark-Auftrag ausführen werden:

    kubectl create namespace spark-job
  4. Erstellen Sie als Nächstes eine Kubernetes-Rolle und eine Rollenbindung. Dies ist für das Servicekonto erforderlich, das der Spark-Auftraglauf verwendet.

    1. 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
    2. Wenden Sie die Kubernetes-Rollen- und Rollenbindungsdefinition mit dem folgenden Befehl an:

      kubectl apply -f emr-job-execution-rbac.yaml

YuniKorn installieren und einrichten

  1. Verwenden Sie den folgenden kubectl-Befehl, um einen yunikorn-Namespace für die Bereitstellung des Yunikorn-Planers zu erstellen:

    kubectl create namespace yunikorn
  2. 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

  1. Sofern noch nicht geschehen, stellen Sie sicher, dass Sie folgende Voraussetzungen erfüllen:

    1. Erstellen Sie Ihren Cluster und richten Sie ihn für YuniKorn ein

    2. YuniKorn installieren und einrichten

    3. Einrichtung des Spark-Operators für Amazon EMR auf EKS

    4. 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
  2. Erstellen Sie eine SparkApplication-Definitionsdatei spark-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"
  3. Senden Sie die Spark-Anwendung mit dem folgenden Befehl. Dadurch wird auch ein SparkApplication-Objekt mit dem Namen spark-pi erstellt:

    kubectl apply -f spark-pi.yaml
  4. Ü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

  1. Führen Sie zunächst die Schritte in diesem Spark-Submit für Amazon einrichten am EMR EKS-Abschnitt durch.

  2. Legen Sie die Werte der folgenden Umgebungsvariablen fest:

    export SPARK_HOME=spark-home export MASTER_URL=k8s://Amazon-EKS-cluster-endpoint
  3. 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
  4. Überprüfen Sie die Ereignisse für das SparkApplication-Objekt mit dem folgenden Befehl:

    kubectl describe pod spark-driver-pod --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