ACK叢集的效能和可用性與叢集資源數量、資源訪問頻率、訪問模式等緊密相關。不同變數組合下,API Server承載的壓力和效能差異不同。在大規模的ACK叢集Pro版(通常為超過500個節點或者10,000個Pod的叢集)中,叢集管理者需要根據業務實際狀況合理規劃和使用規模化叢集,密切關注監控指標,確保叢集的穩定性和可用性。
大規模叢集使用須知
相較於使用多個叢集,構建一個大規模叢集可以有效減少叢集管理營運負擔,提高資源使用率。但在某些複雜的業務情境中,建議您根據商務邏輯或需求將服務拆分到多個叢集中,例如非生產(測試)服務與生產(開發)服務拆分、資料庫服務與前端應用拆分等。
如您有以下維度考量,我們更建議您使用多個叢集,而非單一的大規模叢集。
分類 | 說明 |
隔離性 | 使用多個叢集可以確保不同叢集(例如生產叢集和測試叢集)的隔離性,避免某個叢集的問題影響全部業務,降低故障爆炸半徑。 |
位置 | 某些服務需要部署在離終端使用者更近的特定地理位置,以滿足可用性、低延時的需求。在此情境下,推薦您在多個地區部署多個叢集。 |
單叢集規模上限 | ACK託管控制面通過Auto Scaling和叢集組件的效能最佳化來自適應叢集規模。但Kubernetes架構存在效能瓶頸,超大的叢集規模可能會影響叢集的可用性和效能。在使用大規模叢集前,您應該瞭解Kubernetes社區定義的容量限制與SLO,並前往配額平台查看並申請提高Container Service for Kubernetes的配額上限。如果超出社區和ACK的限制,請拆分業務,使用多個叢集。 |
如您需要多叢集管理,例如應用部署、流量管理、作業分發、全域監控等,建議您啟用多叢集艦隊。
本文使用指引
本文主要面向ACK叢集Pro版的叢集開發和管理員,提供規劃和使用大規模叢集的通用性建議,實際情況仍以您的叢集環境和業務需求為準。
使用新版本叢集
隨著Kubernetes版本不斷升級,Container ServiceACK會定期發布支援的Kubernetes版本,並逐步停止對到期版本的支援人員。對於到期版本,ACK將逐步停止發布新功能特性,停止修複功能缺陷、安全缺陷,且僅提供有限的支援人員。
請您通過協助文檔、控制台資訊、站內信等渠道關注版本發布情況,並在叢集升級前瞭解相應版本的升級注意事項,及時完成版本升級,避免潛在的叢集安全和穩定性問題。關於叢集升級的更多資訊,請參見手動升級叢集、自動升級叢集;關於Kubernetes版本支援資訊,請參見Kubernetes版本概覽及機制。
關注叢集資源限制
為保證大規模叢集的可用性、穩定性和各項效能,請關注下表列出的限制及對應的推薦解決方案。
限制項 | 說明 | 推薦解決方案 |
etcd資料庫大小(DB Size) | etcd資料庫大小上限為8 GB。當etcd資料庫過大時,會影響其效能,包括資料讀取和寫入延遲、系統資源佔用、選舉延時等,也會導致服務和資料恢複過程更加困難和耗時。 | 控制etcd DB Size的總大小在8 GB以下。
|
etcd中每種類型資源的資料總大小 | 如果資來源物件總量過大,用戶端全量訪問該資源時會導致大量的系統資源消耗,嚴重時可能會導致API Server或自訂控制器(Controller)無法初始化。 | 控制每種資源類型的對象總大小在800 MB以下。
|
API Server CLB的串連數和頻寬 | 目前,ACK叢集API Server使用的負載平衡類型為CLB,其串連數與頻寬有最大容量限制。CLB最大串連數可參見CLB執行個體概述,最大頻寬為5120Mbps。 超出CLB串連數或者頻寬節流設定可能會造成節點Not Ready。 | 對於1,000節點以上的叢集,建議選擇按使用量計費的CLB執行個體。 說明 為提升網路連接速度和頻寬,大規模叢集訪問Default命名空間中的Kubernetes服務時,應使用ENI直連模式。在2023年02月以後建立的,v1.20以上的叢集中,建立叢集已預設使用ENI直連;存量叢集的切換請提交工單。更多資訊,請參見Kube API Server。 |
每個命名空間的Service數量 | kubelet會把叢集中定義的Service的相關資訊以環境變數的形式注入到運行在該節點上的Pod中,讓Pod能夠通過環境變數來發現Service,並與之通訊。 每個命名空間中的服務數量過多會導致為Pod注入的環境變數過多,繼而可能導致Pod啟動緩慢甚至失敗 | 將每個命名空間的Service數量控制在5,000以下。 您可以選擇不填充這些環境變數,將 |
叢集的總Service數量 | Service數量過多會導致kube-proxy需要處理的網路規則增多,繼而影響kube-proxy的效能。 對於LoadBalancer類型的Service,Service數量過多會導致Service同步到SLB的時延增加,延遲可能達到分鐘層級。 | 將所有Service的總數量控制在10,000以下。 對LoadBalancer類型的Service,建議將Service總數控制在500以下。 |
單個Service的Endpoint最大數量 | 每個節點上運行著kube-proxy組件,用於監視(Watch)Service的相關更新,以便及時更新節點上的網路規則。當某個Service存在很多Endpoint時,Service相應的Endpoints資源也會很大,每次對Endpoints對象的更新都會導致控制面kube-apiserver和節點kube-proxy之間傳遞大量流量。叢集規模越大,需要更新的相關資料越多,風暴效應越明顯。 說明 為瞭解決此問題,kube-proxy在v1.19以上的叢集中預設使用EndpointSlices來提高效能。 | 將單個Service的Endpoints的後端Pod數量控制在3,000以下。
|
所有Service Endpoint的總數量 | 叢集中Endpoint數量過多可能會造成API Server負載壓力過大,並導致網路效能降低。 | 將所有Service關聯的Endpoint的總數量控制在64,000以下。 |
Pending Pod的數量 | Pending Pod數量過多時,新提交的Pod可能會長時間處於等待狀態,無法被調度到合適的節點上。在此過程中,如果Pod無法被調度,調度器會周期性地產生事件(event),繼而可能導致事件泛濫(event storm)。 | 將Pending Pod的總數量控制在10,000以下。 |
啟用了使用阿里雲KMS進行Secret的落盤加密的叢集中的Secret數量 | 使用KMS v1加密資料時,每次加密都會產生一個新的資料加密金鑰(DEK)。Kubernetes叢集啟動時,需要訪問並解密儲存在etcd中的Secret。如果叢集儲存的Secret過多,叢集在啟動或升級時需要解密大量的資料,影響叢集效能。 | 將開啟KMS V1加密的叢集中儲存的Secret數量控制在2,000以下。 |
合理設定管控組件參數
ACK叢集Pro版提供自訂Pro版叢集的控制面組件參數功能,支援修改kube-apiserver、kube-controller-manager、kube-scheduler等核心託管組件的參數。在大規模叢集中,您需要合理調整管控組件限流的相關參數。
kube-apiserver
為了避免大量並發請求導致控制面超載,kube-apiserver限制了它在特定時間內可以處理的並發請求數。一旦超出此限制,API Server將開始限流請求,向用戶端返回429 HTTP響應碼,即請求過多,並讓用戶端稍後再試。如果服務端沒有任何限流措施,可能導致控制面因處理超出其承載能力的請求而過載,嚴重影響整個服務或叢集的穩定性以及可用性。因此,推薦您在服務端配置限流機制,避免因控制面崩潰而帶來更廣泛的問題。
限流分類
kube-apiserver的限流分為兩種。
v1.18以下:kube-apiserver僅支援最大並發度限流,將請求區分為讀類型和寫類型,通過啟動參數
--max-requests-inflight
和--max-mutating-requests-inflight
限制讀寫請求的最大並發度。該方式不區分請求優先順序。某些低優先順序的慢請求可能佔用大量資源,造成API Server請求堆積,導致一些更高優先順序或更緊急的請求無法及時處理。ACK叢集Pro版支援自訂kube-apiserver的max-requests-inflight和max-mutating-requests-inflight的參數配置。更多資訊,請參見自訂Pro版叢集的控制面組件參數。
v1.18及以上:引入APF(API優先順序和公平性)機制來進行更細粒度的流量管理,支援根據預設的規則和優先順序來分類和隔離請求,從而確保更重要和緊急的請求優先處理,同時遵循一定的公平性策略,保證不同類型的請求都能夠得到合理的處理機會。該特性於v1.20進入Beta階段,預設開啟。
限流監測與推薦解決方案
用戶端可以通過返回狀態代碼429或通過監控指標apiserver_flowcontrol_rejected_requests_total
來判斷服務端是否有限流行為。當觀測到有限流行為時,可以通過以下方式解決。
監控API Server資源用量:當資源用量較低時,可調整
max-requests-inflight
和max-mutating-requests-inflight
參數總和提高總的限流值。對於500個節點以上的叢集,建議參數總和配置為2000~3000之間;對於3000個節點以上的叢集,建議參數總和配置在3000~5000之間。
重新設定PriorityLevelConfiguration:
高優先順序請求:為不期望限流的請求劃分新的FlowSchema,匹配高優先順序的PriorityLevelConfiguration,例如
workload-high
或exempt
。但exempt
的請求不會被APF限流,請謹慎配置。您也可以為高優先順序的請求配置新的PriorityLevelConfiguration,給予更高的並發度。低優先順序請求:當的確存在某些用戶端慢請求導致API Server資源用量高或響應慢時,可以為該類請求新增一個FlowSchema,並為該FlowSchema匹配低並發度的PriorityLevelConfiguration。
ACK叢集Pro版會為您託管kube-apiserver組件。kube-apiserver預設為多AZ高可用,會保證至少2個副本,並隨著控制面資源使用率增大而逐漸調整至最大6個副本。
可並發的總實際請求值 = 副本數單個副本總請求量
。修改kube-apiserver的自訂參數會觸發API Server的變換,可能導致用戶端Controller重新進行List-Watch操作。在大規模叢集下,這可能會造成API Server負載過高,導致其服務暫時不可用。
kube-controller-manager和kube-scheduler
kube-controller-manager和kube-scheduler分別通過kubeAPIQPS/kubeAPIBurst、connectionQPS/connectionBurst參數控制與API Server通訊的QPS。更多資訊,請參見自訂Pro版叢集的控制面組件參數、自訂調度器參數。
kube-controller-manager:對於1000個節點以上的叢集,建議將kubeAPIQPS/kubeAPIBurst調整為300/500以上。
kube-scheduler:一般無需調整。Pod速率超過300/s時建議將connectionQPS/connectionBurst調整為800/1000。
kubelet
kubelet組件的kube-api-burst/qps
預設值為5/10,一般無需調整。當您的叢集出現Pod狀態更新緩慢、調度延遲、儲存卷掛載緩慢等顯著性能問題時,建議您調大參數。操作步驟及說明,請參見自訂節點池kubelet配置。
調大kubelet該參數會增大kubelet與API Server的通訊QPS。如果kubelet發送的請求數量過多,可能會增大API Server的負載。建議您逐步增加取值,並關注API Server的效能和資源用量,確保控制面穩定性。
對節點kubelet執行變更操作時,需合理控制更新頻率。為保證變更過程中控制面的穩定性,ACK限制單節點池每批次的最大並行數不超過10。
規劃叢集資源彈性速率
在大規模叢集中,當叢集處於穩定運行狀態時,通常不會給控制面帶來太大的壓力。但當叢集進行大規模變更操作時,例如快速建立或刪除大量資源,或者大規模擴縮叢集節點數時,可能會造成控制面壓力過大,導致叢集效能下降、響應延遲,甚至服務中斷。
例如,在一個5,000個節點的叢集中,如果存在大量固定數量的Pod且保持穩定運行狀態,那麼它對控制面的壓力通常不會太大。但在一個1,000個節點的叢集中,如果需要在一分鐘內建立10,000個短暫啟動並執行Job,或並發擴容2,000個節點,那麼控制面的壓力會激增。
因此,在大規模叢集中進行資源變更操作時,需根據叢集運行狀態謹慎規劃彈性操作的變更速率,以確保叢集和控制面的穩定性。
推薦操作如下。
由於叢集控制面影響因素較多,以下數字僅供參考。實際操作時,請遵循變更速率由小到大的操作順序,觀察控制面響應正常後再適當提高彈性速率。
節點擴縮容:對於2000個節點以上的叢集,建議在通過節點池手動擴縮容節點時,單個節點池單次操作的節點數不超過100,多個節點池單次操作的總節點數不超過300。
應用Pod擴縮容:若您的應用關聯了Service,擴縮容過程中Endpoint、EndpointSlice的更新會推送到所有節點。在節點數量多的情境下,需要更新的相關資料也很多,可能導致叢集風暴效應。對5000節點以上的叢集,建議非Endpoint關聯的Pod更新QPS不超過300/s;Endpoints關聯的Pod更新QPS不超過10/s。例如,在Deployment中聲明Pod變換(Rolling Update)策略時,推薦您先設定較小的
maxUnavailable
和maxSurge
取值,以降低Pod更新速率。
最佳化用戶端訪問叢集模式
在Kubernetes叢集中,用戶端(客戶商務應用程式或kubectl等)通過API Server來擷取叢集資源資訊。隨著叢集中的資源數量的增加,如果用戶端以相同的頻率進行請求,這些請求可能會給叢集控制面帶來更大的負載,導致控制面響應延遲,甚至導致管控面雪崩。在訪問叢集資源時,需瞭解並規劃訪問資源的大小和頻率。大規模叢集使用建議如下。
優先使用informer訪問本機快取資料
優先使用client-go的informer擷取資源,通過本機快取(Cache)查詢資料,避免List請求直接存取API Server,以減少API Server的負載壓力。
最佳化通過API Server擷取資源的方式
對於未訪問過的本機快取,仍需直接通過API Server擷取資源。但可以遵循以下建議。
在List請求中設定
resourceVersion=0
。resourceVersion
表示資源狀態的版本。設定為0
時,請求會擷取API Server的快取資料,而非直接存取etcd,減少API Server與etcd之間的內部互動次數,更快地響應用戶端List請求。樣本如下。k8sClient.CoreV1().Pods("").List(metav1.ListOptions{ResourceVersion: "0"})
避免全量List資源,防止資料檢索量過大。
為了減少請求返回的資料量,應使用過濾條件(Filter)來限定List請求的範圍,例如lable-selector(基於資源標籤篩選)或field-selector(基於資源欄位篩選)。
說明etcd是一個索引值(KV)儲存系統,本身不具備按label或field過濾資料的功能,請求帶有的過濾條件實際由API Server處理。因此,當使用Filter功能時,建議同時將List請求的
resourceVersion
設定為0
。請求資料將從API Server的緩衝中擷取,而不會直接存取etcd,減少對etcd的壓力。使用Protobuf(而非JSON)訪問非CRD資源。
API Server可以以不同的資料格式向用戶端返回資來源物件,包括JSON和Protobuf。預設情況下,當用戶端請求Kubernetes API時,Kubernetes返回序列化為JSON的對象,其內容類型(Content-Type)為
application/json
。 用戶端可以指定請求使用Protobuf格式的資料,Protobuf在記憶體使用量和網路傳輸串流量方面相較JSON更具優勢。但並非所有API資源類型都支援Protobuf。發送請求時,可以在
Accept
要求標頭中指定多種內容類型(例如application/json
、application/vnd.kubernetes.protobuf
),從而支援在無法使用Protobuf時回退到預設的JSON格式。更多資訊,請參見Alternate representations of resources 。樣本如下。Accept: application/vnd.kubernetes.protobuf, application/json
使用中心化控制器
避免在每個節點上都建立獨立的控制器用於Watch叢集的全量資料。在這種情況下,控制器啟動時,將幾乎同時向API Server發送大量的List請求以同步當前的叢集狀態,對控制面造成巨大壓力,繼而導致服務不穩定或崩潰。
為了避免此問題,建議採用中心化的控制器設計,為整個叢集建立一個或一組集中管理的控制器執行個體,運行在單個節點或少數幾個節點上。中心化的控制器會負責監聽和處理所需的叢集資料,僅啟動一次(或少數幾次)List請求,並僅維護必要數量的Watch串連,大大減少了對API Server的壓力。
合理規劃大規模工作負載
停用自動掛載預設的Service Account
為了確保Pod中的Secret的同步更新,kubelet會為Pod配置的每個Secret建立一個Watch長串連。Watch機制可以讓kubelet即時接收Secret的更新通知。但當所有節點建立的Watch數量總和過多時,大量Watch串連可能會影響叢集控制面的效能。
Kubernetes 1.22版本以前:建立Pod時,如果未指定ServiceAccount,Kubernetes會自動掛載預設的ServiceAccount作為Pod的Secret,使得Pod內部的應用能夠與API Server安全通訊。
對於批處理系統和無需訪問API Server的業務Pod,建議您顯式聲明禁止自動掛載ServiceAccount Token,以避免建立相關的Secret和Watch(更多資訊,請參見automountServiceAccountToken)。在大規模叢集中,該操作可以避免建立不必要的Secret和與API Server的Watch串連,減輕叢集控制面的負擔。
Kubernetes 1.22及之後:使用TokenRequest API來擷取一個短期的、自動輪換的令牌,並以投射卷的形式掛載此令牌。在提高Secret安全性的同時,該操作還能減少kubelet為每個ServiceAccount的Secret建立的Watch串連,降低叢集的效能開銷。
關於如何啟用ServiceAccount Token投射卷功能,請參見使用ServiceAccount Token卷投影。
控制Kubernetes Object數量和大小
請及時清理無需使用的Kubernetes資源,例如ConfigMap、Secret、PVC等,減少系統資源的佔用,保持叢集健康、高效運轉。有以下使用建議。
限制Deployment記錄數:revisionHistoryLimit聲明了要為Deployment保留多少箇舊的ReplicaSet。如果取值太高,Kubernetes會保留很多歷史版本的ReplicaSet,增加kube-controller-manager的管理負擔。在大規模叢集中,如果Deployment較多且更新頻繁,您可以調低Deployment的revisionHistoryLimit的取值,清理舊的ReplicaSet。Deployment的revisionHistoryLimit預設取值為10。
清理無需使用的Job和相關的Pod:如果叢集中通過CronJob或其他機制建立了大量的作業(Job)對象,請使用ttlSecondsAfterFinished來自動清理叢集中較舊的Pod,指定在某個時間周期後Job和相關的Pod將完成自動清理(刪除)。
合理配置Informer類型組件的資源配置
Informer類型的組件主要用於監控和同步Kubernetes叢集的資源狀態。Informer類組件會建立對叢集API Server資源狀態的Watch串連,並在本地維護一個資來源物件的緩衝,以便快速響應資源狀態的變化。
對於Informer類型的組件,例如Controller組件、kube-scheduler等,組件記憶體佔用與其Watch的資源大小相關。大規模叢集下,請關注該類組件的記憶體資源消耗,避免組件OOM。組件頻繁OOM會導致組件持續資源監聽出現問題。組件頻繁重啟時,每次執行的List-Watch操作也會對叢集控制面(尤其是API Server)造成額外的壓力。
關注叢集控制面指標
您可以查看控制面組件監控大盤,擷取控制面核心組件的指標清單、異常指標問題解析等。在大規模叢集中,請重點關注以下指標。關於指標的使用說明、詳細說明,請參見控制面組件監控。
管控資源用量
目前管控組件所有資源用量均可以查看,相關指標和介紹如下:
指標名稱 | PromQL | 說明 |
記憶體使用量量 | memory_utilization_byte{container="kube-apiserver"} | API Server的記憶體使用量量。單位:位元組。 |
CPU使用量 | cpu_utilization_core{container="kube-apiserver"}*1000 | API Server的CPU使用量。單位:毫核。 |
kube-apiserver
關於如何查看指標及指標的完整說明,請參見kube-apiserver組件監控指標說明。
資來源物件數量
名稱
PromQL
說明
資來源物件數量
max by(resource)(apiserver_storage_objects)
max by(resource)(etcd_object_counts)
當ACK為1.22及以上版本時, 指標名字為apiserver_storage_objects
當ACK為1.22及以下版本時,指標名字為etcd_object_counts。
說明由於相容性問題,1.22版本中apiserver_storage_objects名稱和etcd_object_counts名稱均存在。
請求時延
名稱
PromQL
說明
GET讀請求時延
histogram_quantile($quantile, sum(irate(apiserver_request_duration_seconds_bucket{verb="GET",resource!="",subresource!~"log|proxy"}[$interval])) by (pod, verb, resource, subresource, scope, le))
展示GET請求的回應時間,維度包括API Server Pod、Verb(GET)、Resources、Scope。
LIST讀請求時延
histogram_quantile($quantile, sum(irate(apiserver_request_duration_seconds_bucket{verb="LIST"}[$interval])) by (pod_name, verb, resource, scope, le))
展示LIST請求的回應時間,維度包括API Server Pod、Verb(LIST)、Resources、Scope。
寫請求時延
histogram_quantile($quantile, sum(irate(apiserver_request_duration_seconds_bucket{verb!~"GET|WATCH|LIST|CONNECT"}[$interval])) by (cluster, pod_name, verb, resource, scope, le))
展示Mutating請求的回應時間,維度包括API Server Pod、Verb(GET、WATCH、LIST、CONNECT)、Resources、Scope。
請求限流
名稱
PromQL
說明
請求限流速率
sum(irate(apiserver_dropped_requests_total{request_kind="readOnly"}[$interval])) by (name)
sum(irate(apiserver_dropped_requests_total{request_kind="mutating"}[$interval])) by (name)
API Server的限流速率 ,
No data
或者0
表示沒有限流。
kube-scheduler
關於如何查看指標及指標的完整說明,請參見kube-scheduler組件監控指標說明。
Pending Pod數
名稱
PromQL
說明
Scheduler Pending Pods
scheduler_pending_pods{job="ack-scheduler"}
Pending Pod的數量。隊列種類如下:
unschedulable:不可調度的Pod數量。
backoff:backoffQ的Pod數量,即因為某種原因暫時不能被調度的Pod數量。
active:activeQ的Pod數量,即準備就緒並等待被調度的Pod數量。
請求時延
名稱
PromQL
說明
Kube API 請求時延
histogram_quantile($quantile, sum(rate(rest_client_request_duration_seconds_bucket{job="ack-scheduler"}[$interval])) by (verb,url,le))
kube-scheduler對kube-apiserver組件發起的HTTP請求時延,從方法(Verb)和請求URL維度分析。
kube-controller-manager
關於如何查看指標及指標的完整說明,請參見kube-controller-manager組件監控指標說明。
Workqueue
名稱 | PromQL | 說明 |
Workqueue深度 | sum(rate(workqueue_depth{job="ack-kube-controller-manager"}[$interval])) by (name) | Workqueue深度在單位時間內的變化。 |
Workqueue處理時延 | histogram_quantile($quantile, sum(rate(workqueue_queue_duration_seconds_bucket{job="ack-kube-controller-manager"}[5m])) by (name, le)) | 事件在Workqueue中存在的時間長度。 |
etcd
關於如何查看指標及指標的完整說明,請參見etcd組件監控指標說明。
KV總數
名稱
PromQL
說明
kv總數
etcd_debugging_mvcc_keys_total
etcd叢集KV對(鍵對)總數。
資料庫大小(DB Size)
名稱
PromQL
說明
磁碟大小
etcd_mvcc_db_total_size_in_bytes
etcd Backend DB總大小,即etcd後端資料庫總大小。
etcd_mvcc_db_total_size_in_use_in_bytes
etcd Backend DB實際使用大小,即etcd後端資料庫實際使用大小。
相關文檔
關於ACK叢集的配額與限制,請參見配額與限制。
關於如何合理規劃叢集VPC網路及容器網路,請參見Kubernetes叢集網路規劃。
關於如何?叢集建立、工作負載的高可靠配置,請參見工作負載推薦配置。