在同一節點上同時運行多個Pod時,Pod之間可能會因為CPU資源的爭搶帶來頻繁的上下文切換,導致性能抖動。針對性能敏感型應用,您可以啟用CPU拓撲感知調度功能,將Pod固定在節點的CPU Core上運行,緩解因CPU上下文切換、跨NUMA訪存導致的應用性能下降問題。
為了幫助您更好地理解本文檔并使用本功能,推薦您參見Kubernetes官方文檔了解Pod Qos類、為容器和 Pod 分配內存資源、節點上的CPU管理策略(例如CPU管理策略、none
策略、static
策略)等概念。
使用場景
在Kubernetes集群中,多個Pod會在同一個節點上共享CPU核心。但在以下場景中,某些應用可能需要固定在部分CPU核心上運行。
應用尚未完成對云原生場景的適配,例如在設置線程數量時未考慮容器規格(而是整機物理核數量),導致應用出現性能下降問題。
應用運行在神龍裸金屬(Intel、AMD)等多核機器上,且出現大量因跨NUMA訪存帶來的應用性能下降問題。
應用對CPU上下文切換十分敏感,無法承受因此帶來的性能抖動。
雖然Kubernetes提供了CPU Manager以解決此問題,支持為對CPU親和性和性能有更高要求的應用配置static
策略,允許這些應用獨占節點上的特定CPU Core,以獲得穩定的計算資源。但CPU Manager僅提供節點維度的CPU調度選擇,無法在集群維度選擇最優的CPU Core組合。此外,通過CPU Manager為應用配置static
策略時,Pod僅支持對Guaranteed類型的Pod生效,即Pod中的每個容器必須聲明了CPU Request和CPU Limit且兩者取值相等,無法適用于其他類型的Pod,包括Burstable和BestEffort。
為此,ACK集群基于新版的Scheduling Framework實現了CPU拓撲感知調度功能,支持通過Pod Annotation直接啟用,以更好地保障CPU敏感型工作負載的服務性能。
前提條件
已創建ACK集群Pro版,且節點池的CPU Policy為None,請參見創建ACK Pro版集群。
已安裝ack-koordinator組件,且組件版本為0.2.0及以上,請參見ack-koordinator。
費用說明
ack-koordinator組件本身的安裝和使用是免費的,不過需要注意的是,在以下場景中可能產生額外的費用:
ack-koordinator是非托管組件,安裝后將占用Worker節點資源。您可以在安裝組件時配置各模塊的資源申請量。
ack-koordinator默認會將資源畫像、精細化調度等功能的監控指標以Prometheus的格式對外透出。若您配置組件時開啟了ACK-Koordinator開啟Prometheus監控指標選項并使用了阿里云Prometheus服務,這些指標將被視為自定義指標并產生相應費用。具體費用取決于您的集群規模和應用數量等因素。建議您在啟用此功能前,仔細閱讀阿里云Prometheus計費說明,了解自定義指標的免費額度和收費策略。您可以通過賬單和用量查詢,監控和管理您的資源使用情況。
步驟一:部署示例應用
本文以一個Nginx應用為例,介紹如何啟用CPU拓撲感知調度,實現CPU綁核。
使用以下YAML示例,部署一個Nginx應用。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: nodeSelector: policy: intel containers: - name: nginx image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/nginx_optimized:20240221-1.20.1-2.3.0 ports: - containerPort: 80 resources: requests: cpu: 4 memory: 8Gi limits: cpu: 4 memory: 8Gi volumeMounts: - mountPath: /etc/nginx/nginx.conf name: nginx subPath: nginx.conf volumes: - name: nginx configMap: name: nginx-configmap items: - key: nginx_conf path: nginx.conf
在Pod對應的節點上,執行以下命令,查看當前容器的CPU核心綁定情況。
# 具體路徑可根據Pod的UID以及Container的ID拼接得到。 cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podf9b79bee_eb2a_4b67_befe_51c270f8****.slice/cri-containerd-aba883f8b3ae696e99c3a920a578e3649fa957c51522f3fb00ca943dc2c7****.scope/cpuset.cpus
預期輸出:
# 未指定自動綁核策略前,可使用的CPU編號范圍為0~31,表示CPU目前沒有約束。 0-31
步驟二:啟用CPU拓撲感知調度功能
您可以通過Pod Annotation啟用CPU拓撲感知調度功能,實現對Pod的綁核,具體策略如下。
在使用CPU拓撲感知調度時,請勿在Pod上直接指定nodeName
,kube-scheduler并不參與這類Pod的調度過程。您可以使用nodeSelector
等字段配置親和性策略,來指定節點調度。
普通綁核策略
您可以通過Pod Annotation cpuset-scheduler
啟用CPU拓撲感知調度功能,系統會為您實現CPU綁核。
在Pod YAML的
metadata.annotations
中,配置cpuset-scheduler
為true
,啟用CPU拓撲感知調度。說明如需在工作負載(例如Deployment)中配置,請在
template.metadata
字段下配置Pod對應的Annotation。在
Containers
字段下,配置resources.limit.cpu
的取值(該值需為整數),限定CPU綁核范圍。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
annotations:
cpuset-scheduler: "true" # 設置為true,啟用CPU拓撲感知調度。
labels:
app: nginx
spec:
nodeSelector:
policy: intel
containers:
- name: nginx
image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/nginx_optimized:20240221-1.20.1-2.3.0
ports:
- containerPort: 80
resources:
requests:
cpu: 4
memory: 8Gi
limits:
cpu: 4 # 設置resources.limit.cpu值,需為整數。
memory: 8Gi
volumeMounts:
- mountPath: /etc/nginx/nginx.conf
name: nginx
subPath: nginx.conf
volumes:
- name: nginx
configMap:
name: nginx-configmap
items:
- key: nginx_conf
path: nginx.conf
自動綁核策略
您可以通過Annotation開啟CPU拓撲感知調度功能并同步啟用自動綁核策略。配置后,調度器會根據Pod規格自動規劃綁核數量,盡量避免出現跨NUMA訪問內存的情況。
在Pod YAML的
metadata.annotations
中,配置cpuset-scheduler
為true
,且cpu-policy
為static-burst
,啟用自動綁核策略。說明如需在工作負載(例如Deployment)中配置,請在
template.metadata
字段下配置Pod對應的Annotation。在
Containers
字段下,配置resources.limit.cpu
的取值(該值需為整數),做為CPU綁核范圍的參考值。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
annotations:
cpuset-scheduler: "true" # 設置為true,啟用CPU拓撲感知調度。
cpu-policy: "static-burst" # 設置為static-burst,啟用自動綁核策略。
labels:
app: nginx
spec:
nodeSelector:
policy: intel
containers:
- name: nginx
image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/nginx_optimized:20240221-1.20.1-2.3.0
ports:
- containerPort: 80
resources:
requests:
cpu: 4
memory: 8Gi
limits:
cpu: 4 # 做為CPU綁核范圍的參考值,需為整數。
memory: 8Gi
volumeMounts:
- mountPath: /etc/nginx/nginx.conf
name: nginx
subPath: nginx.conf
volumes:
- name: nginx
configMap:
name: nginx-configmap
items:
- key: nginx_conf
path: nginx.conf
結果驗證
以普通綁核策略為例,驗證CPU拓撲感知調度是否成功啟用。自動綁核策略的驗證流程類似。
在Pod對應的節點上,再次執行以下命令,查看啟用自動綁核策略后容器的CPU核心綁定情況。
# 具體路徑可根據Pod的UID以及Container的ID拼接得到。
cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podf9b79bee_eb2a_4b67_befe_51c270f8****.slice/cri-containerd-aba883f8b3ae696e99c3a920a578e3649fa957c51522f3fb00ca943dc2c7****.scope/cpuset.cpus
預期輸出:
# 和limit數量相同
0-3
預期輸出表明,容器可用的CPU編號范圍為0~3,與YAML中聲明的resources.limit.cpu
一致。