全部產品
Search
文件中心

Container Service for Kubernetes:自訂彈性資源優先順序調度

更新時間:Jun 19, 2024

自訂彈性資源優先順序調度是阿里雲提供的彈性調度策略。您可以在應用發布或擴容過程中,自訂資源策略(ResourcePolicy),設定應用執行個體Pod被調度到不同類型節點資源的順序。同時,在縮容過程中按照原調度順序逆序縮容。

重要

自調度器版本v1.x.x-aliyun-6.4開始,自訂彈性資源優先順序功能的ignorePreviousPod欄位的預設值將修改為False,ignoreTerminatingPod欄位的預設值將修改為True。涉及這些欄位的存量ResourcePolicy不受影響,後續更新也不受影響。

前提條件

  • Kubernetes叢集為ACK Pro且版本為1.20.11及以上。關於如何升級,請參見升級ACK叢集K8s版本

  • 對於不同ACK版本的叢集,調度器版本需要滿足以下要求。關於調度器各版本支援的功能,請參見kube-scheduler

    ACK版本

    調度器版本

    1.20

    v1.20.4-ack-7.0及以上

    1.22

    v1.22.15-ack-2.0及以上

    1.24及以上

    所有版本均支援

  • 需要使用ECI資源時,已部署ack-virtual-node。具體操作,請參見ACK使用ECI

使用限制

  • 本功能與pod-deletion-cost衝突,不能同時使用。關於pod-deletion-cost的更多資訊,請參見pod-deletion-cost

  • 本功能暫不支援與使用ECI彈性調度混合使用。關於ECI彈性調度的更多資訊,請參見使用ECI彈性調度

  • 本功能目前使用的是BestEffort策略,無法保證一定按照逆序縮容。

  • max欄位僅在叢集版本為1.22及以上,且調度器版本為5.0及以上的版本中開啟。

  • 與彈性節點池同時使用時,可能導致彈性節點池無效彈出節點。使用時請將彈性節點池包含在某個Unit中,且彈性節點池的Unit不要設定max欄位。

  • 若您的調度器為5.0版本以下或叢集版本為1.20及以下,請注意在ResourcePolicy建立前存在的Pod會在縮容時最先縮容。

  • 若您的調度器為6.1版本以下或叢集版本為1.20及以下,在與ResourcePolicy關聯的Pod未完全刪除時,請不要對ResourcePolicy進行修改。

使用方式

建立ResourcePolicy定義彈性資源優先順序:

apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
  name: test
  namespace: default
