kubernetes 降本增效標準指南| 資源利用率提升工具大全

騰訊雲原生發表於2021-04-12

背景

公有云的發展為業務的穩定性、可擴充性、便利性帶來了極大幫助。這種用租代替買、並且提供完善的技術支援和保障的服務,理應為業務帶來降本增效的效果。但實際上業務上雲並不意味著成本一定較少,還需適配雲上業務的應用開發、架構設計、管理運維、合理使用等多方面解決方案,才能真正助力業務的降本增效。在《Kubernetes 降本增效標準指南》系列 的上一篇文章《容器化計算資源利用率現象剖析》中可看到,IDC 上雲後資源利用率提高有限,即使已經容器化,節點的平均利用率依舊僅在 13% 左右,資源利用率的提升任重道遠。

本篇文章將帶你瞭解:
為什麼 Kubernetes 叢集中的 CPU 和記憶體資源利用率 通常都如此之低?
現階段在 TKE 上面有哪些產品化的方法可以輕鬆提升資源利用率?

資源浪費場景

為何資源利用率通常都如此之低?首先可以看看幾個業務的實際使用資源場景:

1. 資源預留普遍存在 50% 以上的浪費

Kubernetes 中的 Request(請求) 欄位用於管理容器對 CPU 和記憶體資源預留的機制,保證容器至少可以達到的資源量,該部分資源不能被其他容器搶佔,具體可檢視。當 Request 設定過小,無法保證業務的資源量,當業務的負載變高時無力承載,因此使用者通常習慣將 Request 設定得很高,以保證服務的可靠性。但實際上,業務在大多數時段時負載不會很高。以 CPU 為例,下圖是某個實際業務場景下容器的資源預留(Request)和實際使用量(CPU_Usage)關係圖:資源預留遠大於實際使用量,兩者之間差值所對應的資源不能被其他負載使用,因此 Request 設定過大勢必會造成較大的資源浪費。

如何解決這樣的問題?現階段需要使用者自己根據實際的負載情況設定更合理的 Request、以及限制業務對資源的無限請求,防止資源被某些業務過度佔用。這裡可以參考後文中的 Request Quota 和 Limit Ranges 的設定。
此外,TKE 將推出 Request 推薦產品,幫助使用者智慧縮小 Request 和 Usage 之間的差值,在保障業務的穩定性的情況下有效提升資源利用率。

2. 業務資源波峰波谷現象普遍,通常波谷時間大於波峰時間,資源浪費明顯

大多數業務存在波峰波谷,例如公交系統通常在白天負載增加,夜晚負載減少;遊戲業務通常在週五晚上開始出現波峰,在週日晚開始出現波谷。如下圖所示:同一業務在不同的時間段對資源的請求量不同,如果使用者設定的是固定的 Request,f在負載較低時利用率很低。
img

這時可以通過動態調整副本數以高資源利用率承載業務的波峰波谷,可以參考後文中的 HPA 、HPC、CA

3. 不同型別的業務,導致資源利用率有較大差異

線上業務通常白天負載較高,對時延要求較高,必須優先排程和執行;而離線的計算型業務通常對執行時段和時延要求相對較低,理論上可以在線上業務波谷時執行。此外,有些業務屬於計算密集型,對 CPU 資源消耗較多,而有些業務屬於記憶體密集型,對記憶體消耗較多。

img

如上圖所示,通過在離線混部可以動態排程離線業務和線上業務,讓不同型別業務在不同的時間段執行以提升資源利用率。對於計算密集型業務和記憶體密集型業務,可以使用親和性排程,為業務分配更合適的節點,有效提升資源利用率。具體方式可參考後文中的離線上混部和親和性排程。

在 Kubernetes 上提升資源利用率的方法

騰訊雲容器服務 TKE 基於大量的使用者實際業務,已經產品化了一系列工具,幫助使用者輕鬆有效的提升資源利用率。主要從兩方面著手:一是利用原生的 Kubernetes 能力手動進行資源的劃分和限制;二是結合業務特性的自動化方案。
img

