

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Menggunakan YuniKorn sebagai penjadwal khusus untuk Apache Spark di Amazon EMR di EKS
<a name="tutorial-yunikorn"></a>

Dengan Amazon EMR di EKS, Anda dapat menggunakan operator Spark atau spark-submit untuk menjalankan pekerjaan Spark dengan penjadwal kustom Kubernetes. Tutorial ini mencakup cara menjalankan pekerjaan Spark dengan YuniKorn penjadwal pada antrian khusus dan penjadwalan geng.

## Ikhtisar
<a name="tutorial-yunikorn-overview"></a>

[Apache YuniKorn](https://yunikorn.apache.org/) dapat membantu mengelola penjadwalan Spark dengan penjadwalan yang sadar aplikasi sehingga Anda dapat memiliki kontrol halus pada kuota dan prioritas sumber daya. Dengan penjadwalan geng, YuniKorn menjadwalkan aplikasi hanya jika permintaan sumber daya minimal untuk aplikasi dapat dipenuhi. Untuk informasi selengkapnya, lihat [Apa itu penjadwalan geng](https://yunikorn.apache.org/docs/user_guide/gang_scheduling/) di situs YuniKorn dokumentasi Apache. 

## Buat klaster Anda dan siapkan untuk YuniKorn
<a name="tutorial-yunikorn-setup"></a>

Gunakan langkah-langkah berikut untuk menerapkan kluster Amazon EKS. Anda dapat mengubah Wilayah AWS (`region`) dan Availability Zones (`availabilityZones`).

1. Tentukan 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
   ```

1. Buat cluster:

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

1. Buat namespace `spark-job` tempat Anda akan menjalankan pekerjaan Spark:

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

1. Selanjutnya, buat role dan role binding Kubernetes. Ini diperlukan untuk akun layanan yang digunakan oleh Spark job run.

   1. Tentukan akun layanan, peran, dan pengikatan peran untuk pekerjaan 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. Terapkan definisi role dan role binding Kubernetes dengan perintah berikut:

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

## Instal dan atur YuniKorn
<a name="tutorial-yunikorn-install"></a>

1. Gunakan perintah kubectl berikut untuk membuat namespace `yunikorn` guna menerapkan penjadwal Yunikorn:

   ```
   kubectl create namespace yunikorn
   ```

1. Untuk menginstal scheduler, jalankan perintah Helm berikut:

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

   ```
   helm repo update
   ```

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

## Jalankan aplikasi Spark dengan YuniKorn penjadwal dengan operator Spark
<a name="tutorial-yunikorn-sparkoperator"></a>

1. Jika Anda belum melakukannya, selesaikan langkah-langkah di bagian berikut untuk menyiapkan:

   1. [Buat klaster Anda dan siapkan untuk YuniKorn](#tutorial-yunikorn-setup)

   1. [Instal dan atur YuniKorn](#tutorial-yunikorn-install)

   1. [Menyiapkan operator Spark untuk Amazon EMR di EKS](spark-operator-setup.md)

   1. [Instal operator Spark](spark-operator-gs.md#spark-operator-install)

      Sertakan argumen berikut saat Anda menjalankan `helm install spark-operator-demo` perintah:

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

1. Buat file `SparkApplication` definisi`spark-pi.yaml`.

   Untuk digunakan YuniKorn sebagai penjadwal untuk pekerjaan Anda, Anda harus menambahkan anotasi dan label tertentu ke definisi aplikasi Anda. Anotasi dan label menentukan antrian untuk pekerjaan Anda dan strategi penjadwalan yang ingin Anda gunakan.

   Dalam contoh berikut, anotasi `schedulingPolicyParameters` mengatur penjadwalan geng untuk aplikasi. Kemudian, contoh membuat **kelompok tugas**, atau “geng” tugas, untuk menentukan kapasitas minimum yang harus tersedia sebelum menjadwalkan pod untuk memulai eksekusi pekerjaan. Dan akhirnya, ini menentukan dalam definisi kelompok tugas untuk menggunakan kelompok simpul dengan `"app": "spark"` label, seperti yang didefinisikan di [Buat klaster Anda dan siapkan untuk YuniKorn](#tutorial-yunikorn-setup) bagian.

   ```
   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. Kirim aplikasi Spark dengan perintah berikut. Ini juga menciptakan `SparkApplication` objek yang disebut`spark-pi`:

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

1. Periksa peristiwa untuk `SparkApplication` objek dengan perintah berikut: 

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

   Acara pod pertama akan menunjukkan bahwa YuniKorn telah menjadwalkan pod:

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

## Jalankan aplikasi Spark dengan YuniKorn scheduler dengan `spark-submit`
<a name="tutorial-yunikorn-sparksubmit"></a>

1. Pertama, selesaikan langkah-langkah di [Menyiapkan spark-submit untuk Amazon EMR di EKS](spark-submit-setup.md) bagian ini.

1. Tetapkan nilai untuk variabel lingkungan berikut:

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

1. Kirim aplikasi Spark dengan perintah berikut:

   Dalam contoh berikut, anotasi `schedulingPolicyParameters` mengatur penjadwalan geng untuk aplikasi. Kemudian, contoh membuat **kelompok tugas**, atau “geng” tugas, untuk menentukan kapasitas minimum yang harus tersedia sebelum menjadwalkan pod untuk memulai eksekusi pekerjaan. Dan akhirnya, ini menentukan dalam definisi kelompok tugas untuk menggunakan kelompok simpul dengan `"app": "spark"` label, seperti yang didefinisikan di [Buat klaster Anda dan siapkan untuk YuniKorn](#tutorial-yunikorn-setup) bagian.

   ```
   $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. Periksa peristiwa untuk `SparkApplication` objek dengan perintah berikut: 

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

   Acara pod pertama akan menunjukkan bahwa YuniKorn telah menjadwalkan pod:

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