全部產品
Search
文件中心

Container Service for Kubernetes:基於實際剩餘資源的多叢集Spark作業調度與分發

更新時間:Apr 12, 2025

如果您已經擁有多個正在運行線上服務的ACK叢集,並希望在不影響這些服務的情況下,充分利用叢集的空閑資源來運行Spark作業,您可以利用ACK One艦隊的多叢集Spark作業調度和分發能力來提高資源使用率。本文將介紹如何通過ACK One艦隊和ACK Koordinator組件,根據各叢集實際剩餘資源(而非請求資源)來調度和分發多叢集Spark作業,協助您最大化多叢集中閑置資源的利用效率,並通過優先順序控制和離線混合部署能力,確保線上服務的正常運行。

背景資訊

基於叢集實際剩餘資源的多叢集Spark作業的調度和分發方案,主要依賴以下三部分能力:

  • ACK One艦隊的多叢集Spark作業的調度和分發,包括對實際剩餘資源的感知調度。

  • ACK Spark Operator支援Koordinator在離線混部特性。

  • ACK Koordinator的單叢集在離線混部能力。

整體流程如下:

  1. 將多個ACK叢集關聯到艦隊,並在各關聯集群中安裝ACK Koordinator組件和ACK Spark Operator組件。

  2. 為艦隊建立SparkApplicationPropagationPolicy

  3. 艦隊的多叢集調度組件(Global Scheduler)會根據每個關聯子叢集的剩餘資源,來匹配Spark作業資源請求完成調度。

    對叢集版本為1.28及以上的子叢集,艦隊支援通過資源預占來提高Spark作業調度的成功率。

  4. 艦隊調度完作業後,通過多叢集應用分發SparkApplication至調度選中的關聯集群中。

  5. 在關聯集群中,ACK Spark Operator負責運行Spark作業的driverexecutor。同時艦隊會監視子叢集中Spark作業運行狀態,若driver由於資源不足而無法運行,艦隊會在一定時間後回收該SparkApplication,並重調度到其他資源充足的關聯集群中。

前提條件

步驟一:在關聯集群中配置ack-koordinator

  1. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇組態管理 > 配置項

  3. 配置項頁面,單擊使用YAML建立資源,使用以下樣本內容添加配置。詳情請參見在離線混部快速入門

    #ConfigMap ack-slo-config範例。
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ack-slo-config
      namespace: kube-system
    data:
      colocation-config: |-
        {
          "enable": true
        }
      resource-qos-config: |-
        {
          "clusterStrategy": {
            "lsClass": {
              "cpuQOS": {
                "enable": true
              },
              "memoryQOS": {
                "enable": true
              },
              "resctrlQOS": {
                "enable": true
              }
            },
            "beClass": {
              "cpuQOS": {
                "enable": true
              },
              "memoryQOS": {
                "enable": true
              },
              "resctrlQOS": {
                "enable": true
              }
            }
          }
        }
      resource-threshold-config: |-
        {
          "clusterStrategy": {
            "enable": true
          }
        }

步驟二:(可選)在艦隊中建立命名空間,並下發到子叢集

在各子叢集安裝ack-spark-operator之前,需要確保各子叢集已有待分發的spark應用的命名空間,否則組件安裝會異常。可以通過在艦隊中建立命名空間,使用ClusterPropagationPolicy將其分發至各叢集。本文樣本命名空間為spark

  1. 使用艦隊的KubeConfig串連艦隊執行個體,執行以下命令,建立相應命名空間。

    kubectl create ns spark
  2. 使用ClusterPropagationPolicy將艦隊的命名空間下發至指定子叢集,如想下發到所有艦隊的關聯集群,可以省略clusterAffinity欄位整個內容。

    apiVersion: policy.one.alibabacloud.com/v1alpha1
    kind: ClusterPropagationPolicy
    metadata:
      name: ns-policy
    spec:
      resourceSelectors:
      - apiVersion: v1
        kind: Namespace
        name: spark
      placement:
        clusterAffinity:
          clusterNames:
          - ${cluster1-id} # 您的叢集ID。
          - ${cluster2-id} # 您的叢集ID。
        replicaScheduling:
          replicaSchedulingType: Duplicated

