全部產品
Search
文件中心

Container Service for Kubernetes:啟用容器記憶體QoS

更新時間:Oct 25, 2024

Kubernetes支援以Request和Limit的形式來描述容器記憶體資源需求,應用的記憶體效能會受到多種因素影響,例如Page Cache回收、其他容器的過度使用,甚至引發節點資源不足而導致整機OOM,影響服務品質。ack-koordinator提供容器記憶體QoS功能,支援根據優先順序為容器設定服務品質參數,可以在確保記憶體資源公平性的前提下,優先保障高優先順序應用的效能。

說明

為了協助您更好地理解本文檔並使用本功能,推薦您參見Kubernetes官方文檔瞭解Pod Qos類為容器和 Pod 分配記憶體資源等概念。

功能介紹

為什麼需要容器記憶體QoS

在Kubernetes叢集,為了確保工作負載Pod能夠高效、安全地運行,Kubernetes在資源使用層面引入了資源請求Request和資源限制Limit模型,容器記憶體情況如下圖所示。

  • 記憶體Request(requests.memory):作用於調度階段,以確保為Pod找到一個具有足夠資源的合適節點。

  • 記憶體Limit(requests.memory):在單個節點層面進行約束,限制Pod記憶體使用量總量,對應cgroup檔案參數memory.limit_in_bytes,表示記憶體使用量上限。

容器在使用記憶體時,其服務品質會受自身用量以及節點用量兩個方面的影響。

  • 自身記憶體限制:當Pod自身的記憶體使用量(含Page Cache)接近聲明的Limit值時,會觸發記憶體子系統(Memcg)層級的直接記憶體回收,阻塞進程執行。如果此時的記憶體申請速度超過回收速度,容器會因觸發OOM而被異常終止。

  • 節點記憶體限制:容器的Limit參數可以高於Request。當多個容器部署在同一節點上時,可能會導致容器記憶體Limit之和超出節點物理總量。當整機記憶體用量較高時,同樣會觸發記憶體資源回收,影響應用效能,甚至在資源不足時,應用會因整機OOM而被異常終止。

功能特性

為了提高應用運行時效能和節點的穩定性,ack-koordinator組件結合不同Alibaba Cloud Linux核心版本提供了容器記憶體QoS保障的能力,支援依據Pod參數自動設定記憶體子系統(Memcg),為容器開啟Memcg QoSMemcg後台非同步回收Memcg全域最低水位線分級等特性,以保障容器的記憶體資源QoS和公平性。

容器記憶體回收及保障策略

容器的記憶體QoS支援多個cgroup參數配置。

  • memory.limit_in_bytes:記憶體使用量上限。

  • memory.high:記憶體限流閾值,核心會盡量回收記憶體,避免記憶體超過該值。

  • memory.wmark_high:記憶體後台非同步回收閾值(wmarkRatio),非同步回收當前可以回收的記憶體,以確保當前記憶體使用量量處於安全水位。

  • memory.min:記憶體使用量鎖定閾值,可配置絕對鎖定閾值(minLimitPercent)和相對鎖定閾值(lowLimitPercent)。

關於參數的詳細介紹及配置說明,請參見下文進階參數配置

容器記憶體QoS功能可以帶來以下功能特性。

  • Pod記憶體使用量接近Limit限制時,優先在後台非同步回收一部分記憶體,緩解直接記憶體回收帶來的效能影響。

  • Pod之間實施更公平的記憶體回收。當整機記憶體資源不足時,優先從記憶體超用的Pod中回收記憶體,避免個別Pod造成整機記憶體資源品質下降。

  • 整機資源回收時,優先保障延時敏感型LS(Latency-Sensitive)Pod,即Guaranteed、Burstable Pod的記憶體運行品質。

靈活配置、多環境適配

Kubernetes在社區1.22版本中提供的容器記憶體QoS(Memory QoS)特性,僅支援cgroup v2介面,您需要在kubelet上手動設定開啟,啟用後會對所有節點上的所有容器生效,無法進行更細粒度的配置。相比之下,ack-koordinator的容器記憶體QoS功能有以下能力最佳化。

  • 結合Alibaba Cloud Linux,相比社區額外提供記憶體後台回收、最低水位線分級等QoS增強能力,並自適應相容cgroup v1和cgroup v2介面。更多關於ACK容器記憶體QoS啟用的核心能力,請參見Alibaba Cloud Linux的核心功能與介面概述

  • 支援通過Pod Annotation或ConfigMap實現指定Pod維度、叢集全域維度或者命名空間維度容器記憶體QoS配置,更加靈活,使用簡單。

前提條件

費用說明

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

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

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

配置說明