spec:
  ignorePreviousPod: false
  ignoreTerminatingPod: true
  matchLabelKeys:
  - pod-template-hash
  preemptPolicy: AfterAllUnits
  selector:
    key1: value1
  strategy: prefer
  units:
  - nodeSelector:
      unit: first
    resource: ecs
  - nodeSelector:
      unit: second
    max: 10
    resource: ecs
  - resource: eci
  whenTryNextUnits:
    policy: TimeoutOrExceedMax
    timeout: 1m
  • selector:聲明ResourcePolicy作用於同一命名空間下label上打了key1=value1的Pod。selector為空白時將對該命名空間下所有Pod生效。

  • strategy:調度策略選擇,目前只支援prefer

  • units:使用者自訂的調度單元。擴容時,將按照units下資源的順序進行擴容;縮容時,將按照逆序進行縮容。

    • resource:彈性資源的類型,目前支援eciecs以及elastic三種類型。elastic在叢集版本為1.24以上,且調度器版本為6.4.3及以上版本可用。

    • nodeSelector:用nodelabel標識該調度單元下的節點,只對ecs資源生效。

    • max(調度器為5.0版本及以上可用):在本調度單元中最多能調度的Pod的副本數。

  • preemptPolicy(調度器為6.1版本及以上可用):當ResourcePolicy中存在多個unit時,是否允許ResourcePolicy在每個Unit調度失敗時嘗試搶佔。BeforeNextUnit表示調度器將在每個Unit調度失敗時嘗試搶佔,AfterAllUnits表示ResourcePolicy只在最後一個Unit調度失敗時嘗試搶佔。預設為AfterAllUnits。

  • ignorePreviousPod(調度器為6.1版本及以上可用):需要與units中的max一起使用。該值為true時,在進行Pod數量統計時將忽略ResourcePolicy建立之前已經調度的Pod。

  • ignoreTerminatingPod(調度器為6.1版本及以上可用):需要與units中的max一起使用。該值為true時,在進行Pod數量統計時將忽略處於Terminating狀態的Pod。

  • matchLabelKeys(調度器為6.2版本及以上可用):需要與units中的max一起使用,Pod會根據自身Label的值進行分組,不同分組的Pod將適用於不同的max計數。當使用該功能時,若Pod上缺少任務matchLabelKeys中申明的Label,Pod將會被拒絕調度。

  • whenTryNextUnits(叢集版本1.24及以上,調度器為6.4版本及以上可用):描述Pod在何種情況下被允許使用後續Unit中的資源。

    • policy:代表Pod採用的策略。可選值包括ExceedMaxLackResourceAndNoTerminatingTimeoutOrExceedMaxLackResourceOrExceedMax(預設值)。

      • ExceedMax:若當前Unit的Max未設定,或當前Unit中的Pod數量大於等於設定的Max值,允許Pod使用下一級資源。該策略可以與自動調整以及ECI配合,達到優先嘗試節點池自動調整的效果。

        重要
        • 請注意,如果自動調整節點池長時間無法彈出節點,此策略可能導致Pod Pending。

        • 當前由於Cluster Autoscaler未感知ResourcePolicy的Max限制,實際彈出的執行個體數可能會多於設定的Max值。該問題將在後續版本中進行最佳化。

      • TimeoutOrExceedMax:當滿足以下條件之一:

        • 當前Unit的Max已設定且Unit中的Pod數量小於設定的Max值時;

        • 當前Unit的Max未設定,且當前Unit的Type為elastic

        若當前Unit資源不足以調度Pod,則在當前Unit中等待,等待時間的最大長度為timeout。該策略可以與自動調整以及ECI配合,達到優先嘗試節點池自動調整,並且在逾時後自動使用eci的效果。

      • 重要

        請注意,若Timeout期間內彈出節點,在Timeout期間內節點未達到Ready狀態,且Pod未容忍NotReady的汙點,則Pod仍然會被調度到ECI上。

      • LackResourceOrExceedMax:若當前Unit中的Pod數量大於等於設定的Max值,或當前Unit中已沒有多餘資源,允許Pod使用下一級資源。該策略為預設策略,適合大部分情境的基本需求。

      • LackResourceAndNoTerminating:若當前Unit中的Pod數量大於等於設定的Max值,或當前Unit中已沒有多餘資源,並且當前Unit中無處於Terminating狀態的Pod時,允許Pod使用下一級資源。該策略適合與變換策略配置使用,達到變換時不會由於Terminating導致新Pod滾動到後續Unit上的效果。

    • timeout:當policy為timeoutOrExceedMaxPolicy時,該欄位可以被用來描述逾時時間長度,當該欄位為空白值時,我們將此值視為15分鐘。

使用情境樣本

情境一:基於節點池優先順序調度

