全部產品
Search
文件中心

Container Service for Kubernetes:動態資源超賣

更新時間:Jun 19, 2024

ack-koordinator提供動態資源超賣功能,通過對節點負載資料的即時收集,可以充分挖掘叢集中已指派但未使用的資源量,以實現對叢集資源的動態超賣。本文主要介紹如何使用動態資源超賣功能。

前提條件

費用說明

ack-koordinator組件本身的安裝和使用是免費的,不過需要注意的是,在以下情境中可能產生額外的費用:

  • ack-koordinator是非託管組件,安裝後將佔用Worker節點資源。您可以在安裝組件時配置各模組的資源申請量。

  • ack-koordinator預設會將資源畫像、精細化調度等功能的監控指標以Prometheus的格式對外透出。若您配置組件時開啟了ACK-Koordinator開啟Prometheus監控指標選項並使用了阿里雲Prometheus服務,這些指標將被視為自訂指標併產生相應費用。具體費用取決於您的叢集規模和應用數量等因素。建議您在啟用此功能前,仔細閱讀阿里雲Prometheus計費說明,瞭解自訂指標的免費額度和收費策略。您可以通過賬單和用量查詢,監控和管理您的資源使用方式。

背景資訊

在Kubernetes系統中,Kubelet通過參考Pod的QoS等級來管理單機容器的資源品質,例如OOM(Out of Memory)優先順序控制等。Pod的QoS層級分為Guaranteed、Burstable和BestEffort。QoS層級並不是顯式定義,而是取決於Pod配置的Request和Limit(CPU、記憶體)。

為了提高穩定性,應用管理員在提交Guaranteed和Burstable這兩類Pod時會預留相當數量的資源Buffer來應對上下遊鏈路的負載波動,在大部分時間段,容器的Request會遠高於實際的資源使用率。為了提升叢集資源使用率,應用管理員會提交一些QoS為BestEffort的低優任務,來充分使用那些已指派但未使用的資源,實現對叢集資源的超賣,其缺點如下:

  • 節點可容納低優任務的資源量沒有任何參考,即使節點實際負載已經很高,由於BestEffort任務在資源規格上缺少容量約束,仍然會被調度到節點上運行。

  • BestEffort任務間缺乏公平性保證,任務資源規格存在區別,但無法在Pod描述上體現。

缺點

針對以上問題,ACK的差異化SLO(Service Level Objectives)提供了將這部分資源量化的能力。將上圖中的紅線定義為Usage,藍線到紅線預留部分資源定義為Buffered,綠色覆蓋部分定義為Reclaimed。

如下圖所示,Reclaimed資源代表可動態超賣的資源量。ack-koordinator會根據節點真實負載情況動態更新,並以標準擴充資源的形式即時更新到K8s的Node元資訊中。低優的BestEffort任務可以通過在Request和Limit中定義的Reclaimed資源配置來使用這部分資源,這部分配置同時也會體現在節點側的資源限制參數上,保證BestEffort作業之間的公平性。

為體現與原生資源類型的差異性,ack-koordinator使用“Batch”優先順序的概念描述該部分超賣資源,以下簡稱batch-cpu和batch-memory。

動態資源超賣

使用限制

組件

版本要求

Kubernetes

≥v1.18

ack-koordinator

≥0.8.0

Helm版本

≥v3.0