當您為Pod開啟容器記憶體QoS時,記憶體cgroup參數將基於係數配置和Pod參數自適應調整。您可以參見下文,在單個Pod維度、叢集全域維度或叢集下命名空間維度開啟容器記憶體QoS並配置相關參數。

通過Annotation為指定Pod配置

您可以通過Pod Annotation為指定Pod開啟容器記憶體QoS功能。

annotations:
  # 設定為auto,表示開啟該Pod的容器記憶體QoS功能。
  koordinator.sh/memoryQOS: '{"policy": "auto"}'
  # 設定為none,表示關閉該Pod的容器記憶體QoS功能。
  koordinator.sh/memoryQOS: '{"policy": "none"}'

通過ConfigMap在叢集維度配置

您可以通過ConfigMap配置,在叢集維度開啟容器記憶體QoS,針對叢集全域生效。您可以根據應用特徵,使用koordinator.sh/qosClass來統一管理記憶體QoS參數,並在Pod Labelkoordinator.sh/qosClass配置Pod的QoS層級為LSBE等級,無需通過Pod Annotation重複配置。

  1. 參見以下樣本建立ConfigMap,開啟全叢集的容器記憶體QoS功能。

    apiVersion: v1
    data:
      resource-qos-config: |-
        {
          "clusterStrategy": {
            "lsClass": {
               "memoryQOS": {
                 "enable": true
               }
             },
            "beClass": {
               "memoryQOS": {
                 "enable": true
               }
             }
          }
        }
    kind: ConfigMap
    metadata:
      name: ack-slo-config
      namespace: kube-system
  2. 在Pod YAML中指定QoS等級為LSBE

    說明

    如果Pod中沒有指定koordinator.sh/qosClassack-koordinator將參考Pod原生的QoSClass來設定參數,其中Guaranteed為系統內部預設值,Burstable和Besteffort分別使用ConfigMap中LSBE的預設配置。

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-demo
      labels:
        koordinator.sh/qosClass: 'LS' # 指定Pod的QoS層級為LS。
  3. 查看命名空間kube-system下是否存在ConfigMap ack-slo-config

    • 存在:使用PATCH方式進行更新,避免幹擾ConfigMap中其他配置項。

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

      kubectl apply -f configmap.yaml
  4. (可選)參見下文進階參數配置配置進階參數。

通過ConfigMap在NameSpace維度配置

若您需要開啟或關閉部分命名空間下LSBE Pod的參數設定,可以參見以下流程,為指定Namespace內的Pod開啟或禁用容器記憶體QoS功能,在命名空間層級生效。

  1. 參見以下樣本建立ConfigMap,開啟全叢集的容器記憶體QoS功能。

    apiVersion: v1
    data:
      resource-qos-config: |-
        {
          "clusterStrategy": {
            "lsClass": {
               "memoryQOS": {
                 "enable": true
               }
             },
            "beClass": {
               "memoryQOS": {
                 "enable": true
               }
             }
          }
        }
    kind: ConfigMap
    metadata:
      name: ack-slo-config
      namespace: kube-system
  2. 使用以下ConfigMap內容,建立ack-slo-pod-config.yaml檔案。

    下方代碼以命名空間kube-system為例,展示如何開啟或禁用kube-system中Pod的容器記憶體QoS功能。

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ack-slo-pod-config
      namespace: kube-system # 首次使用時需要先手動建立該Namespace。
    data:
      # 單獨開啟或關閉部分Namespace的Pod。
      memory-qos: |
        {
          "enabledNamespaces": ["allow-ns"],
          "disabledNamespaces": ["block-ns"]
        }
  3. 執行以下命令,更新ConfigMap。

    kubectl patch cm -n kube-system ack-slo-pod-config --patch "$(cat ack-slo-pod-config.yaml)"
  4. (可選)參見下文進階參數配置配置進階參數。

操作步驟

本小節以一個Redis應用為例,使用以下評測環境進行測試,展示在記憶體超賣情境下,關閉或開啟ACK容器記憶體QoS時,樣本應用的時延和吞吐效能表現差異。

  • 使用ACK叢集Pro版

  • 叢集內包含兩個節點:壓測節點(規格為8 Core 32 GB)、測試節點(規格為8 Core 32 GB)。