1. 如何資源劃分和限制

設想,你是個叢集管理員,現在有4個業務部門使用同一個叢集,你的責任是保證業務穩定性的前提下,讓業務真正做到資源的按需使用。為了有效提升叢集整體的資源利用率,這時就需要限制各業務使用資源的上限,以及通過一些預設值防止業務過量使用。

理想情況下,業務應該根據實際情況,設定合理的 Request 和 Limit。(Request 用於對資源的佔位,表示容器至少可以獲得的資源;Limit 用於對資源的限制,表示容器至多可以獲得的資源。)這樣更利於容器的健康執行、資源的充分使用。但實際上使用者經常忘記設定容器對資源的 Request 和 Limit。此外,對於共享使用一個叢集的團隊/專案來說,他們通常都將自己容器的 Request 和 Limit 設定得很高以保證自己服務的穩定性。如果你使用的是 TKE 的控制檯,建立負載時會給所有的容器設定如下預設值。該預設值是 TKE 根據真實業務分析預估得出,和具體的業務需求之間可能存在偏差。

Request Limit
CPU(核) 0.25 0.5
Memory(MiB) 256 1024

為了更細粒度的劃分和管理資源,可以在 TKE 上設定名稱空間級別的 Resource Quota 以及 Limit Ranges。

1.1 使用 Resource Quota 劃分資源

如果你管理的某個叢集有4個業務,為了實現業務間的隔離和資源的限制,你可以使用名稱空間和 Resource Quota

Resource Quota 用於設定名稱空間資源的使用配額,名稱空間是 Kubernetes 叢集裡面的一個隔離分割槽,一個叢集裡面通常包含多個名稱空間,例如 Kubernetes 使用者通常會將不同的業務放在不同的名稱空間裡,你可以為不同的名稱空間設定不同的 Resource Quota,以限制一個名稱空間對叢集整體資源的使用量,達到預分配和限制的效果。Resource Quota 主要作用於如下方面,具體可檢視

  1. 計算資源:所有容器對 CPU 和 記憶體的 Request 以及 Limit 的總和
  2. 儲存資源:所有 PVC 的儲存資源請求總和
  3. 物件數量:PVC/Service/Configmap/Deployment等資源物件數量的總和

Resource Quota 使用場景

  • 給不同的專案/團隊/業務分配不同的名稱空間,通過設定每個名稱空間資源的 Resource Quota 以達到資源分配的目的
  • 設定一個名稱空間的資源使用數量的上限以提高叢集的穩定性,防止一個名稱空間對資源的多度侵佔和消耗

TKE 上的 Resource Quota

TKE 上已經實現對 Resource Quota 的產品化,你可以直接在控制檯利用 Resource Quota 限制一個名稱空間的資源使用量,具體可參考文件
img
img

1.2 使用 Limit Ranges 限制資源

使用者經常忘記設定資源的 Request 和 Limit,或者將值設定得很大怎麼辦?作為管理員,如果可以為不同的業務設定不同資源使用預設值以及範圍,可以有效減少業務建立時的工作量同時,限制業務對資源的過度侵佔。

與 Resource Quota 對名稱空間整體的資源限制不同,Limit Ranges 適用於一個名稱空間下的單個容器。可以防止使用者在名稱空間內建立對資源申請過小或過大容器,防止使用者忘記設定容器的 Request 和 Limit。Limit Ranges 主要作用於如下方面,具體可檢視

  1. 計算資源:對所有容器設定 CPU 和記憶體使用量的範圍
  2. 儲存資源:對所有 PVC 能申請的儲存空間的範圍
  3. 比例設定:控制一種資源 Request 和 Limit 之間比例
  4. 預設值:對所有容器設定預設的 Request/Limit,如果容器未指定自己的記憶體請求和限制,將為它指定預設的記憶體請求和限制

