

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# YuniKorn Utilización como programador personalizado para Apache Spark en Amazon EMR en EKS
<a name="tutorial-yunikorn"></a>

Con Amazon EMR en EKS, puede usar el operador de Spark o spark-submit para ejecutar trabajos de Spark con los programadores personalizados de Kubernetes. En este tutorial se explica cómo ejecutar tareas de Spark con un YuniKorn programador según una programación personalizada de colas y grupos.

## Descripción general de
<a name="tutorial-yunikorn-overview"></a>

[Apache YuniKorn](https://yunikorn.apache.org/) puede ayudarte a gestionar la programación de Spark con una programación compatible con las aplicaciones, de forma que puedas tener un control pormenorizado de las cuotas y prioridades de los recursos. Con la programación en grupo, solo se YuniKorn puede programar una aplicación cuando se puede satisfacer la solicitud mínima de recursos de la aplicación. Para obtener más información, consulte [Qué es la programación de pandillas](https://yunikorn.apache.org/docs/user_guide/gang_scheduling/) en el sitio de YuniKorn documentación de Apache. 

## Cree su clúster y prepárese para YuniKorn
<a name="tutorial-yunikorn-setup"></a>

Siga estos pasos para implementar un clúster de Amazon EKS. Puede cambiar la Región de AWS (`region`) y las zonas de disponibilidad (`availabilityZones`).

1. Defina el clúster de 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
   ```

1. Cree el clúster:

   ```
   eksctl create cluster -f eks-cluster.yaml
   ```

1. Cree el espacio de nombres `spark-job` en el que ejecutará el trabajo de Spark:

   ```
   kubectl create namespace spark-job
   ```

1. A continuación, cree un rol de Kubernetes y una vinculación de roles. Esto es obligatorio para la cuenta de servicio que utiliza la ejecución del trabajo de Spark.

   1. Defina la cuenta de servicio, el rol y la vinculación de roles de los trabajos de 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
      ```

   1. Aplique el rol de Kubernetes y la definición de la vinculación de roles con el siguiente comando:

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

## Instalar y configurar YuniKorn
<a name="tutorial-yunikorn-install"></a>

1. Use el siguiente comando kubectl para crear un espacio de nombres de `yunikorn` para implementar el programador de YuniKorn:

   ```
   kubectl create namespace yunikorn
   ```

1. Para instalar el programador, ejecute los siguientes comandos de Helm:

   ```
   helm repo add yunikorn https://apache.github.io/yunikorn-release
   ```

   ```
   helm repo update
   ```

   ```
   helm install yunikorn yunikorn/yunikorn --namespace yunikorn
   ```

## Ejecute una aplicación de Spark con un YuniKorn programador con el operador de Spark
<a name="tutorial-yunikorn-sparkoperator"></a>

1. Si aún no lo ha hecho, complete los pasos de las secciones siguientes para configurarlo todo:

   1. [Cree su clúster y prepárese para YuniKorn](#tutorial-yunikorn-setup)

   1. [Instalar y configurar YuniKorn](#tutorial-yunikorn-install)

   1. [Configuración del operador de Spark para Amazon EMR en EKS](spark-operator-setup.md)

   1. [Instalar el operador de Spark](spark-operator-gs.md#spark-operator-install)

      Cuando ejecute el comando `helm install spark-operator-demo`, incluya los siguientes argumentos:

      ```
      --set batchScheduler.enable=true 
      --set webhook.enable=true
      ```

1. Cree un archivo de definición `spark-pi.yaml` de `SparkApplication`.

   Para utilizarlo YuniKorn como planificador de sus trabajos, debe añadir determinadas anotaciones y etiquetas a la definición de la aplicación. Las anotaciones y etiquetas especifican la cola del trabajo y la estrategia de programación que desee utilizar.

   En el siguiente ejemplo, la anotación `schedulingPolicyParameters` configura la planificación por grupos de la aplicación. A continuación, en el ejemplo se crean **grupos de tareas** para especificar la capacidad mínima que debe estar disponible antes de programar los pods para iniciar la ejecución del trabajo. Por último, especifica en la definición del grupo de tareas el uso de grupos de nodos con la etiqueta `"app": "spark"`, tal como se define en la sección [Cree su clúster y prepárese para YuniKorn](#tutorial-yunikorn-setup).

   ```
   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"
   ```

1. Envíe la aplicación de Spark con el siguiente comando. Esto también crea un objeto `SparkApplication` llamado `spark-pi`:

   ```
   kubectl apply -f spark-pi.yaml
   ```

1. Compruebe los eventos del objeto `SparkApplication` con el siguiente comando: 

   ```
   kubectl describe sparkapplication spark-pi --namespace spark-job
   ```

   El primer evento del pod mostrará que se YuniKorn han programado los 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
   ```

## Ejecuta una aplicación Spark con un YuniKorn programador con `spark-submit`
<a name="tutorial-yunikorn-sparksubmit"></a>

1. En primer lugar, complete los pasos de la sección [Configuración de spark-submit para Amazon EMR en EKS](spark-submit-setup.md).

1. Establezca los valores de las siguientes variables de entorno:

   ```
   export SPARK_HOME=spark-home
   export MASTER_URL=k8s://Amazon-EKS-cluster-endpoint
   ```

1. Envíe la aplicación de Spark con el siguiente comando:

   En el siguiente ejemplo, la anotación `schedulingPolicyParameters` configura la planificación por grupos de la aplicación. A continuación, en el ejemplo se crean **grupos de tareas** para especificar la capacidad mínima que debe estar disponible antes de programar los pods para iniciar la ejecución del trabajo. Por último, especifica en la definición del grupo de tareas el uso de grupos de nodos con la etiqueta `"app": "spark"`, tal como se define en la sección [Cree su clúster y prepárese para YuniKorn](#tutorial-yunikorn-setup).

   ```
   $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
   ```

1. Compruebe los eventos del objeto `SparkApplication` con el siguiente comando: 

   ```
   kubectl describe pod spark-driver-pod --namespace spark-job
   ```

   El primer evento de pods mostrará que se YuniKorn han programado los 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
   ```