當您需要部署一個Deployment,此時叢集有兩個節點池,一個是節點池A,一個是節點池B。您希望優先調度節點池A,資源不足時調度節點池B。當進行縮容時,優先縮容在節點池B中的Pod,然後縮容節點池A中的Pod。如下樣本中,cn-beijing.10.0.3.137cn-beijing.10.0.3.138屬於節點池A, cn-beijing.10.0.6.47cn-beijing.10.0.6.46屬於節點池B,節點規格均為2核4 GB。基於節點池優先順序調度的具體操作步驟如下:

  1. 使用以下YAML內容,建立ResourcePolicy自訂節點池調度順序。

    apiVersion: scheduling.alibabacloud.com/v1alpha1
    kind: ResourcePolicy
    metadata:
      name: nginx
      namespace: default
    spec:
      selector:
        app: nginx # 此處要與後續建立的Pod的label相關聯。
      strategy: prefer
      units:
      - resource: ecs
        nodeSelector:
          alibabacloud.com/nodepool-id: np7ec79f2235954e879de07b780058****
      - resource: ecs
        nodeSelector:
          alibabacloud.com/nodepool-id: npab2df797738644e3a7b7cbf532bb****
    說明

    節點池ID可以從所在叢集的節點管理 > 節點池中擷取。具體操作,請參見建立節點池

  2. 使用以下YAML內容建立Deployment,部署2個Pod。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          name: nginx
          labels:
            app: nginx # 此處要與上一步建立的ResourcePolicy的selector相關聯。
        spec:
          containers:
          - name: nginx
            image: nginx
            resources:
              limits:
                cpu: 2
              requests:
                cpu: 2
  3. 建立應用Nginx並查看部署結果。

    1. 執行以下命令,建立應用Nginx。

      kubectl apply -f nginx.yaml

      預期輸出:

      deployment.apps/nginx created
    2. 執行以下命令,查看部署結果。

      kubectl get pods -o wide

      預期輸出:

      NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running   0          17s   172.29.112.216   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-k****   1/1     Running   0          17s   172.29.113.24    cn-beijing.10.0.3.138   <none>           <none>

      由預期輸出得到,前兩個Pod被調度在節點池A的節點上。

  4. 對Pod進行擴容。

    1. 執行以下命令,將Pod擴容到4個。

      kubectl scale deployment nginx --replicas 4                      

      預期輸出:

      deployment.apps/nginx scaled
    2. 執行以下命令,查看Pod狀態。

      kubectl get pods -o wide

      預期輸出:

      NAME                    READY   STATUS    RESTARTS   AGE    IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running   0          101s   172.29.112.216   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-k****   1/1     Running   0          101s   172.29.113.24    cn-beijing.10.0.3.138   <none>           <none>
      nginx-9cdf7bbf9-m****   1/1     Running   0          18s    172.29.113.156   cn-beijing.10.0.6.47    <none>           <none>
      nginx-9cdf7bbf9-x****   1/1     Running   0          18s    172.29.113.89    cn-beijing.10.0.6.46    <none>           <none>

      由預期輸出得到,當節點池A的節點資源不足時,調度到節點池B的節點上。

  5. 對Pod進行縮容。

    1. 執行以下命令,將Pod從4個副本縮容到2個。

      kubectl scale deployment nginx --replicas 2

      預期輸出:

      deployment.apps/nginx scaled
    2. 執行以下命令,查看Pod狀態。

      kubectl get pods -o wide

      預期輸出:

      NAME                    READY   STATUS        RESTARTS   AGE     IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running       0          2m41s   172.29.112.216   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-k****   1/1     Running       0          2m41s   172.29.113.24    cn-beijing.10.0.3.138   <none>           <none>
      nginx-9cdf7bbf9-m****   0/1     Terminating   0          78s     172.29.113.156   cn-beijing.10.0.6.47    <none>           <none>
      nginx-9cdf7bbf9-x****   0/1     Terminating   0          78s     172.29.113.89    cn-beijing.10.0.6.46    <none>           <none>

      由預期輸出得到,根據調度的逆序,優先縮容在節點池B中的Pod。

情境二:ECS和ECI混合調度