Limit Ranges 使用場景

  1. 設定資源使用預設值,以防使用者遺忘,也可以避免 QoS 驅逐重要的 Pod
  2. 不同的業務通常執行在不同的名稱空間裡,不同的業務通常資源使用情況不同,為不同的名稱空間設定不同的 Request/Limit 可以提升資源利用率
  3. 限制容器個對資源使用的上下限,保證容器正常執行的情況下,限制其請求過多資源

TKE 上的 Limit Ranges

TKE 上已經實現對 Limit Ranges 的產品化,你可以直接在控制檯管理名稱空間的 Limit Ranges,具體可參考文件
img

2. 自動化提升資源利用率的方法

上面提到的利用 Resource Quota 和 Limit Ranges 來分配和限制資源的方法依賴經驗和手工,主要解決的是資源請求和分配不合理。如何更自動化的動態調整以提升資源利用率是使用者更關心的問題,接下來從彈性伸縮、排程、在離線混部三大產品化的方向,詳述如何提升資源利用率。

2.1 彈性伸縮

2.1.1 通過 HPA 按指標彈性擴縮容

如上面資源浪費場景2所說,如果你的業務是存在波峰波谷的,固定的資源 Request 註定在波谷時會造成資源浪費,針對這樣的場景,如果波峰的時候可以自動增加業務負載的副本數量,波谷的時候可以自動減少業務負載的副本數量,將有效提升資源整體利用率。

HPA(Horizontal Pod Autoscaler)可以基於一些指標(例如 CPU、記憶體的利用率)自動擴縮 Deployment 和 StatefulSet 中的 Pod 副本的數量,達到工作負載穩定的目的,真正做到按需使用。

HPA 使用場景
  1. 流量突發:突然流量增加,負載過載時會自動增加 Pod 數量以及時響應
  2. 自動縮容:流量較少時,負載對資源的利用率過低時會自動減少 Pod 的數量以避免浪費
TKE 上的 HPA

TKE 基於 Custom Metrics API 支援許多用於彈性伸縮的指標,涵蓋 CPU、記憶體、硬碟、網路以及 GPU 相關的指標,覆蓋絕大多數的 HPA 彈性伸縮場景,詳細列表請參見 自動伸縮指標說明。此外,針對例如基於業務單副本 QPS 大小來進行自動擴縮容等複雜場景,可通過安裝 prometheus-adapter 來實現自動擴縮容,具體可參考文件
img

2.1.2 通過 HPC 定時擴縮容

假設你的業務是電商平臺,雙十一要進行促銷活動,這時可以考慮使用 HPA 自動擴縮容。但是 HPA 需要先監控各項指標後,再進行反應,可能擴容速度不夠快,無法及時承載高流量。針對這種有預期的流量暴增,如果能提前發生副本擴容,將有效承載流量井噴。
HPC(HorizontalPodCronscaler)是 TKE 自研元件,旨在定時控制副本數量,以達到提前擴縮容、和提前觸發動態擴容時資源不足的影響,相較社群的 CronHPA,額外支援:

  1. 與 HPA 結合:可以實現定時開啟和關閉 HPA,讓你的業務在高峰時更彈性
  2. 例外日期設定:業務的流量不太可能永遠都是規律的,設定例外日期可以減少手工調整 HPC
  3. 單次執行:以往的 CronHPA 都是永久執行,類似 Cronjob,單次執行可以更靈活的應對大促場景
HPC 使用場景

以遊戲服務為例,從週五晚上到週日晚上,遊戲玩家數量暴增。如果可以將遊戲伺服器在星期五晚上前擴大規模,並在星期日晚上後縮放為原始規模,則可以為玩家提供更好的體驗。如果使用 HPA,可能因為擴容速度不夠快導致服務受影響。

TKE 上的 HPC

TKE 上已經實現對 HPC 的產品化,但你需要提前在”元件管理“裡面安裝 HPC,HPC 使用 CronTab 語法格式。

安裝:
img

使用:
img
img

2.1.3 通過 CA 自動調整節點數量