操作步驟

  1. 使用以下命令,查看當前Batch資源總量。

    查看前請確保對應配置已經開啟,詳見步驟3中的描述。

    # 將$nodeName替換為要查詢的目標節點名稱。
    kubectl get node $nodeName -o yaml

    預期輸出:

    #Node
    status:
      allocatable:
        # 單位為千分之一核,以下表示50核。
        kubernetes.io/batch-cpu: 50000
        # 單位為位元組,以下表示50 GB。
        kubernetes.io/batch-memory: 53687091200
  2. 建立Pod並申請Batch資源。在Label中指定QoS等級,並在Request和Limit中添加對應的Batch資源配置,即可讓Pod使用動態超賣資源,具體樣本如下。

    #Pod
    metadata:
      labels:
        # 必填,標記為低優先順序Pod。
        koordinator.sh/qosClass: "BE"
    spec:
      containers:
      - resources:
          requests:
            # 單位為千分之一核,如下表示1核。
            kubernetes.io/batch-cpu: "1k"
            # 單位為位元組,如下表示1 GB。
            kubernetes.io/batch-memory: "1Gi"
          limits:
            kubernetes.io/batch-cpu: "1k"
            kubernetes.io/batch-memory: "1Gi"

    申請Batch資源需注意:

    • 若您通過Deployment或其它類型工作負載提交Pod,只需在對應的模板欄位中參照上述樣本,採用相同格式填寫即可。同一個Pod不能同時申請Batch資源和普通的CPU或Memory資源。

    • 由於節點的Batch資源總量根據當前實際負載動態計算得到,在邊界情況下可能會因Kubelet未及時同步而被拒絕,此時您可以直接將被拒絕的Pod進行刪除。

    • 受K8s的約束,擴充資源必須以整數形式表達,因此batch-cpu資源需要以千分之一核為單位進行配置。

  3. 管理動態超賣資源。

    節點的Batch容量根據實際的資源使用率情況動態計算得到,CPU和記憶體維度預設的計算過程可以按如下公式簡單推導:

    nodeBatchAllocatable = nodeAllocatable * thresholdPercent - podUsage(non-BE) - systemUsage

    計算公式中各因子的含義如下:

    • nodeAllocatable:節點可分配資源總量。

    • thresholdPercent:預留水位比例。

    • podUsage(non-BE):高優先順序Pod的資源用量,即非BE類型Pod的資源使用量。

    • systemUsage:節點系統資源真實用量。

    同時,對於記憶體維度資源超賣,ack-koordinator還支援按請求量(Request)計算,具體配置參考後文有關memoryCalculatePolicy的描述,公式如下。其中podRequest(non-BE)表示高優先順序Pod的資源請求量,即非BE類型Pod的資源請求量(Request)之和。

    nodeBatchAllocatable = nodeAllocatable * thresholdPercent - podRequest(non-BE) - systemUsage

    公式中的thresholdPercent為可配置參數,通過修改ConfigMap中的配置項可以實現對資源的靈活管理,配置樣本及詳細說明如下。

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ack-slo-config
      namespace: kube-system
    data:
      colocation-config: |
        {
          "enable": true,
          "metricAggregateDurationSeconds": 60,
          "cpuReclaimThresholdPercent": 60,
          "memoryReclaimThresholdPercent": 70,
          "memoryCalculatePolicy": "usage"
        }

    欄位名稱

    格式

    含義

    enable

    Boolean

    表示是否開啟節點Batch資源的動態更新,關閉時Batch資源量會被重設為0。預設值為 false

    metricAggregateDurationSeconds

    Int

    Batch資源最小更新頻率,單位為秒。通常建議保持為1分鐘不必修改。

    cpuReclaimThresholdPercent

    Int

    計算節點batch-cpu資源容量時的預留係數。預設值為65,單位為百分比。

    memoryReclaimThresholdPercent

    Int

    計算節點batch-memory資源容量時的預留係數。預設值為65,單位為百分比。

    memoryCalculatePolicy

    String

    計算節點batch-memory資源容量時的策略。

    • "usage":預設值,表示batch-memory記憶體資源按照高優先順序Pod的記憶體真實用量計算,包括了節點未申請的資源,以及已申請但未使用的資源量。

    • "request":表示batch-memory記憶體資源按照高優先順序Pod的記憶體請求量計算,僅包括節點未申請的資源。

    說明

    ack-koordinator在單機端提供了針對Batch資源的壓制和驅逐能力,包括彈性資源限制容器記憶體QoS容器L3 Cache及記憶體頻寬隔離,能夠有效避免低優的BestEffort容器帶來的幹擾問題。

  4. 查看命名空間kube-system下是否存在ConfigMap ack-slo-config

    • 若存在ConfigMap ack-slo-config,請使用PATCH方式進行更新,避免幹擾ConfigMap中其他配置項。

      kubectl patch cm -n kube-system ack-slo-config --patch "$(cat configmap.yaml)"
    • 若不存在ConfigMap ack-slo-config,請執行以下命令進行建立Configmap。

      kubectl apply -f configmap.yaml
  5. (可選)通過Prometheus查看Batch資源使用方式。

    如果您首次使用該功能的大盤,請確保動態資源超賣大盤已經升級到最新版本。關於升級的具體操作,請參見相關操作

    通過ACK控制台Prometheus監控查看Batch資源使用方式的具體操作如下:

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

    2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇營運管理 > Prometheus 監控

    3. Prometheus監控頁面,單擊成本分析/資源最佳化頁簽,然後單擊在離線混部頁簽。

      您可以在在離線混部頁簽查看詳細資料,包括叢集以及單個節點的Batch總量和已申請量。更多資訊,請參見基礎監控

    # 節點batch-cpu可分配總量。
    koordlet_node_resource_allocatable{resource="kubernetes.io/batch-cpu",node="$node"}
    # 節點batch-cpu已指派量。
    koordlet_container_resource_requests{resource="kubernetes.io/batch-cpu",node="$node"}
    # 節點batch-memory可分配總量。
    kube_node_status_allocatable{resource="kubernetes.io/batch-memory",node="$node"}
    # 節點batch-memory已指派量。
    koordlet_container_resource_requests{resource="kubernetes.io/batch-memory",node="$node"}