步驟三:在關聯集群中安裝ack-spark-operator

請在期望運行Spark作業的子叢集上安裝ack-spark-operator組件,且版本為2.1.2及以上。

  1. 登入Container Service管理主控台,在左側導覽列選擇市場 > 應用市場

  2. 應用市場頁面單擊應用目錄頁簽,然後搜尋並選中ack-spark-operator

  3. ack-spark-operator頁面,單擊一鍵部署

  4. 建立面板中,選擇叢集和命名空間,然後單擊下一步

  5. 參數配置頁面,設定相應參數,選擇Chart 版本為2.1.2或更高版本,jobNamespaces中添加spark,然後單擊確定

    重要

    必須將SparkApplication所在的namespace添加到spark.jobNamespaces

    下表列出了部分配置參數的說明。完整的參數配置詳情,您可以在ack-spark-operator頁面中的配置項查看。

    參數

    描述

    樣本值

    controller.replicas

    控制器副本數量。

    1(預設值)

    webhook.replicas

    Webhook副本數量。

    1(預設值)

    spark.jobNamespaces

    可運行Spark任務的命名空間列表。包含Null 字元串表示允許所有命名空間。多個命名空間使用英文半形逗號 , 隔開。

    • ["default"](預設值)

    • [""](所有命名空間)

    • ["ns1","ns2","ns3"](多個命名空間)

    spark.serviceAccount.name

    Spark作業會在spark.jobNamespaces指定的每個命名空間中自動建立名為spark-operator-spark的ServiceAccount和RBAC資源並進行相關授權。您可以自訂ServiceAccount名稱,後續提交Spark作業時請指定自訂建立的ServiceAccount名稱。

    spark-operator-spark(預設值)

步驟四:在艦隊上建立PriorityClass,並分發到子叢集

為了保證提交的Spark作業不會搶佔線上服務資源、影響線上服務產品的正常運行,建議對要提交的Spark作業設定低優先順序。

    1. 使用艦隊的KubeConfig,建立一個低優先順序的PriorityClass,其value設定為負數。

      apiVersion: scheduling.k8s.io/v1
      kind: PriorityClass
      metadata:
        name: low-priority
      value: -1000
      globalDefault: false
      description: "Low priority for Spark applications"
    2. 在艦隊中建立ClusterPropagationPolicy,將PriorityClass分發到指定叢集中。若您希望將PriorityClass分發到所有關聯集群,可以將clusterAffinity部分刪除。

      apiVersion: policy.one.alibabacloud.com/v1alpha1
      kind: ClusterPropagationPolicy
      metadata:
        name: priority-policy
      spec:
        preserveResourcesOnDeletion: false
        resourceSelectors:
        - apiVersion: scheduling.k8s.io/v1
          kind: PriorityClass
        placement:
          clusterAffinity:
            clusterNames:
            - ${cluster1-id} # 您的叢集ID。
            - ${cluster2-id} # 您的叢集ID。
      #      labelSelector:
      #        matchLabels:
      #          key: value
          replicaScheduling:
            replicaSchedulingType: Duplicated