上面提到的 HPA 和 HPC,都是在業務負載層面的自動擴縮副本數量,以靈活應對流量的波峰波谷,提升資源利用率。但是對於叢集整體而言,資源總數是固定的,HPA 和 HPC 只是讓叢集有更多空餘的資源,是否有一種方法,能在叢集整體較“空”時回收部分資源,能在叢集整體較“滿”時擴充叢集整體資源?因為叢集整體資源的使用量直接決定了賬單費用,這種叢集級別的彈性擴縮將真正幫助你節省使用成本。

CA(Cluster Autoscaler)用於自動擴縮叢集節點數量,以真正實現資源利用率的提升,並直接作用於使用者的費用,是降本增效的關鍵。

CA 使用場景
  1. 在業務波峰時,根據業務突增的負載擴容合適的節點
  2. 在業務波谷時,根據資源的空閒情況釋放多餘的節點
TKE 上的 CA

TKE 上的 CA 是以節點池的形態來讓使用者使用的,CA 推薦和 HPA 一起使用:HPA 負責應用層的擴縮容,CA 負責資源層(節點層)的擴縮容,當 HPA 擴容造成叢集整體資源不足時,會引發 Pod 的 Pending,Pod Pending 會觸發 CA 擴充節點池以增加叢集整體資源量,整體擴容邏輯可參考下圖:

img
具體的引數配置方式以及應用場景可參考《像管理 Pod 一樣管理 Node》,或者可參考騰訊雲容器服務官方文件

2.2 排程

Kubernetes 排程機制是 Kubernetes 原生提供的一種高效優雅的資源分配機制,它的核心功能是為每個 Pod 找到最適合它的節點,在 TKE 場景下,排程機制幫助實現了應用層彈性伸縮到資源層彈性伸縮的過渡。通過合理利用 Kubernetes 提供的排程能力,根據業務特性配置合理的排程策略,也能有效提高叢集中的資源利用率。

2.2.1 節點親和性

倘若你的某個業務是 CPU 密集型,不小心被 Kubernetes 的排程器排程到記憶體密集型的節點上,導致記憶體密集型的 CPU 被佔滿,但記憶體幾乎沒怎麼用,會造成較大的資源浪費。如果你能為節點設定一個標記,表明這是一個 CPU 密集型的節點,然後在建立業務負載時也設定一個標記,表明這個負載是一個 CPU 密集型的負載,Kubernetes 的排程器會將這個負載排程到 CPU 密集型的節點上,這種尋找最合適的節點的方式,將有效提升資源利用率。

建立 Pod 時,可以設定節點親和性,即指定 Pod 想要排程到哪些節點上(這些節點是通過 K8s Label)來指定的。

節點親和性使用場景

節點親和性非常適合在一個叢集中有不同資源需求的工作負載同時執行的場景。比如說,騰訊雲的 CVM(節點) 有 CPU 密集型的機器,也有記憶體密集型的機器。如果某些業務對 CPU 的需求遠大於記憶體,此時使用普通的 CVM 機器,勢必會對記憶體造成較大浪費。此時可以在叢集裡新增一批 CPU 密集型的 CVM,並且把這些對 CPU 有較高需求的 Pod 排程到這些 CVM 上,這樣可以提升 CVM 資源的整體利用率。同理,還可以在叢集中管理異構節點(比如 GPU 機器),在需要 GPU 資源的工作負載中指定需要GPU資源的量,排程機制則會幫助你尋找合適的節點去執行這些工作負載。

TKE 上的節點親和性

TKE 提供與原生 Kubernetes 完全一致的親和性使用方式,你可通過控制檯或配置 YAML 的方式使用此項功能,具體可參考

2.2.2 動態排程器

原生的 Kubernetes 排程策略傾向於排程pod到節點剩餘資源較多的節點上, 比如預設的 LeastRequestedPriority 策略。但是原生排程策略存在一個問題:這樣的資源分配是靜態的,Request 不能代表資源真實使用情況,因此一定會存在一定程度的浪費。因此,如果排程器可以基於節點的實際資源利用率進行排程,將一定程度上解決資源浪費的問題。

