深入研究Kubernetes的資源請求和限制
譯文【51CTO.com快譯】很多組織在Kubernetes集群中創(chuàng)建資源時可能會遇到以下情況:
(1)沒有為工作負載指定CPU資源請求或較低的CPU資源請求,這意味著更多Pod可能在同一節(jié)點上工作。而在流量突增的時候,服務(wù)器中的CPU會以更長的延遲以達到最大值,但某些服務(wù)器可能會出現(xiàn)CPU軟鎖定的情況。
(2)同樣,沒有為工作負載指定內(nèi)存資源請求或較低的內(nèi)存資源請求。一些Pod(尤其是那些運行Java商業(yè)應(yīng)用程序的Pod)將會重新啟動,盡管它們實際上可以在本地測試中正常運行。
(3)在Kubernetes集群中,工作負載通常并不會在節(jié)點之間平均分配。特別是在大多數(shù)情況下,內(nèi)存資源分布并不均勻,這意味著某些節(jié)點可以比其他節(jié)點有著更高的內(nèi)存利用率。作為容器編排事實上的標準,Kubernetes應(yīng)該具有一個有效的調(diào)度程序,以確保資源的均勻分配。但真的是這樣嗎?
在通常情況下,如果流量突然出現(xiàn)爆發(fā)性增長,并在服務(wù)器出現(xiàn)宕機以至于SSH登錄失敗時,則集群管理員將無法執(zhí)行任何操作,只能重新啟動群集。在本文中,將通過分析可能出現(xiàn)的問題并討論如今解決的最佳實踐,深入探討Kubernetes的資源請求和限制。如果你對其底層機制感興趣,則還可以從源代碼的角度找到分析。本文將對你了解Kubernetes的資源請求和限制的工作方式以及它們可以按預(yù)期的方式工作的原因有所幫助。
概念
為了充分利用Kubernetes集群中的資源,提高調(diào)度效率,Kubernetes使用資源請求和限制來控制容器的資源分配。每個容器都有自己的請求和限制。這兩個參數(shù)由resources.requests和resources.limits指定。一般來說,請求在調(diào)度中更為重要,而限制在運行中更為重要。
請求定義了容器所需的最少資源。例如,對于運行Spring Boot業(yè)務(wù)的容器,其指定的請求必須是Java虛擬機(JVM)需要在容器映像中消耗的最少資源量。如果只是指定低內(nèi)存請求,則Kubernetes調(diào)度程序很可能會將Pod調(diào)度到?jīng)]有足夠資源來運行JVM的節(jié)點。也就是說,Pod無法使用JVM啟動過程所需的更多內(nèi)存。因此導(dǎo)致Pod不斷重啟。
另一方面,限制決定了容器可以使用的最大資源量,從而防止了由于過度消耗資源而導(dǎo)致的資源短缺或服務(wù)器宕機的情況。如果將其設(shè)置為0,則表示該容器沒有資源限制。特別是,如果在沒有指定請求的情況下設(shè)置限制,Kubernetes會認為默認情況下請求的值與限制的值相同。
請求和限制適用于兩種類型的資源——可壓縮的(例如CPU)和不可壓縮的(例如內(nèi)存)。對于不可壓縮資源,進行適當?shù)南拗剖欠浅V匾摹?/p>
以下是請求和限制的概述:
- 如果Pod中的服務(wù)使用的CPU資源超過了指定的限制值,則Pod將會受到限制,但不會被終止。如果未設(shè)置限制值,則Pod可以使用所有空閑的CPU資源。
- 如果Pod使用的內(nèi)存資源超出了指定的限制值,Pod中的容器進程將因OOM而終止。在這種情況下,Kubernetes傾向于在原始節(jié)點上重新啟動容器,或者簡單地創(chuàng)建另一個Pod。
- 0≤請求≤節(jié)點可分配;請求≤限制≤無限。
場景分析
在了解了請求和限制的概念之后,回顧一下以上提到的三種情況:
(1)情況1
首先,需要知道CPU資源和內(nèi)存資源是完全不同的。CPU資源是可壓縮的,CPU的分配和管理基于完全公平調(diào)度程序(CFS)。簡而言之,如果Pod中的服務(wù)使用的CPU資源超過了指定的限制值,它將受到Kubernetes的限制。對于沒有CPU限制的Pod來說,一旦空閑的CPU資源耗盡,之前分配的CPU資源量將逐漸減少。在這兩種情況下,最終,Pod將無法處理外部請求,從而導(dǎo)致更長的延遲和響應(yīng)時間。
(2)情況2
與其相反,內(nèi)存資源無法壓縮,并且Pod無法共享內(nèi)存資源。這意味著如果內(nèi)存耗盡,分配新的內(nèi)存資源肯定會失敗。
Pod中的某些進程專門在初始化時需要一定數(shù)量的內(nèi)存。例如,JVM在啟動時會應(yīng)用一定數(shù)量的內(nèi)存。如果指定的內(nèi)存請求小于JVM應(yīng)用的內(nèi)存,則內(nèi)存應(yīng)用程序?qū)?OOM終止)。因此,這個Pod將繼續(xù)重啟并發(fā)生故障。
(3)情況3
在創(chuàng)建Pod時,Kubernetes需要以平衡和全面的方式分配或配置不同的資源,其中包括CPU和內(nèi)存。與此同時,Kubernetes調(diào)度算法需要考慮多種因素,例如NodeResourcesLeastAllocated和Pod affinity。內(nèi)存資源常常分布不均的原因是,對于應(yīng)用程序來說,內(nèi)存被認為比其他資源更稀缺。
此外,Kubernetes調(diào)度程序根據(jù)集群的當前狀態(tài)工作。換句話說,當創(chuàng)建新的Pod時,調(diào)度程序會根據(jù)此時集群的資源規(guī)范為Pod選擇一個最佳節(jié)點來運行。由于Kubernetes集群是高度動態(tài)的,因此在這里可能會發(fā)生潛在問題。例如,要維護一個節(jié)點,可能需要對其進行鎖定,并且在該節(jié)點上運行的所有Pod都將被調(diào)度到其他節(jié)點。而出現(xiàn)的問題是,在維護之后,這些Pod不會自動安排回原始節(jié)點。這是因為Kubernetes本身無法將運行中的Pod重新綁定到另一個節(jié)點,也就無法將其重新調(diào)度到另一個節(jié)點。
優(yōu)秀實踐
從以上分析可以知道,集群穩(wěn)定性直接影響應(yīng)用程序的性能。暫時的資源短缺通常是導(dǎo)致集群不穩(wěn)定的主要原因,而在云平臺不穩(wěn)定意味著應(yīng)用程序出現(xiàn)故障,甚至節(jié)點出現(xiàn)故障。
以下介紹兩種提高集群穩(wěn)定性的方法:
首先,通過編輯Kubelet配置文件來保留一定數(shù)量的系統(tǒng)資源。當處理不可壓縮的計算資源(例如內(nèi)存或磁盤空間)時,這一點尤其重要。
其次,為Pod配置適當?shù)姆?wù)質(zhì)量(QoS)類。Kubernetes使用QoS類來確定Pod的調(diào)度和逐出優(yōu)先級。可以為不同的Pod分配不同的QoS類,其中包括“Guaranteed”(最高優(yōu)先級)、“Burstable”和“BestEffort”(最低優(yōu)先級)。
- Guaranteed。Pod中的每個容器(包括init容器)都必須具有為CPU和內(nèi)存指定的請求和限制,并且它們必須相等。
- Burstable。Pod中至少有一個容器具有為CPU或內(nèi)存指定的請求。
- BestEffort。Pod中沒有容器具有為CPU和內(nèi)存指定的請求和限制。
注:使用Kubelet的CPU管理策略,可以為特定Pod設(shè)置CPU親和性。
當資源耗盡時,集群將首先用BestEffort的QoS類終止Pod,然后是Burstable。換句話說,優(yōu)先級最低的Pod首先終止。如果具有足夠的資源,可以給所有的Pod分配一個Guaranteed類。這可以看作是計算資源與性能和穩(wěn)定性之間的權(quán)衡。你可能期望采用更多的資源,但集群可以更高效地工作。與此同時,為了提高資源利用率,你可以將運行業(yè)務(wù)服務(wù)的Pod分配為Guaranteed類。對于其他服務(wù),根據(jù)優(yōu)先級為它們分配Burstable或BestEffort類別。
接下來,將以KubeSphere容器平臺為例,了解如何更好地為Pod配置資源。
使用KubeSphere分配資源
如上所述,請求和限制是集群穩(wěn)定性的兩個重要組成部分。作為Kubernetes的主要發(fā)行版之一,KubeSphere擁有簡潔、清晰、交互式的用戶界面,極大地降低了Kubernetes的學(xué)習(xí)難度。
1.在開始之前做的工作
KubeSphere具有功能強大的多租戶系統(tǒng),可對不同用戶進行細粒度的訪問控制。在KubeSphere 3.0中,可以分別為名稱空間(ResourceQuotas)和容器(LimitRanges)設(shè)置請求和限制。要執(zhí)行這些操作,需要創(chuàng)建一個工作區(qū)、一個項目(即名稱空間)和一個帳戶(ws-admin)。
2.設(shè)置資源配額
轉(zhuǎn)到項目的“概述”頁面,導(dǎo)航到“項目設(shè)置”中的“基本信息”,然后從“管理項目”下拉菜單中選擇“編輯配額”。
在出現(xiàn)的對話框中,為項目設(shè)置請求和限制。
需要記?。?/p>
- 在這個頁面上設(shè)置的請求或限制必須大于為項目中所有Pod指定的總請求或限制。
- 在項目中創(chuàng)建容器而不指定請求或限制時,創(chuàng)建時將看到錯誤消息(記錄在事件中)。
在配置項目配額后,需要為項目中創(chuàng)建的所有容器指定請求和限制。項目配額為所有容器設(shè)置了規(guī)則。
注:KubeSphere中的項目配額與Kubernetes中的ResourceQuotas相同。除了CPU和內(nèi)存,還可以分別為其他對象(如Deployments和ConfigMaps)設(shè)置資源配額。
3.設(shè)置默認請求和限制
如上所述,如果指定了項目配額,則需要相應(yīng)地配置Pod的請求和限制。實際上,在測試甚至生產(chǎn)中,請求的值和限制的值非常接近,甚至對于大多數(shù)Pod來說都是相等的。為了簡化創(chuàng)建工作負載的過程,KubeSphere允許用戶預(yù)先設(shè)置容器的默認請求和限制。這樣無需在每次創(chuàng)建Pod時都設(shè)置請求和限制。
要設(shè)置默認請求和限制,需要執(zhí)行以下步驟:
(1)同樣在“基本信息”頁面上,從“管理項目”下拉菜單中單擊“編輯資源默認請求”。
在出現(xiàn)的對話框中,配置容器的默認請求和限制。
注:KubeSphere中的默認容器請求和限制在Kubernetes中稱為LimitRanges。
(2)以后創(chuàng)建工作負載時,請求和限制將自動填充。
對于運行關(guān)鍵業(yè)務(wù)流程的容器,它們需要比其他容器處理更多的流量。實際上并沒有什么萬能的解決方案,你需要根據(jù)這些容器的要求和限制做出謹慎而全面的決定。因此需要考慮以下問題:
①容器是CPU密集型還是IO密集型?
②它們的可用性高嗎?
③服務(wù)的上游和下游對象是什么?
如果長時間觀察一些容器的運行,就會發(fā)現(xiàn)它是周期性的。因此,在配置請求和限制時,歷史監(jiān)視數(shù)據(jù)可以作為重要的參考。對于集成到平臺中的Prometheus,KubeSphere具有強大而全面的可觀察性系統(tǒng),可以對資源進行更細致的監(jiān)視。在縱向上,它涵蓋了從集群到Pod的數(shù)據(jù);在橫向上,它跟蹤有關(guān)CPU、內(nèi)存、網(wǎng)絡(luò)和存儲的信息。通常情況下,可以基于歷史數(shù)據(jù)的平均值來指定請求,而限制則需要高于平均值。也就是說,可能需要根據(jù)需要對最終決定進行一些調(diào)整。
源代碼分析
現(xiàn)在已經(jīng)了解了配置請求和限制的一些優(yōu)秀實踐,以下將更深入地研究源代碼。
(1)請求和計劃
以下代碼顯示了Pod的請求與Pod中容器的請求之間的關(guān)系。
從上面的代碼可以看出,調(diào)度程序計算了要調(diào)度的Pod所需的資源。具體來說,它根據(jù)Pod規(guī)范分別計算初始化容器的總請求和工作容器的總請求,將會使用更大的一個。需要注意的是,對于輕量級虛擬機(例如kata容器),需要將自己的虛擬化資源消耗計入緩存中。在接下來的過濾階段,將檢查所有節(jié)點以查看它們是否滿足條件。
注:調(diào)度過程需要不同的階段,其中包括前置過濾器、過濾器、后置過濾器和評分。
在過濾之后,如果只有一個適用的節(jié)點,則會將Pod調(diào)度到該節(jié)點。如果有多個適用的Pod,則調(diào)度程序?qū)⑦x擇加權(quán)分數(shù)總和最高的節(jié)點。計分插件的實現(xiàn)基于多種因素,調(diào)度插件實現(xiàn)一個或多個擴展點。需要注意的是,請求的值和限制的值直接影響插件NodeResourcesLeastAllocated的最終結(jié)果。以下是源代碼:
對于NodeResourcesLeastAllocated,如果一個節(jié)點具有相同Pod的更多資源,則它將獲得更高的分數(shù)。換句話說,一個Pod將更有可能被調(diào)度到具有足夠資源的節(jié)點。
在創(chuàng)建Pod時,Kubernetes需要分配不同的資源,包括CPU和內(nèi)存。每種資源都有權(quán)重(源代碼中的resToWeightMap結(jié)構(gòu))??傮w而言,它們告訴Kubernetes調(diào)度程序,最佳的決定可能是實現(xiàn)資源平衡。在評分階段,除了NodeResourcesLeastAllocated外,調(diào)度程序還使用其他插件進行評分,例如InterPodAffinity。
(2)QoS和調(diào)度
作為Kubernetes中的一種資源保護機制,QoS主要用于控制不可壓縮的資源(例如內(nèi)存)。它還會影響不同Pod和容器的OOM分數(shù)。當節(jié)點內(nèi)存不足時,內(nèi)核(OOM Killer)終止優(yōu)先級較低的Pod(分數(shù)越高,優(yōu)先級越低)。以下是源代碼:
結(jié)語
作為一個可移植且可擴展的開源平臺,Kubernetes誕生于管理容器化工作負載和服務(wù)。它擁有一個全面的、快速發(fā)展的生態(tài)系統(tǒng),已經(jīng)幫助其鞏固了在容器編排中事實上的標準的地位。用戶學(xué)習(xí)Kubernetes并不是那么容易,而這正是KubeSphere發(fā)揮作用的地方。 KubeSphere使用戶可以在其儀表板上執(zhí)行幾乎所有操作,同時還可以選擇使用內(nèi)置的Web Kubectl工具來運行命令。本文重點介紹了請求和限制,它們在Kubernetes中的基本邏輯以及如何使用KubeSphere對其進行配置以簡化集群的操作和維護。
原文標題:Dive Deep Into Resource Requests and Limits in Kubernetes,作者:Sherlock Xu
【51CTO譯稿,合作站點轉(zhuǎn)載請注明原文譯者和出處為51CTO.com】