步驟五:在艦隊中提交在離線混部策略的SparkApplicaiton

  1. 在艦隊中建立如下PropagationPolicy,可以將所有sparkoperator.k8s.io/v1beta2SparkApplication資源都分發到相應的叢集中,若要分發到所有關聯集群,可以省略clusterAffinity整個欄位內容。

    apiVersion: policy.one.alibabacloud.com/v1alpha1
    kind: PropagationPolicy
    metadata:
      name: sparkapp-policy 
      namespace: spark
    spec:
      preserveResourcesOnDeletion: false
      propagateDeps: true
      placement:
        clusterAffinity:
          clusterNames:
          - ${cluster1-id} # 您的叢集ID。
          - ${cluster2-id} # 您的叢集ID。
    #      labelSelector:
    #        matchLabels:
    #          key: value
        replicaScheduling:
          replicaSchedulingType: Divided
          customSchedulingType: Gang
      resourceSelectors:
        - apiVersion: sparkoperator.k8s.io/v1beta2
          kind: SparkApplication
  2. 在艦隊中建立Spark作業。可以通過在SparkApplication中添加註解 sparkoperator.k8s.io/koordinator-colocation: "true" 來標識driverexecutor是否需要根據實際剩餘資源進行調度。本例配置如下所示,表示driverexecutor都需要根據實際剩餘資源進行調度。

    apiVersion: sparkoperator.k8s.io/v1beta2
    kind: SparkApplication
    metadata:
      name: spark-pi
      namespace: spark
    spec:
      arguments:
      - "50000"
      driver:
        coreLimit: 1000m
        cores: 1
        memory: 512m
        priorityClassName: low-priority
        template:
          metadata:
            annotations:
              sparkoperator.k8s.io/koordinator-colocation: "true"
          spec:
            containers:
            - name: spark-kubernetes-driver
            serviceAccount: spark-operator-spark
      executor:
        coreLimit: 1000m
        cores: 1
        instances: 1
        memory: 1g
        priorityClassName: low-priority
        template:
          metadata:
            annotations:
              sparkoperator.k8s.io/koordinator-colocation: "true"
          spec:
            containers:
            - name: spark-kubernetes-executor
      image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.4
      mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.4.jar
      mainClass: org.apache.spark.examples.SparkPi
      mode: cluster
      restartPolicy:
        type: Never
      sparkVersion: 3.5.4
      type: Scala

步驟六:查看Spark作業狀態

  1. 在艦隊中執行以下命令,查看艦隊中Spark作業的狀態。

    kubectl get sparkapp -nspark

    預期輸出:

    NAME       STATUS    ATTEMPTS   START                  FINISH       AGE
    spark-pi   RUNNING   1          2025-03-05T11:19:43Z   <no value>   48s
  2. 在艦隊中執行以下命令,在事件中查看Spark作業調度至哪個關聯集群。

    kubectl describe sparkapp spark-pi  -nspark

    預期輸出:

    Normal   ScheduleBindingSucceed  2m29s                  default-scheduler                   Binding has been scheduled successfully. Result: {c6xxxxx:0,[{driver 1} {executor 1}]}
  3. 在艦隊中執行以下命令,查看資源調度分髮狀態。

    kubectl get rb  spark-pi-sparkapplication -nspark 

    預期輸出:

    NAME                        SCHEDULED   FULLYAPPLIED   OVERRIDDEN   ALLAVAILABLE   AGE
    spark-pi-sparkapplication   True        True           True         True     
  4. 在艦隊中執行以下命令,查看關聯集群中Spark作業的狀態。

    kubectl amc get sparkapp -M -nspark

    預期輸出:

    NAME       CLUSTER     STATUS      ATTEMPTS   START                  FINISH                 AGE   ADOPTION
    spark-pi   c6xxxxxxx   COMPLETED   1          2025-02-24T12:10:34Z   2025-02-24T12:11:20Z   61s   Y
  5. 在艦隊中執行以下命令,查看Pod狀態。

    kubectl amc get pod -M -nspark    

    預期輸出:

    NAME                               CLUSTER     READY   STATUS      RESTARTS   AGE
    spark-pi-3c0565956608ad6d-exec-1   c6xxxxxxx   1/1     Running            0          2m35s
    spark-pi-driver                    c6xxxxxxx   1/1     Running            0          2m50s
  6. 在艦隊中執行以下命令,查看關聯集群中Spark作業的詳情。

    kubectl amc get sparkapp spark-pi -m ${member clusterid} -oyaml -nspark