TKE 自研的動態排程器所做的就是這樣的工作。動態排程器的核心原理如下:
img

動態排程器的使用場景

除了降低資源浪費,動態排程器還可以很好的緩解叢集排程熱點的問題。

  1. 動態排程器會統計過去一段時間排程到節點的 Pod 數目,避免往同一節點上排程過多的 Pod
  2. 動態排程器支援設定節點負載閾值,在排程階段過濾掉超過閾值的節點。
TKE 上的動態排程器

你可以在擴充套件元件裡面安裝和使用動態排程器:
img
更多關於動態排程器的使用指南,可以參考 《TKE 重磅推出全鏈路排程解決方案》 和官方文件

2.3 在離線業務混部

如果你既有線上 Web 服務業務,又有離線的計算服務業務,藉助 TKE 的在離線業務混部技術可以動態排程和執行不同的業務,提升資源利用率。

在傳統架構中,大資料業務和線上業務往往部署在不同的資源叢集中,這兩部分業務相互獨立。但大資料業務一般更多的是離線計算類業務,在夜間處於業務高峰,而線上業務恰恰相反夜間常常處於空載狀態。雲原生技術藉助容器完整(CPU,記憶體,磁碟IO,網路IO等)的隔離能力,及 Kubernetes 強大的編排排程能力,實現線上和離線業務混合部署,從而使在離線業務充分利用線上業務空閒時段的資源,以提高資源利用率。

在離線業務混部使用場景

在 Hadoop 架構下,離線作業和線上作業往往分屬不同的叢集,然而線上業務、流式作業具有明顯的波峰波谷特性,在波谷時段,會有大量的資源處於閒置狀態,造成資源的浪費和成本的提升。在離線混部叢集,通過動態排程削峰填谷,當線上叢集的使用率處於波谷時段,將離線任務排程到線上叢集,可以顯著的提高資源的利用率。然而,Hadoop Yarn 目前只能通過 NodeManager 上報的靜態資源情況進行分配,無法基於動態資源排程,無法很好的支援線上、離線業務混部的場景。

TKE 上的在離線混部

線上業務具有明顯的波峰浪谷特徵,而且規律比較明顯,尤其是在夜間,資源利用率比較低,這時候大資料管控平臺向 Kubernetes 叢集下發建立資源的請求,可以提高大資料應用的算力,具體可參考

img

如何權衡資源利用率與穩定性

在企業的運維工作中,除了成本,系統的穩定性也是十分重要的指標。如何在兩者間達到平衡,可能是很多運維人員心中的“痛點”。一方面,為了降低成本,資源利用率當然是越高越好,但是資源利用率達到一定水位後,負載過高極有可能導致業務 OOM 或 CPU 抖動等問題。
為了減小企業成本控制之路上的顧慮,TKE 還提供了“兜底神器“ - 重排程器 來保障叢集負載水位在可控範圍內。
重排程器是動態排程器是一對好搭檔(它們的關係可以參考下圖),就像它的名字一樣,它主要負責“保護”節點中已經負載比較“危險”的節點, 優雅驅逐這些節點上的業務。
img

TKE 上的重排程器

可以在擴充套件元件裡面安裝和使用重排程器:
img

更多關於重排程器的使用指南,可以參考 《TKE 重磅推出全鏈路排程解決方案》

總結

資源利用率的提升道阻且長,如何在保障業務穩定性的前提下,有效提升資源利用率具有較大挑戰。利用上述這些 TKE 的產品化方案,可以有效幫助使用者解決資源利用率提升過程中的種種挑戰,此外 TKE 也在開發其他的工具幫助使用者降低提升資源利用率的門檻。《Kubernetes 降本增效標準指南》系列後期文章將更加深入講解 Kubernetes 提升資源利用率的方法,敬請期待。

相關文章