All Products
Search
Document Center

Container Service for Kubernetes:Gunakan elastic container instances untuk menjalankan pekerjaan Spark

Last Updated:Aug 21, 2026

Topik ini menjelaskan cara menjalankan pekerjaan Spark di ACK menggunakan resource Elastic Container Instance (ECI). Dengan mengonfigurasi strategi penjadwalan yang sesuai, Anda dapat membuat Pod ECI sesuai permintaan dan hanya membayar resource yang dikonsumsi, sehingga mengurangi biaya idle serta menjalankan pekerjaan Spark secara lebih ekonomis.

Prasyarat

Anda memerlukan:

Cara kerja

Saat ack-virtual-node diterapkan, setiap node ECI memiliki taint virtual-kubelet.io/provider=alibabacloud:NoSchedule. Tanpa toleransi yang sesuai, penjadwal akan melewati node ECI dan menempatkan semua pod di ECS. Untuk mengarahkan pod Spark ke ECI, tambahkan toleransi dan aturan afinitas node ke spesifikasi SparkApplication.

ECI menjalankan setiap container dalam sandbox virtual ringan yang sepenuhnya mengisolasi pod. Dengan penagihan pay-as-you-go, Anda hanya membayar CPU dan memori yang dikonsumsi setiap pod selama berjalan—bukan kapasitas node idle.

Penempatan driver vs. executor

Pod driver dan executor gagal dengan cara berbeda, yang memengaruhi penempatannya:

  • Jika executor gagal, Spark secara otomatis menggantinya. Executor bersifat stateless dan toleran terhadap kesalahan.

  • Jika driver gagal, seluruh pekerjaan gagal dan dimulai ulang dari awal. Pastikan driver tetap stabil.

Simpan driver di node ECS yang andal dan arahkan executor ke instans ECI atau preemptible berbiaya lebih rendah saat biaya menjadi pertimbangan utama.

Karakteristik ECI untuk beban kerja Spark:

Karakteristik Nilai
Skala Lebih dari 50.000 pod dalam kluster ACK Serverless; tidak perlu konfigurasi tambahan
Kecepatan provisioning Ribuan pod dalam hitungan detik
Penagihan Pay-as-you-go; tersedia instans preemptible untuk pengurangan biaya lebih lanjut

Pilih strategi penjadwalan

Tiga strategi mencakup skenario penerapan umum:

Strategi Kapan digunakan Penempatan driver Penempatan executor
ECS only Beban kerja stabil dan dapat diprediksi ECS ECS
ECI only Pekerjaan batch atau burst yang membutuhkan elastisitas penuh ECI ECI
ECS-first with ECI fallback Beban normal di ECS; memperluas kapasitas ke ECI secara otomatis saat puncak ECS (disarankan) ECS (disarankan), ECI (overflow)

Untuk kontrol detail halus, seperti membatasi jumlah pod per jenis resource, gunakan ResourcePolicy.

Jadwalkan pekerjaan Spark di node ECS dan ECI

Semua contoh menggunakan SparkApplication (CRD sparkoperator.k8s.io/v1beta2) dengan pengaturan dasar berikut:

Bidang Nilai
Image registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2
mainClass org.apache.spark.examples.SparkPi
sparkVersion 3.5.2
driver.serviceAccount spark-operator-spark

ECS only

Tidak diperlukan toleransi atau afinitas. Taint ECI default mencegah penjadwal menempatkan pod di sana.

apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
  name: spark-pi-ecs-only
  namespace: default
spec:
  type: Scala
  mode: cluster
  image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2
  mainClass: org.apache.spark.examples.SparkPi
  mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.2.jar
  arguments:
  - "5000"
  sparkVersion: 3.5.2
  driver:
    cores: 1
    coreLimit: 1200m
    memory: 512m
    serviceAccount: spark-operator-spark
  executor:
    instances: 2
    cores: 2
    memory: 4g

Perilaku yang diharapkan: Semua pod driver dan executor dijadwalkan ke node ECS. Jika kapasitas ECS tidak mencukupi, pod tetap dalam status Pending hingga kapasitas tersedia.

ECI only

Tambahkan toleransi untuk taint ECI default dan aturan afinitas requiredDuringSchedulingIgnoredDuringExecution untuk mengunci pod hanya ke node ECI. Terapkan keduanya pada spesifikasi driver dan executor.

apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
  name: spark-pi-eci-only
  namespace: default