驗證步驟

  1. 使用以下YAML內容,建立redis-demo.yaml檔案。

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: redis-demo-config
    data:
      redis-config: |
        appendonly yes
        appendfsync no
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: redis-demo
      labels:
        koordinator.sh/qosClass: 'LS' # 指定Redis執行個體的QoS層級為LS。
      annotations:
        koordinator.sh/memoryQOS: '{"policy": "auto"}' # 增加容器記憶體QoS的配置。
    spec:
      containers:
      - name: redis
        image: redis:5.0.4
        command:
          - redis-server
          - "/redis-master/redis.conf"
        env:
        - name: MASTER
          value: "true"
        ports:
        - containerPort: 6379
        resources:
          limits:
            cpu: "2"
            memory: "6Gi"
          requests:
            cpu: "2"
            memory: "2Gi"
        volumeMounts:
        - mountPath: /redis-master-data
          name: data
        - mountPath: /redis-master
          name: config
      volumes:
        - name: data
          emptyDir: {}
        - name: config
          configMap:
            name: redis-demo-config
            items:
            - key: redis-config
              path: redis.conf
      nodeName: # nodeName需修改為測試節點的nodeName。
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: redis-demo
    spec:
      ports:
      - name: redis-port
        port: 6379
        protocol: TCP
        targetPort: 6379
      selector:
        name: redis-demo
      type: ClusterIP
  2. 執行以下命令,部署Redis Server作為目標評測應用。

    您可通過Service redis-demo進行叢集內訪問。

    kubectl apply -f redis-demo.yaml
  3. 類比記憶體超賣情境。

    使用Stress工具製造較大的節點記憶體壓力,觸發系統記憶體回收,節點上已指派Pod的記憶體Limit之和已超過整機大小。

    1. 使用以下Pod YAML內容,建立stress-demo.yaml檔案。

      apiVersion: v1
      kind: Pod
      metadata:
        name: stress-demo
        labels:
          koordinator.sh/qosClass: 'BE' # 指定Stress執行個體的QoS層級為BE。
        annotations:
          koordinator.sh/memoryQOS: '{"policy": "auto"}' # 增加Memory QoS功能的配置。
      spec:
        containers:
          - args:
              - '--vm'
              - '2'
              - '--vm-bytes'
              - 11G
              - '-c'
              - '2'
              - '--vm-hang'
              - '2'
            command:
              - stress
            image: polinux/stress
            imagePullPolicy: Always
            name: stress
        restartPolicy: Always
        nodeName: # nodeName需修改為測試節點的nodeName,與Redis的節點相同。
    2. 使用以下命令,部署stress-demo。

      kubectl apply -f stress-demo.yaml
  4. 使用以下命令,查看系統的全域最低水位線。

    說明

    由於系統的全域最低水位線較低,對於記憶體超賣情境可能來不及回收就觸發整機OOM,因此通常配合較高的全域最低水位線使用。以記憶體32 GiB的測試機為例,設定最低水位線為4000000 KB。

    cat /proc/sys/vm/min_free_kbytes

    預期輸出:

    4000000
  5. 在Pod YAML中,使用memtier-benchmark壓測工具發送請求。

    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        name: memtier-demo
      name: memtier-demo
    spec:
      containers:
        - command:
            - memtier_benchmark
            - '-s'
            - 'redis-demo'
            - '--data-size'
            - '200000'
            - "--ratio"
            - "1:4"
          image: 'redislabs/memtier_benchmark:1.3.0'
          name: memtier
      restartPolicy: Never
      nodeName: # nodeName需修改為壓測節點的nodeName。
  6. 使用以下命令,收集memtier-benchmark測試結果。

    kubectl logs -f memtier-demo
  7. 在Pod YAML中,通過修改Redis執行個體和Stress執行個體的Pod Annotation,測試不同配置下的效能結果。

    apiVersion: v1
    kind: Pod
    metadata:
      name: redis-demo
      labels:
        koordinator.sh/qosClass: 'LS'
      annotations:
        koordinator.sh/memoryQOS: '{"policy": "none"}' # 配置關閉容器記憶體QoS。
    spec:
      ...
    
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: stress-demo
      labels:
        koordinator.sh/qosClass: 'BE'
      annotations:
        koordinator.sh/memoryQOS: '{"policy": "none"}' # 配置關閉容器記憶體QoS。
                            

結果分析

當功能全部關閉或開啟容器記憶體QoS時,指標的資料結果如下。

  • 全部關閉:不開啟容器記憶體QoS,Pod配置為none

  • 開啟容器記憶體QoS:Pod配置為auto,全部使用自適應配置。

重要

以下結果資料僅為理論值(參考值),實際資料以您的作業環境為準。

指標

全部關閉

開啟容器記憶體QoS

Latency-avg

51.32 ms

47.25 ms

Throughput-avg

149.0 MB/s

161.9 MB/s

由對比資料可得,在記憶體超賣情境下,開啟容器記憶體QoS後,Redis應用的時延(Latency)下降了7.9%,吞吐(Throughput)上漲了8.7%,時延和吞吐指標都得到一定的改善。

進階參數配置

容器記憶體QoS支援Pod層級和叢集層級的精細化配置,對於同時支援在Pod Annotation和ConfigMap配置的參數,Pod Annotation配置優先順序大於ConfigMap配置。如果Pod Annotation中沒有對應配置,ack-koordinator會進一步參考Namespace維度ConfigMap配置;如果Namespace維度沒有對應的配置,ack-koordinator會以叢集維度ConfigMap配置為準。

