如果能確保你最重要的工作負載總能獲取於 Kubernetes 叢集中運行所需的資源,這不是一件好事嗎?現在,你就可以這麼做。Kubernetes 1.9 版本中介紹了一個名為 “優先權與先占權” 的 alpha 版功能,允許您為工作負載分配優先權別,以便在叢集滿載時,重要性高的 pods 能驅趕重要性較低的 pods。
在採用優先權和先占權功能之前,Kubernetes pod 完全按照先搶先贏的原則進行安排,先運行的會持續執行直到完成狀態 (或是永久性執行,如 Deployment 或 StatefulSet 創建的 pod)。這意味著較不重要的工作負載會阻斷隨後而至更為重要的的工作負載 – 並非預期的效果。而優先和先占的功能設定解決了這個問題。
優先權和先占權在很多情況下都很有價值。例如,假設您想限制自動調節的最大叢集大小以控製成本,或者您擁有無法即時增加的叢集 (例如,因為它們是內部部署的,並且您需要購買並安裝額外的硬體)。或者您擁有高優先權的雲端工作負載,而此工作負載的增加速度比叢集自動增加節點 (nodes) 的速度更快。簡而言之,優先和搶占能夠為關鍵應用帶來更好的資源利用率,更低的成本和更好的服務水準。
在不犧牲安全性之下,可預測的叢集成本
在過去的一年裡,Kubernetes 社群在系統可擴展性和支援多用戶方面取得了巨大進步。結果,我們看到,運行這兩個關鍵的面向用戶的服務 (例如,Web 服務器,應用服務器,後端和其他在直接服務路徑中的微服務) 和非急迫性的工作負載的 Kubernetes 叢集越來越多 (如:每日或每週數據分析管道,一次性分析工作,開發人員實驗等)。以這種方式共享一個叢集非常節省成本,因為它允許後一類型的工作負載部分或完全運行在前者未使用的 “資源漏洞” 中,但您仍然需要付費。事實上,有一篇關於Google內部工作負載的研究發現若不在急迫和非急迫性的工作負載之間共享叢集會使成本增加近 60%。在雲端環境中,節點大小靈活且資源碎片較少,我們不期望 Kubernetes 的優先權和先占權產生如此顯著的結果,但總體前提仍然成立。
填充未使用資源的傳統方法是去執行不太重要的工作負載,如 BestEffort。但是,因為系統沒有明確地為 BestEffort pod 預留資源,所以如果節點耗盡內存,即使它們只佔用少量的資源,它們也可能會耗盡 CPU 或終止程序。
更好的選擇是將所有工作負載以 Burstable 或 Guaranteed 方式運行,以便他們獲得資源保證。然而,這導致了可預測的成本和安全性之間的權衡峰值。例如,考慮在叢集忙於處理非急迫性分析工作負載時遇到流量高峰的面對用戶的服務。如果沒有優先權和先占權能力,可以通過配置叢集自動調整程序而不使用上限或使用極高的上限來優先考慮安全性。這樣,即使在非急迫性工作負載繁忙的情況下,它也能處理負載峰值。或者,您可以通過配置叢集 autoscaler 來實現可預測性,但可能會導致服務無法充分擴展以處理意外的負載。
另一方面,通過增加優先權和先占權,當叢集資源耗盡時,Kubernetes 會將非急迫性工作負載中逐出叢集,從而允許您設置叢集大小的上限,而不必擔心服務管道可能無法充分擴展以應對流量高峰。請注意,被驅逐的 pod 在被強制終止之前會收到終止寬限期,默認為 30 秒。
即使您不關心可預測性與安全性之間的權衡,優先權和先占權仍然有用,因為先占權功能驅除 Pod 的速度快於 cloud 提供商提供 Kubernetes 節點的速度。例如,假設面向高優先權的面向用戶的服務存在負載峰值,所以 Horizontal Pod Autoscaler 建立新的 Pods 來吸收負載。如果叢集中運行的優先權較低的工作負載,那麼一旦來自低優先權工作負載的 pod 被清除,新的優先權較高的 pod 就可以開始運行; 他們不必等待叢集 autoscaler 建立新節點。一旦叢集自動調節程序為其添加節點,被驅逐的低優先權 Pod 會再次開始運行。(如果您希望以這種方式使用優先權和先占權功能,最好的做法是為您的低優先權工作負載設置較低的終止寬限期,以便高優先權的Pod可以快速開始運行。)
在 Kubernetes Engine 上啟用優先權和先占權功能
我們最近在 Google Kubernetes Engine 中提供了 Kubernetes 1.9 版本,並在 alpha 叢集中提供了優先權和先占權功能。開始使用此新功能的方法如下所述:
1. 建立一個 alpha 叢集 -請注意 alpha 叢集相關的限制。
2. 依照安裝說明,在您的 Kubernetes 群集中至少建立兩個 PriorityClass。
3. 使用填充的 priorityClassName 字段建立工作負載 (使用 Deployment,ReplicaSet,StatefulSet,Job 或任何您喜歡的內容),與您建立的一個 PriorityClass 配對。
如果您願意,您還可以啟用叢集自動調整程序並設置最大叢集容量。在這種情況下,您的叢集不會增長到配置的最大節點數以上,並且當叢集達到其最大容量並且存在來自較高優先權類的掛起的 Pod 時,較高優先權的 Pod 將驅逐較低優先權的 Pod。如果您未啟用叢集自動調整程序,則優先權和先占權行為是相同的,但叢集大小是固定的。
進階技術:加強“空白填補”
正如我們先前所提及,優先權與先佔權的促成動機之一就是允許非急迫性 (non-time-critical) 的工作負載能”填補節點上重要工作負載之間的資源空隙”。為了嚴格執行此項操作,可以將工作負載與優先權小於零的 PriorityClass 關聯起來。然後,即使叢集大小低於 autoscaler 配置的最大容量,叢集自動調整程序也不會添加該工作負載運行所需的節點。
因此,您可以建立三個重要性依序遞減的工作負載層:
– 可以訪問整個叢集直到叢集 autoscaler 最大容量的工作負載
– 可觸發自動縮放的工作負載,但如果叢集已達到配置的最大容量以及有更高優先權的的工作負載需要運行時則會被驅逐
– 工作負載只會“填補”高優先權工作負載的資源使用情況,意即,如果它們無法適應現有的免費資源,它將等待運行。
由於 PriorityClass 映射到一個整數,所以可以在這三個類別中創建許多子層。