spec:
  type: Scala
  mode: cluster
  image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2
  mainClass: org.apache.spark.examples.SparkPi
  mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.2.jar
  arguments:
  - "5000"
  sparkVersion: 3.5.2
  driver:
    cores: 1
    coreLimit: 1200m
    memory: 512m
    serviceAccount: spark-operator-spark
    affinity:
      nodeAffinity:
        # Kunci driver hanya ke node ECI.
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: type
              operator: In
              values:
              - virtual-kubelet
    tolerations:
    # Toleransi terhadap taint ECI default.
    - key: virtual-kubelet.io/provider
      operator: Equal
      value: alibabacloud
      effect: NoSchedule
  executor:
    instances: 2
    cores: 2
    memory: 4g
    affinity:
      nodeAffinity:
        # Kunci executor hanya ke node ECI.
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: type
              operator: In
              values:
              - virtual-kubelet
    tolerations:
    # Toleransi terhadap taint ECI default.
    - key: virtual-kubelet.io/provider
      operator: Equal
      value: alibabacloud
      effect: NoSchedule

Perilaku yang diharapkan: Semua pod dijadwalkan ke node ECI dan pekerjaan berjalan dalam mode sepenuhnya serverless. Jika kapasitas ECI di wilayah tersebut terbatas, pod tetap dalam status Pending hingga resource tersedia.

ECS-first with ECI fallback

Gunakan afinitas preferredDuringSchedulingIgnoredDuringExecution untuk mengutamakan ECS sekaligus memungkinkan overflow ke ECI. Tambahkan toleransi ECI agar penjadwal dapat menempatkan pod di ECI saat kapasitas ECS penuh.

apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
  name: spark-pi-ecs-first
  namespace: default
spec:
  type: Scala
  mode: cluster
  image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2
  mainClass: org.apache.spark.examples.SparkPi
  mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.2.jar
  arguments:
  - "5000"
  sparkVersion: 3.5.2
  driver:
    cores: 1
    coreLimit: 1200m
    memory: 512m
    serviceAccount: spark-operator-spark
    affinity:
      nodeAffinity:
        # Utamakan node ECS; alihkan ke ECI jika kapasitas ECS habis.
        preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          preference:
            matchExpressions:
            - key: type
              operator: NotIn
              values:
              - virtual-kubelet
    tolerations:
    # Izinkan penjadwalan ke node ECI bila diperlukan.
    - key: virtual-kubelet.io/provider
      operator: Equal
      value: alibabacloud
      effect: NoSchedule
  executor:
    instances: 2
    cores: 2
    memory: 4g
    affinity:
      nodeAffinity:
        # Utamakan node ECS; alihkan ke ECI jika kapasitas ECS habis.
        preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          preference:
            matchExpressions:
            - key: type
              operator: NotIn
              values:
              - virtual-kubelet
    tolerations:
    # Izinkan penjadwalan ke node ECI bila diperlukan.
    - key: virtual-kubelet.io/provider
      operator: Equal
      value: alibabacloud
      effect: NoSchedule

Perilaku yang diharapkan: Pod ditempatkan di ECS jika kapasitas tersedia. Saat ECS penuh, pod overflow dijadwalkan ke ECI. Hal ini menghindari antrian pekerjaan saat puncak tanpa harus menyediakan resource ECI secara permanen.

Lihat Konfigurasi alokasi sumber daya berdasarkan instans ECS dan elastic container instances untuk informasi tentang taint, toleransi, dan afinitas node.

Konfigurasi penjadwalan resource berbasis prioritas

