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 QoS、Memcg後台非同步回收、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叢集,且符合以下條件:
已安裝ack-koordinator組件,且版本為0.8.0及以上。具體操作,請參見ack-koordinator(ack-slo-manager)。
費用說明
ack-koordinator組件本身的安裝和使用是免費的,不過需要注意的是,在以下情境中可能產生額外的費用:
配置說明
當您為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層級為LS
或BE
等級,無需通過Pod Annotation重複配置。
參見以下樣本建立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
在Pod YAML中指定QoS等級為
LS
或BE
。說明如果Pod中沒有指定
koordinator.sh/qosClass
,ack-koordinator將參考Pod原生的QoSClass來設定參數,其中Guaranteed
為系統內部預設值,Burstable和Besteffort分別使用ConfigMap中LS
和BE
的預設配置。apiVersion: v1 kind: Pod metadata: name: pod-demo labels: koordinator.sh/qosClass: 'LS' # 指定Pod的QoS層級為LS。
查看命名空間
kube-system
下是否存在ConfigMapack-slo-config
。存在:使用PATCH方式進行更新,避免幹擾ConfigMap中其他配置項。
kubectl patch cm -n kube-system ack-slo-config --patch "$(cat configmap.yaml)"
不存在:執行以下命令建立ConfigMap。
kubectl apply -f configmap.yaml
(可選)參見下文進階參數配置配置進階參數。
通過ConfigMap在NameSpace維度配置
若您需要開啟或關閉部分命名空間下LS
和BE
Pod的參數設定,可以參見以下流程,為指定Namespace內的Pod開啟或禁用容器記憶體QoS功能,在命名空間層級生效。
參見以下樣本建立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
使用以下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"] }
執行以下命令,更新ConfigMap。
kubectl patch cm -n kube-system ack-slo-pod-config --patch "$(cat ack-slo-pod-config.yaml)"
(可選)參見下文進階參數配置配置進階參數。
操作步驟
本小節以一個Redis應用為例,使用以下評測環境進行測試,展示在記憶體超賣情境下,關閉或開啟ACK容器記憶體QoS時,樣本應用的時延和吞吐效能表現差異。
使用ACK叢集Pro版。
叢集內包含兩個節點:壓測節點(規格為8 Core 32 GB)、測試節點(規格為8 Core 32 GB)。
驗證步驟
使用以下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
執行以下命令,部署Redis Server作為目標評測應用。
您可通過Service redis-demo進行叢集內訪問。
kubectl apply -f redis-demo.yaml
類比記憶體超賣情境。
使用Stress工具製造較大的節點記憶體壓力,觸發系統記憶體回收,節點上已指派Pod的記憶體Limit之和已超過整機大小。
使用以下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的節點相同。
使用以下命令,部署stress-demo。
kubectl apply -f stress-demo.yaml
使用以下命令,查看系統的全域最低水位線。
說明由於系統的全域最低水位線較低,對於記憶體超賣情境可能來不及回收就觸發整機OOM,因此通常配合較高的全域最低水位線使用。以記憶體32 GiB的測試機為例,設定最低水位線為4000000 KB。
cat /proc/sys/vm/min_free_kbytes
預期輸出:
4000000
在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。
使用以下命令,收集memtier-benchmark測試結果。
kubectl logs -f memtier-demo
在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 |
| 51.32 ms | 47.25 ms |
| 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配置為準。
Annotation和ConfigMap兩列分別代表是否允許通過Pod Annotation或ConfigMap進行配置。其中,代表支援,代表不支援。
參數 | 類型 | 取值範圍 | 說明 | Pod Annotation | ConfigMap |
| Boolean |
|
| ||
| String |
|
| ||
| Int | 0~100 | 單位為百分比,預設值為 相較於記憶體Request,容器記憶體絕對鎖定、不被全域回收的比例。適合對Page Cache敏感的情境開啟,保留一部分檔案快取不被回收以改善讀寫效能。更多資訊,請參見Alibaba Cloud Linux cgroup v1介面支援memcg QoS功能。 計算方式: | ||
| Int | 0~100 | 單位為百分比,預設值為 相較於記憶體Request,容器記憶體相對鎖定、優先不被回收的比例。更多資訊,請參見Alibaba Cloud Linux cgroup v1介面支援memcg QoS功能。 計算方式為 | ||
| Int | 0~100 | 單位為百分比,預設值為 相較於記憶體Limit,容器記憶體使用量觸發限流的比例。超出限流閾值時,容器將進入較大壓力的主動記憶體回收狀態。適用於應用記憶體超賣的情境(Request<Limit),以規避cgroup層級的OOM。更多資訊,請參見Alibaba Cloud Linux cgroup v1介面支援memcg QoS功能。 計算方式為 | ||
| Int | 0~100 | 單位為百分比,預設值為 相較於記憶體Limit和 計算方式為 | ||
| Int | -25~50 | 單位為百分比,預設值依據QoS, 相較於(整機)全域記憶體最低水位線,容器所做出的調整比例。負數值讓容器更晚進入全域記憶體回收,正數值讓容器更早進入全域記憶體回收。更多資訊,請參見Alibaba Cloud Linux Memcg全域最低水位線分級。 例如,如果Pod的QoS等級為LS,按預設配置,最低水位線分級係數 |
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-koordinator。ack-koordinator將對以上舊版本協議相容至2023年7月30日,我們建議您將原協議資源欄位及時升級到新版本。
ack-koordinator各版本對記憶體QoS功能的適配如下。
組件版本 | alibabacloud.com協議 | koordinator.sh協議 |
≥0.3.0且<0.8.0 | 支援 | 不支援 |
≥0.8.0 | 支援 | 支援 |