使用範例

  1. 使用以下命令,查看節點Reclaimed資源總量。

    查看前請確保對應配置已經開啟,詳見步驟3中的描述。

    kubectl get node $nodeName -o yaml

    預期輸出:

    #Node資訊
    status:
      allocatable:
        # 單位為千分之一核,以下表示50核。
        kubernetes.io/batch-cpu: 50000
        # 單位為位元組,以下表示50 GB。
        kubernetes.io/batch-memory: 53687091200
  2. 使用以下YAML內容,建立名為be-pod-demo.yaml檔案。

    apiVersion: v1
    kind: Pod
    metadata:
      lables:
        koordinator.sh/qosClass: "BE"
      name: be-demo
    spec:
      containers:
      - command:
        - "sleep"
        - "100h"
        image: polinux/stress
        imagePullPolicy: Always
        name: be-demo
        resources:
          limits:
            kubernetes.io/batch-cpu: "50k"
            kubernetes.io/batch-memory: "10Gi"
          requests:
            kubernetes.io/batch-cpu: "50k"
            kubernetes.io/batch-memory: "10Gi"
      schedulerName: default-scheduler
  3. 使用以下命令,部署be-pod-demo作為目標評測應用。

    kubectl apply -f be-pod-demo.yaml
  4. 在單機端的cgroup分組中查看BE Pod資源限制的生效情況。

    1. 使用以下命令,查看CPU資源限制參數。

      cat /sys/fs/cgroup/cpu,cpuacct/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod4b6e96c8_042d_471c_b6ef_b7e0686a****.slice/cri-containerd-11111c202adfefdd63d7d002ccde8907d08291e706671438c4ccedfecba5****.scope/cpu.cfs_quota_us

      預期輸出:

      #容器對應的CPU Cgroup為50核。
      5000000
    2. 使用以下命令,查看Memory資源限制參數。

      cat /sys/fs/cgroup/memory/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod4b6e96c8_042d_471c_b6ef_b7e0686a****.slice/cri-containerd-11111c202adfefdd63d7d002ccde8907d08291e706671438c4ccedfecba5****.scope/memory.limit_in_bytes

      預期輸出:

      #容器對應的Memory Cgroup為10 GB。
      10737418240

常見問題

當前已通過ack-slo-manager的舊版本協議使用了動態資源超賣功能,升級為ack-koordinator後是否繼續支援?

舊版本的動態資源超賣協議包括兩部分:

  • 在Pod的Annotation中填寫的alibabacloud.com/qosClass

  • 在Pod的Request和Limit中填寫的alibabacloud.com/reclaimed

ack-koordinator相容以上舊版本協議,並在ACK Pro調度器中統一計算新舊版本協議的資源申請量和可用量。您可將組件無縫升級至ack-koordinator。

說明

ack-koordinator對舊版本協議的相容期限截止至2023年07月30日。強烈建議您將原協議資源欄位及時升級到新版本。

ACK Pro調度器和ack-koordinator對各版本協議的適配如下。

ACK調度器版本

ack-koordinator版本(ack-slo-manager)

alibabacloud.com協議

koordinator.sh協議

≥1.18且<1.22.15-ack-2.0

≥0.3.0

支援

不支援

≥1.22.15-ack-2.0

≥0.8.0

支援

支援

應用使用了Batch資源後,記憶體資源用量突然變得更高是什麼原因?

對於在Pod資源限制Limit中配置了kubernetes.io/batch-memory的應用(簡稱batch limit),koordinator會等待容器建立後根據batch limit在節點上為其設定cgroup限制參數。由於部分應用在啟動時會根據容器cgroup參數自動申請記憶體,若應用在cgroup的memory.limit參數設定前就啟動完成,其記憶體的真實用量可能會超過batch limit。而受作業系統約束,這時容器的記憶體cgroup參數將無法設定成功,直至其真實用量降低至batch limit以下才會設定成功。

對於這種情況,我們建議適當修改應用配置參數,控制其記憶體真實用量在batch limit以下,或在應用啟動指令碼中首先檢查記憶體限制參數,確認設定完成後再啟動,確保應用的記憶體用量得到合理限制,避免出現OOM等情況。

在容器內執行以下命令,可以查看記憶體資源限制參數。

# 單位為位元組
cat /sys/fs/cgroup/memory/memory.limit_in_bytes 
1048576000