Gunakan ResourcePolicy untuk mendefinisikan unit penjadwalan dengan batas pod per unit. Penjadwal ACK mengisi unit sesuai urutan prioritas saat memperluas kapasitas dan menghapus pod dalam urutan terbalik saat skala-masuk. Lihat Konfigurasi penjadwalan resource berbasis prioritas.

  1. Buat resourcepolicy.yaml untuk pod Spark Operator di namespace default (maksimal 2 di ECS AMD64, lalu 3 di ECI):

    apiVersion: scheduling.alibabacloud.com/v1alpha1
    kind: ResourcePolicy
    metadata:
      name: sparkapplication-resource-policy
      namespace: default                      # Hanya berlaku untuk pod di namespace ini.
    spec:
      ignorePreviousPod: true
      ignoreTerminatingPod: false
      matchLabelKeys:
      - sparkoperator.k8s.io/submission-id    # Kelompokkan pod berdasarkan ID pengiriman pekerjaan Spark.
      preemptPolicy: AfterAllUnits            # Lakukan preemption hanya setelah semua unit habis.
      selector:
        sparkoperator.k8s.io/launched-by-spark-operator: "true"
      strategy: prefer
      units:
      - max: 2                               # Maksimal 2 pod di node ECS AMD64 (prioritas pertama).
        resource: ecs
        nodeSelector:
          kubernetes.io/arch: amd64
      - max: 3                               # Maksimal 3 pod di ECI (prioritas kedua).
        resource: eci
  2. Terapkan ResourcePolicy:

    kubectl apply -f resourcepolicy.yaml
  3. Buat spark-pi.yaml. SparkApplication ini meminta 1 driver dan 5 executor, semuanya mentoleransi taint ECI sehingga ResourcePolicy dapat mendistribusikannya ke kedua jenis unit.

    apiVersion: sparkoperator.k8s.io/v1beta2
    kind: SparkApplication
    metadata:
      name: spark-pi
      namespace: default
    spec:
      type: Scala
      mode: cluster
      image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2
      mainClass: org.apache.spark.examples.SparkPi
      mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.2.jar
      arguments:
      - "5000"
      sparkVersion: 3.5.2
      driver:
        cores: 1
        coreLimit: 1200m
        memory: 512m
        serviceAccount: spark-operator-spark
        tolerations:
        - key: virtual-kubelet.io/provider    # Izinkan driver dijadwalkan ke ECI jika diperlukan.
          operator: Equal
          value: alibabacloud
          effect: NoSchedule
      executor:
        instances: 5
        cores: 1
        coreLimit: 1200m
        memory: 512m
        tolerations:
        - key: virtual-kubelet.io/provider    # Izinkan executor dijadwalkan ke ECI.
          operator: Equal
          value: alibabacloud
          effect: NoSchedule
  4. Kirim pekerjaan Spark:

    kubectl apply -f spark-pi.yaml
  5. Verifikasi hasil penjadwalan:

    kubectl get pods -o wide -l sparkoperator.k8s.io/app-name=spark-pi

    Output yang diharapkan:

    NAME                                        READY   STATUS      RESTARTS   AGE       IP                  NODE
    spark-pi-34c0998f9f832e61-exec-1            1/1     Running     0          28s       192.XXX.XX.34       cn-beijing.192.XXX.XX.250
    spark-pi-34c0998f9f832e61-exec-2            1/1     Running     0          28s       192.XXX.XX.87       virtual-kubelet-cn-beijing-i
    spark-pi-34c0998f9f832e61-exec-3            1/1     Running     0          28s       192.XXX.XX.88       virtual-kubelet-cn-beijing-i
    spark-pi-34c0998f9f832e61-exec-4            1/1     Running     0          28s       192.XXX.XX.86       virtual-kubelet-cn-beijing-i
    spark-pi-34c0998f9f832e61-exec-5            0/1     Pending     0          28s       <none>              <none>
    spark-pi-driver                             1/1     Running     0          34s       192.XXX.XX.37       cn-beijing.192.XXX.XXX.250

    Hasil: Driver dan exec-1 ditempatkan di unit ECS AMD64 (maksimal 2 pod). exec-2, exec-3, dan exec-4 ditempatkan di unit ECI (maksimal 3 pod). exec-5 tetap dalam status Pending karena kedua unit telah mencapai batas podnya.

Percepat pengambilan image dengan ImageCache

Mengambil image Spark besar saat startup setiap pod menambah latensi. ECI ImageCache melakukan pre-cache image di infrastruktur dasar, memangkas waktu startup pod dari sekitar 100 detik menjadi hampir instan saat cache tersedia. Lihat Gunakan ImageCache untuk mempercepat pembuatan elastic container instances.

Bandingkan startup dengan dan tanpa cache image

Tanpa cache, kubectl describe pod spark-pi-driver setelah mengirim SparkApplication menunjukkan:

Events:
  ...
  Warning  ImageCacheMissed       24m   EciService         [eci.imagecache]Missed image cache.
  Normal   ImageCacheAutoCreated  24m   EciService         [eci.imagecache]Image cache imc-2zeXXXXXXXXXXXXXXXXX is auto created
  Normal   Pulling                24m   kubelet            Pulling image "registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2"
  Normal   Pulled                 23m   kubelet            Successfully pulled image "registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2" in 1m41.289s (1m41.289s including waiting)
  ...

Proses pengambilan image memakan waktu sekitar 100 detik. ECI secara otomatis membuat cache untuk eksekusi berikutnya.