當您需要部署一個Deployment,此時叢集中有3種類型的資源,分別是訂用帳戶的ECS、隨用隨付的ECS和彈性執行個體ECI。為了降低資源使用成本,您希望部署的服務優先調度順序依次為:訂用帳戶的ECS、隨用隨付的ECS、彈性執行個體ECI。同時在服務縮容時優先刪除ECI上的Pod,釋放ECI的節點資源,然後刪除隨用隨付的ECS上的Pod,最後刪除訂用帳戶的ECS上的Pod。樣本節點為2核4 GB,ECS和ECI混合調度的具體操作步驟如下:

  1. 執行以下命令,對不同付費類型的節點分別打不同的label(此處也可以通過節點池的功能自動標識label)。

    kubectl label node cn-beijing.10.0.3.137 paidtype=subscription
    kubectl label node cn-beijing.10.0.3.138 paidtype=subscription
    kubectl label node cn-beijing.10.0.6.46 paidtype=pay-as-you-go
    kubectl label node cn-beijing.10.0.6.47 paidtype=pay-as-you-go
  2. 使用以下YAML內容,建立ResourcePolicy自訂節點池調度順序。

    apiVersion: scheduling.alibabacloud.com/v1alpha1
    kind: ResourcePolicy
    metadata:
      name: nginx
      namespace: default
    spec:
      selector:
        app: nginx # 此處要與後續建立的Pod的label相關聯。
      strategy: prefer
      units:
      - resource: ecs
        nodeSelector:
          paidtype: subscription
      - resource: ecs
        nodeSelector:
          paidtype: pay-as-you-go
      - resource: eci
  3. 使用以下YAML內容建立Deployment,部署2個Pod。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          name: nginx
          labels:
            app: nginx # 此處要上一步建立的ResourcePolicy的selector相關聯。
        spec:
          containers:
          - name: nginx
            image: nginx
            resources:
              limits:
                cpu: 2
              requests:
                cpu: 2
  4. 建立應用Nginx並查看部署結果。

    1. 執行以下命令,建立應用Nginx。

      kubectl apply -f nginx.yaml

      預期輸出:

      deployment.apps/nginx created
    2. 執行以下命令,查看部署結果。

      kubectl get pods -o wide

      預期輸出:

      NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running   0          66s   172.29.112.215   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running   0          66s   172.29.113.23    cn-beijing.10.0.3.138   <none>           <none>

      由預期輸出得到,前兩個Pod被調度到labelpaidtype=subscription的節點上。

  5. 對Pod進行擴容。

    1. 執行以下命令,將Pod擴容到4個。

      kubectl scale deployment nginx --replicas 4

      預期輸出:

      deployment.apps/nginx scaled
    2. 執行以下命令,查看Pod狀態。

      kubectl get pods -o wide

      預期輸出:

      NAME                    READY   STATUS    RESTARTS   AGE     IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-4****   1/1     Running   0          16s     172.29.113.155   cn-beijing.10.0.6.47    <none>           <none>
      nginx-9cdf7bbf9-b****   1/1     Running   0          3m48s   172.29.112.215   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-f****   1/1     Running   0          16s     172.29.113.88    cn-beijing.10.0.6.46    <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running   0          3m48s   172.29.113.23    cn-beijing.10.0.3.138   <none>           <none>

      由預期輸出得到,當labelpaidtype=subscription的節點資源不足時,調度到labelpaidtype=pay-as-you-go的節點上。

    3. 執行以下命令,將Pod擴容到6個。

      kubectl scale deployment nginx --replicas 6

      預期輸出:

      deployment.apps/nginx scaled
    4. 執行以下命令,查看Pod狀態。

      kubectl get pods -o wide

      預期輸出:

      NAME                    READY   STATUS    RESTARTS   AGE     IP               NODE                           NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-4****   1/1     Running   0          3m10s   172.29.113.155   cn-beijing.10.0.6.47           <none>           <none>
      nginx-9cdf7bbf9-b****   1/1     Running   0          6m42s   172.29.112.215   cn-beijing.10.0.3.137          <none>           <none>
      nginx-9cdf7bbf9-f****   1/1     Running   0          3m10s   172.29.113.88    cn-beijing.10.0.6.46           <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running   0          6m42s   172.29.113.23    cn-beijing.10.0.3.138          <none>           <none>
      nginx-9cdf7bbf9-s****   1/1     Running   0          36s     10.0.6.68        virtual-kubelet-cn-beijing-j   <none>           <none>
      nginx-9cdf7bbf9-v****   1/1     Running   0          36s     10.0.6.67        virtual-kubelet-cn-beijing-j   <none>           <none>

      由預期輸出得到,ECS上的資源不足,Pod被調度ECI的資源上。

  6. 對Pod進行縮容。

    1. 執行以下命令,將Pod從6個副本縮容到4個。

      kubectl scale deployment nginx --replicas 4

      預期輸出:

      deployment.apps/nginx scaled
    2. 執行以下命令,命令查看Pod狀態。

      kubectl get pods -o wide

      預期輸出:

      NAME                    READY   STATUS        RESTARTS   AGE     IP               NODE                           NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-4****   1/1     Running       0          4m59s   172.29.113.155   cn-beijing.10.0.6.47           <none>           <none>
      nginx-9cdf7bbf9-b****   1/1     Running       0          8m31s   172.29.112.215   cn-beijing.10.0.3.137          <none>           <none>
      nginx-9cdf7bbf9-f****   1/1     Running       0          4m59s   172.29.113.88    cn-beijing.10.0.6.46           <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running       0          8m31s   172.29.113.23    cn-beijing.10.0.3.138          <none>           <none>
      nginx-9cdf7bbf9-s****   1/1     Terminating   0          2m25s   10.0.6.68        virtual-kubelet-cn-beijing-j   <none>           <none>
      nginx-9cdf7bbf9-v****   1/1     Terminating   0          2m25s   10.0.6.67        virtual-kubelet-cn-beijing-j   <none>           <none>

      由預期輸出得到,根據調度節點的逆序,優先縮容在ECI上的Pod。

    3. 執行以下命令,將4個副本縮容到2個。

      kubectl scale deployment nginx --replicas 2

      預期輸出:

      deployment.apps/nginx scaled
    4. 執行以下命令,查看Pod狀態。

      kubectl get pods -o wide

      預期輸出:

      NAME                    READY   STATUS        RESTARTS   AGE     IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-4****   0/1     Terminating   0          6m43s   172.29.113.155   cn-beijing.10.0.6.47    <none>           <none>
      nginx-9cdf7bbf9-b****   1/1     Running       0          10m     172.29.112.215   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-f****   0/1     Terminating   0          6m43s   172.29.113.88    cn-beijing.10.0.6.46    <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running       0          10m     172.29.113.23    cn-beijing.10.0.3.138   <none>           <none>

      由預期輸出得到,根據調度節點的逆序,優先縮容位於labelpaidtype=pay-as-you-go節點上的Pod。

    5. 執行以下命令,查看Pod狀態。

      kubectl get pods -o wide

      預期輸出:

      NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
      nginx-9cdf7bbf9-b****   1/1     Running   0          11m   172.29.112.215   cn-beijing.10.0.3.137   <none>           <none>
      nginx-9cdf7bbf9-r****   1/1     Running   0          11m   172.29.113.23    cn-beijing.10.0.3.138   <none>           <none>

      由預期輸出得到,當前只存在labelpaidtype=subscription節點上的Pod。

相關文檔

  • 在ACK叢集中部署服務時,您可以使用容忍度和節點親和性來聲明只使用ECS或ECI彈性資源,或者是在ECS資源不足時自動申請ECI資源。通過配置調度策略,您可以在不同工作負載情境下實現對彈性資源的不同需求。詳細資料,請參見指定ECS和ECI的資源分派

  • 高可用以及高效能是分布式任務執行過程中的重要要求。在ACK叢集Pro版中,您可以通過Kubernetes原生調度語義實現分布式任務的跨可用性區域打散,以達到高可用性區域部署的要求,或者通過Kubernetes原生調度語義實現分布式任務在指定可用性區域中的親和性部署,以達到高效能部署的要求。詳細資料,請參見實現ECI Pod可用性區域打散以及親和調度