如何管理Kubernetes集群的容量與資源
譯文【51CTO.com快譯】眾所周知,系統(tǒng)資源并非無限的。在那些大型集群即服務(wù)的場景中,我們需要認(rèn)真地布局和規(guī)劃集群資源的配比。不過,在各種軟件項目中,開發(fā)人員往往會錯誤地認(rèn)為虛擬化和容器化能夠讓資源看起來更像個巨大的池子,可用隨意使用。例如,他們在嘗試運行某個需要大量資源的應(yīng)用,尤其是在啟用了自動擴展功能的群集上時,就可能看到如下圖所示的情況:
顯然,通過kubectl get,我們發(fā)現(xiàn)有數(shù)十個evicted pod,而實際上可能只想運行5個pod。此時,您可能非常希望通過對Kubernetes集群資源的管理,來自動實現(xiàn)對于容量和資源的分配。
兩個示例
如上圖所示,假設(shè)我們手頭有一個帶有16個虛擬CPU和64GB RAM的Kubernetes集群。那么,我們可以在它上面流暢地運行一個需要20GB內(nèi)存的AI容器嗎?
假設(shè)該集群中有4個worker,每個都需要有16GB的可用內(nèi)存(實際上,DaemonSet和系統(tǒng)服務(wù)都需要運行一個節(jié)點,并占用少量的資源,因此真實可用內(nèi)存可能會更少一些)。那么,在這種情況下,如果我們只分配16GB內(nèi)存給容器的話,我們將無法保證其流暢運行。
其實,不僅此類大容器的部署,我們在進行其他復(fù)雜的部署,甚至是采用Helm chart(請參見-- https://grapeup.com/blog/asp-net-core-ci-cd-on-azure-pipelines-with-kubernetes-and-helm/)之類開箱即用的產(chǎn)品時,都必須始終考慮到資源的限制問題。
讓我們來看另一個示例--將Ceph部署到同一個集群中。我們的實現(xiàn)目標(biāo)是將1TB的存儲空間分成10個OSD(object storage daemons,對象存儲守護程序)和3個ceph MON(監(jiān)視器)。我們希望將其放置在兩個節(jié)點上,其余兩個則留給需要使用該存儲的部署。這將是一個高度可擴展的架構(gòu)。
一般用戶首先能夠想到的做法是將OSD的數(shù)量設(shè)置為10,MON設(shè)置為3,將tolerations添加到Ceph的pod中,以及將taint匹配上Node 1和Node 2。而所有的ceph部署和pod都將nodeSelector設(shè)置為僅針對Node 1和2。
如下圖所示,Kubernetes會讓mon-1、mon-2和5個osd運行在第一個worker上,讓mon-3和另5個osds運行在第二個worker上。應(yīng)用程序可以快速地將大量的大體積文件保存到Ceph上。
如果我們還部署了儀表板,并創(chuàng)建了一個復(fù)制池,那么還可以直觀地看到1TB的可用存儲空間和10個OSD的狀態(tài)。
不過,在運行了一段時間后,我們會發(fā)現(xiàn)真正可用的存儲空間只剩下了400GB,出現(xiàn)了許多evicted OSD pods,而且有4個OSDs正在同時運行。對此,我們需要重新審視初始時的部署配置。
極限和范圍
平時,就算我們運行了13個Pod(其中可能有3個監(jiān)控器),也不會占用過多的資源,但是OSD則不然。由于Ceph在內(nèi)存中緩存了很大量的數(shù)據(jù),那么我們使用得越頻繁,它需要的資源也就越多。同時,各種存儲容器的數(shù)據(jù)復(fù)制和平衡也需要消耗一定的空間。因此,在初次化部署之后,內(nèi)存的分配情況會如下圖所示:
而在數(shù)小時的持續(xù)運行之后,該集群就會出現(xiàn)如下狀況:
可見,我們損失了幾乎50%的pod。而且這并非是最終狀態(tài),如果高吞吐量將目標(biāo)指向剩余的容器,那么我們很快會失去得更多。那么,這是否意味著我們需要給Ceph集群配置超過32GB的內(nèi)存呢?非也。只要我們正確地設(shè)置了限制(請參見--https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container),單個OSD就不能從其他pod處搶奪所有的可用內(nèi)存。
也就是說,在這種情況下,我們最簡單的方法是:為mon整體分配并保留2GB的內(nèi)存,其中每個的極限為650MB;將一共30GB的內(nèi)存除以10個OSD(請見下圖):
由于我們?yōu)镺SD分配了15GB的內(nèi)存,并為每個Pod配置了650MB的內(nèi)存,因此第一個節(jié)點會需要:15 + 2 * 0.65 = 16.3GB。此外,我們同樣需要考慮到在同一節(jié)點上運行的DaemonSet日志。因此,修正值應(yīng)該是:
服務(wù)質(zhì)量
如果我們還為Pod設(shè)置了一個與限制完全匹配的請求,那么Kubernetes將會以不同的方式來對待此類Pod,如下圖所示:
該配置將Kubernetes中的QoS設(shè)置為Guaranteed(否則是Burstable)。有Guaranteed的Pod是永遠(yuǎn)不會被evicte的。通過設(shè)置相同的請求和限制,我們可以確保Pod的資源使用情況,而無需顧及Kubernetes對其進行移動或管理。此舉雖然降低了調(diào)度程序(scheduler)的靈活性,但是能夠讓整個部署方式更具有一定的彈性。
自動擴展環(huán)境中的資源
對于關(guān)鍵性任務(wù)系統(tǒng)(mission-critical systems,請參見--https://grapeup.com/)而言,光靠估算所需的資源,來匹配群集的大小,并做好相關(guān)限制是遠(yuǎn)遠(yuǎn)不夠的。有時候,我們需要通過更加復(fù)雜的配置,以及非固定的集群容量,來實現(xiàn)水平擴展和調(diào)整可用的worker數(shù)量。
假設(shè)資源會呈線性擴展的話,那么我們可以同時規(guī)劃最小和最大群集的容量。而如果pod能夠被允許在群集擴展時,跟蹤那些按比例在水平方向和垂直方向的擴展的話,那么它在按等比收縮時,則可能會“逐出”其他的pod。為了緩解該問題,Kubernetes提出了兩個主要概念:Pod Priority和Pod Disruption Budget。
下面,讓我們從創(chuàng)建測試場景開始討論。這次我們不需要大量的節(jié)點,只需要創(chuàng)建一個具有兩個節(jié)點組的集群:一個由常規(guī)實例組成(稱為持久性),一個由可搶占(preemptible/spot)實例組成。如下圖所示,當(dāng)VM(現(xiàn)有節(jié)點)的CPU使用率超過0.7(即70%)時,可搶占節(jié)點組將進行擴展。
可搶占實例的優(yōu)勢在于它們比具有相同性能的常規(guī)VM要容易實現(xiàn)得多。而唯一缺點是無法保證其生命周期。也就是說,當(dāng)云提供商出于維護目的,或在24小時之后決定在其他地方需要實例時,該實例就可能會被“逐出”。因此,我們只能在其中運行那些可容錯的無狀態(tài)負(fù)載。
那么,集群中為什么只有一個持久性節(jié)點呢?這是為極端情況做準(zhǔn)備的。當(dāng)所有可搶占節(jié)點均未運行時,它將維護一個最少的容器集,以管理和保障應(yīng)用程序的可操作性。下表展示了此類例程的結(jié)構(gòu)。我們可以使用節(jié)點選擇器將redis master配置為能夠在持久性節(jié)點上運行。
Pod Priority
下面,我們來看一個水平pod自動擴展器(Horizontal Pod Autoscaler,HPA)的例子。
前端:
后端:
視頻轉(zhuǎn)換器:
作為一款視頻轉(zhuǎn)換器,它的目標(biāo)是降低平均資源的占有率。也就是說,通過檢查擴展策略,當(dāng)有多個轉(zhuǎn)換隊列時,其CPU平均使用率可能會迅速達(dá)到25%,那么它就會產(chǎn)生新的自動化擴展。例如:如果在大約10分鐘的時間內(nèi),需要進行50次視頻轉(zhuǎn)換,那么該轉(zhuǎn)換器就會擴展出25個實例。那么,為了避免集群中的其他容器被evicte,我們可以創(chuàng)建一種優(yōu)先級類別(請參見-- https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption):優(yōu)先級較高的pod對于調(diào)度程序而言,具有更高的價值;而優(yōu)先級較低的pod,則可以被evicte。
因此,如果我們給予轉(zhuǎn)換器較低的優(yōu)先級,那么就是默認(rèn)了前端和后端Pod更為重要。在最壞的情況下,該視頻轉(zhuǎn)換器可以從群集中逐出。
Pod Disruption Budget
作為更好的pod控制與調(diào)度方法,Pod Disruption Budget(PDB)使我們可以一次性配置最少數(shù)量的pod。由于有效地阻止了節(jié)點資源被耗盡,因此它比僅使用Pod Priority要更加嚴(yán)格。如果其他worker上沒有足夠的空間用來重新調(diào)度pod,它會保證副本的數(shù)量不少于可分配的預(yù)定。
上表展示了最基本的配置。其中,前端副本數(shù)不低于2。我們可以據(jù)此為所有Pod分配一個最小值,并確保始終至少有1到2個pod可以處理請求。
這是確保pod能夠自動擴展、集群可以伸縮的最簡單、也是最安全的方法。只要我們配置了帶有中斷預(yù)定的最少容器集,就能夠在不會影響整體穩(wěn)定性的基礎(chǔ)上,滿足最小集群容量、以及各種請求的最低處理要求。
至此,我們已擁有了創(chuàng)建穩(wěn)定方案所需的全部必需組件。我們可以將HPA配置為與PDB相同的最小副本數(shù),以簡化調(diào)度程序的工作。同時,我們需要根據(jù)最大群集數(shù),來確保限制數(shù)與請求數(shù)不但相同,且不會evicte pod。具體配置如下表所示:
基于上述調(diào)度程序的靈活性,在前端和后端的負(fù)載過低,卻有大量數(shù)據(jù)需要轉(zhuǎn)換時,該轉(zhuǎn)換器會自動擴展出19-21個實例。
自動擴展的注意事項
關(guān)于自動擴展,我們需要注意如下兩個方面:
首先,由于我們無法確定云服務(wù)提供商的虛擬機啟動時長(可能幾秒鐘,也可能需要幾分鐘),因此我們無法保障自動擴展肯定能夠解決峰值負(fù)載的問題。
其次,在集群縮減時,對于那些正在運行組件,我們需要通過反復(fù)測試,讓調(diào)度程序能夠快速地將負(fù)載移至其他worker處,以實現(xiàn)在不破壞應(yīng)用操作的前提下,有效地關(guān)閉虛擬機。
原標(biāo)題:Kubernetes Cluster Management: Size and Resources,作者:Adam Kozlowski
【51CTO譯稿,合作站點轉(zhuǎn)載請注明原文譯者和出處為51CTO.com】