說明

AnnotationConfigMap兩列分別代表是否允許通過Pod Annotation或ConfigMap進行配置。其中,對代表支援,錯代表不支援。

參數

類型

取值範圍

說明

Pod Annotation

ConfigMap

enable

Boolean

  • true

  • false

  • true:叢集全域開啟容器記憶體QoS功能,相應QoS等級的容器啟用記憶體子系統的推薦配置。

  • false:叢集全域關閉容器記憶體QoS功能,相應QoS等級的容器的記憶體子系統配置會重設為建立初始值。

錯

對

policy

String

  • auto

  • default

  • none

  • auto:Pod開啟容器記憶體QoS功能並啟用推薦參數,生效優先順序高於叢集ConfigMap配置。

  • default:Pod繼承叢集ConfigMap配置。

  • none:Pod關閉容器記憶體QoS功能,相關記憶體子系統配置會重設為容器建立的初始值,生效優先順序高於叢集ConfigMap配置。

對

錯

minLimitPercent

Int

0~100

單位為百分比,預設值為0,表示關閉。

相較於記憶體Request,容器記憶體絕對鎖定、不被全域回收的比例。適合對Page Cache敏感的情境開啟,保留一部分檔案快取不被回收以改善讀寫效能。更多資訊,請參見Alibaba Cloud Linux cgroup v1介面支援memcg QoS功能

計算方式:memory.min=request*minLimitPercent/100。例如,容器Memory Request=100MiB,當minLimitPercent=100時,memory.min=104857600

對

對

lowLimitPercent

Int

0~100

單位為百分比,預設值為0,表示關閉。

相較於記憶體Request,容器記憶體相對鎖定、優先不被回收的比例。更多資訊,請參見Alibaba Cloud Linux cgroup v1介面支援memcg QoS功能

計算方式為memory.low=request*lowLimitPercent/100。例如,容器Memory Request=100MiB,當lowLimitPercent=100時,memory.low=104857600

對

對

throttlingPercent

Int

0~100

單位為百分比,預設值為0,表示關閉。

相較於記憶體Limit,容器記憶體使用量觸發限流的比例。超出限流閾值時,容器將進入較大壓力的主動記憶體回收狀態。適用於應用記憶體超賣的情境(Request<Limit),以規避cgroup層級的OOM。更多資訊,請參見Alibaba Cloud Linux cgroup v1介面支援memcg QoS功能

計算方式為memory.high=limit*throttlingPercent/100。例如,容器Memory Limit=100MiB,當throttlingPercent=80時,memory.high=83886080(80 MiB)

對

對

wmarkRatio

Int

0~100

單位為百分比,預設值為950表示關閉。超出非同步回收閾值時,容器將啟動後台記憶體回收。

相較於記憶體Limit和memory.high,容器觸發非同步記憶體非同步回收的比例。更多資訊,請參見Alibaba Cloud Linux Memcg後台非同步回收

計算方式為memory.wmark_high=limit(throttlingPercent開啟時為memory.high)*wmarkRatio/100。例如,容器Memory Limit=100MiB,當wmarkRatio=95,throttlingPercent=80時,記憶體限流閾值memory.high=83886080(80 MiB),後台回收係數memory.wmark_ratio=95,後台回收觸發閾值memory.wmark_high=79691776(76 MiB)

對

對

wmarkMinAdj

Int

-25~50

單位為百分比,預設值依據QoS,LS對應-25BE對應500表示關閉。

相較於(整機)全域記憶體最低水位線,容器所做出的調整比例。負數值讓容器更晚進入全域記憶體回收,正數值讓容器更早進入全域記憶體回收。更多資訊,請參見Alibaba Cloud Linux Memcg全域最低水位線分級

例如,如果Pod的QoS等級為LS,按預設配置,最低水位線分級係數memory.wmark_min_adj=-25,相應容器的最低水位線將下調25%。

對

對

FAQ

當前已經通過ack-slo-manager的舊版本協議使用了容器記憶體QoS功能,升級為ack-koordinator後是否繼續支援容器記憶體QoS功能?

舊版本(≤0.8.0)的Pod協議包括兩部分。

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

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

ack-koordinator保持了對以上舊版本協議的相容,您可以將組件無縫升級至ack-koordinatorack-koordinator將對以上舊版本協議相容至2023年7月30日,我們建議您將原協議資源欄位及時升級到新版本。

ack-koordinator各版本對記憶體QoS功能的適配如下。

組件版本

alibabacloud.com協議

koordinator.sh協議

≥0.3.0且<0.8.0

支援

不支援

≥0.8.0

支援

支援