Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Utilisation de YuniKorn comme planificateur personnalisé pour Apache Spark sur Amazon EMR on EKS
Avec Amazon EMR on EKS, vous avez la possibilité d'utiliser l'opérateur Spark ou la commande spark-submit pour lancer des tâches Spark en utilisant des planificateurs personnalisés Kubernetes. Ce didacticiel explique comment exécuter des tâches Spark avec un planificateur YuniKorn sur une file d'attente personnalisée et une planification groupée.
Présentation
Apache YuniKorn
Création de votre cluster et préparation pour YuniKorn
Suivez les étapes ci-dessous pour déployer un cluster Amazon EKS. Vous pouvez modifier les zones Région AWS (region
) et les zones de disponibilité (availabilityZones
).
-
Définissez le cluster 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 -
Créez le cluster :
eksctl create cluster -f eks-cluster.yaml
-
Créez l'espace de noms
spark-job
dans lequel vous exécuterez la tâche Spark :kubectl create namespace spark-job
-
Créez ensuite un rôle Kubernetes et une liaison de rôle. Cela est requis pour le compte de service utilisé par l'exécution de la tâche Spark.
-
Définissez le compte de service, le rôle et la liaison de rôle pour les tâches 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
-
Appliquez la définition du rôle Kubernetes et de la liaison de rôle à l'aide de la commande suivante :
kubectl apply -f emr-job-execution-rbac.yaml
-
Installation et configuration de YuniKorn
-
Utilisez la commande kubectl suivante pour créer un espace de noms
yunikorn
afin de déployer le planificateur YuniKorn :kubectl create namespace yunikorn
-
Pour installer le planificateur, exécutez les commandes Helm suivantes :
helm repo add yunikorn https://apache.github.io/yunikorn-release
helm repo update
helm install yunikorn yunikorn/yunikorn --namespace yunikorn
Exécution d'une application Spark avec le planificateur YuniKorn à l'aide de l'opérateur Spark
-
Si vous ne l'avez pas encore fait, suivez les étapes indiquées dans les sections ci-dessous pour vous préparer :
-
Installation de l'opérateur Spark
Incluez les arguments suivants lorsque vous exécutez la commande
helm install spark-operator-demo
:--set batchScheduler.enable=true --set webhook.enable=true
-
Créez un fichier de définition
SparkApplication
spark-pi.yaml
.Pour utiliser YuniKorn comme planificateur pour vos tâches, vous devez ajouter certaines annotations et étiquettes à la définition de votre application. Les annotations et les étiquettes indiquent la file d'attente pour votre tâche et la stratégie de planification que vous souhaitez utiliser.
Dans l'exemple ci-dessous, l'annotation
schedulingPolicyParameters
configure la planification groupée pour l'application. L'exemple crée ensuite des groupes de tâches pour indiquer la capacité minimale qui doit être disponible avant de programmer les pods pour commencer l'exécution de la tâche. Enfin, il indique dans la définition du groupe de tâches qu'il faut utiliser des groupes de nœuds avec l'étiquette"app": "spark"
, comme défini dans la section Création de votre cluster et préparation pour YuniKorn.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" -
Soumettez l'application Spark à l'aide de la commande suivante. Cela crée également un objet
SparkApplication
appeléspark-pi
:kubectl apply -f spark-pi.yaml
-
Vérifiez les événements de l'objet
SparkApplication
à l'aide de la commande suivante :kubectl describe sparkapplication spark-pi --namespace spark-job
Le premier événement du pod montrera que YuniKorn a programmé les pods :
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
Exécution d'une application Spark avec le planificateur YuniKorn à l'aide de spark-submit
-
Effectuez d'abord les étapes décrites dans la section Configuration de Spark-Submit pour Amazon sur EMR EKS.
-
Définissez les valeurs des variables d'environnement suivantes :
export SPARK_HOME=spark-home export MASTER_URL=k8s://
Amazon-EKS-cluster-endpoint
-
Soumettez l'application Spark à l'aide de la commande suivante :
Dans l'exemple ci-dessous, l'annotation
schedulingPolicyParameters
configure la planification groupée pour l'application. L'exemple crée ensuite des groupes de tâches pour indiquer la capacité minimale qui doit être disponible avant de programmer les pods pour commencer l'exécution de la tâche. Enfin, il indique dans la définition du groupe de tâches qu'il faut utiliser des groupes de nœuds avec l'étiquette"app": "spark"
, comme défini dans la section Création de votre cluster et préparation pour YuniKorn.$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 -
Vérifiez les événements de l'objet
SparkApplication
à l'aide de la commande suivante :kubectl describe pod
spark-driver-pod
--namespace spark-jobLe premier événement du pod montrera que YuniKorn a programmé les pods :
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