Dengan cache hit, event menunjukkan:

Events:
  ...
  Normal  SuccessfulHitImageCache  23s   EciService         [eci.imagecache]Successfully hit image cache imc-2zeXXXXXXXXXXXXXXXXX, eci will be scheduled with this image cache.
  Normal  Pulled                   4s    kubelet            Container image "registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2" already present on machine
  ...

Tidak diperlukan pengambilan image.

Tentukan ID cache image

Tambahkan anotasi k8s.aliyun.com/eci-image-snapshot-id ke spesifikasi driver dan executor untuk mengunci cache image tertentu:

apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
  name: spark-pi-eci-only
  namespace: default
spec:
  type: Scala
  mode: cluster
  image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2
  mainClass: org.apache.spark.examples.SparkPi
  mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.2.jar
  arguments:
  - "5000"
  sparkVersion: 3.5.2
  driver:
    annotations:
      k8s.aliyun.com/eci-image-cache: "true"  # Mengaktifkan pembuatan dan pencocokan cache gambar otomatis.
    cores: 1
    coreLimit: 1200m
    memory: 512m
    serviceAccount: spark-operator-spark
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: type
              operator: In
              values:
              - virtual-kubelet
    tolerations:
    - key: virtual-kubelet.io/provider
      operator: Equal
      value: alibabacloud
      effect: NoSchedule
  executor:
    annotations:
      k8s.aliyun.com/eci-image-cache: "true"  # Mengaktifkan pembuatan dan pencocokan cache gambar otomatis.
    instances: 2
    cores: 2
    memory: 4g
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: type
              operator: In
              values:
              - virtual-kubelet
    tolerations:
    - key: virtual-kubelet.io/provider
      operator: Equal
      value: alibabacloud
      effect: NoSchedule

Aktifkan pembuatan dan pencocokan cache image otomatis

Untuk membiarkan ECI mengelola pembuatan dan pencocokan cache secara otomatis—tanpa ID cache—atur anotasi k8s.aliyun.com/eci-image-cache ke "true" pada driver dan executor:

apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
  name: spark-pi-eci-only
  namespace: default
spec:
  type: Scala
  mode: cluster
  image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.2
  mainClass: org.apache.spark.examples.SparkPi
  mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.2.jar
  arguments:
  - "5000"
  sparkVersion: 3.5.2
  driver:
    annotations:
      k8s.aliyun.com/eci-image-cache: "true"  # Aktifkan pembuatan dan pencocokan cache image otomatis.
    cores: 1
    coreLimit: 1200m
    memory: 512m
    serviceAccount: spark-operator-spark
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: type
              operator: In
              values:
              - virtual-kubelet
    tolerations:
    - key: virtual-kubelet.io/provider
      operator: Equal
      value: alibabacloud
      effect: NoSchedule
  executor:
    annotations:
      k8s.aliyun.com/eci-image-cache: "true"  # Aktifkan pembuatan dan pencocokan cache image otomatis.
    instances: 2
    cores: 2
    memory: 4g
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: type
              operator: In
              values:
              - virtual-kubelet
    tolerations:
    - key: virtual-kubelet.io/provider
      operator: Equal
      value: alibabacloud
      effect: NoSchedule

Pada eksekusi pertama, ECI membuat cache secara otomatis. Eksekusi berikutnya akan mencocokkan cache tersebut dan melewati proses pengambilan image.

Penerapan di produksi

  • Gunakan strategi ECS-first with ECI fallback untuk pekerjaan produksi. Menjaga beban kerja sensitif latensi di node ECS persisten, sementara ECI menyerap trafik burst tanpa perlu menyediakan node tambahan di muka.

  • Jalankan driver di ECS, executor di ECI. Kegagalan driver menyebabkan seluruh pekerjaan dimulai ulang. Simpan driver di node ECS yang stabil dan arahkan executor tanpa status ke instans ECI atau preemptible berbiaya lebih rendah.

  • Aktifkan caching image otomatis untuk pekerjaan berulang. Eksekusi pertama membuat cache; eksekusi berikutnya melewati pengambilan image, memangkas waktu startup dari sekitar 100 detik menjadi hampir instan.

  • Gunakan ResourcePolicy saat distribusi pod lintas jenis node harus tepat. Bidang max per unit membatasi jumlah pod, berguna untuk membatasi pengeluaran ECI per pengiriman pekerjaan.

Langkah selanjutnya