Kubernetes集群多租戶資源管理
1.概述
先講解Pod的兩個重要參數(shù):CPU Request與Memory Request。在大多數(shù)情況下我們在定義Pod時并沒有定義這兩個參數(shù),此時Kubernetes會認為該Pod所需的資源很少,并可以將其調(diào)度到任何可用的Node上。這樣一來,當(dāng)集群中的計算資源不很充足時,如果集群中的Pod負載突然加大,就會使某個Node的資源嚴重不足。
為了避免系統(tǒng)掛掉,該Node會選擇“清理”某些Pod來釋放資源,此時每個Pod都可能成為犧牲品。但有些Pod擔(dān)負著更重要的職責(zé),比其他Pod更重要,比如與數(shù)據(jù)存儲相關(guān)的、與登錄相關(guān)的、與查詢余額相關(guān)的,即使系統(tǒng)資源嚴重不足,也需要保障這些Pod的存活,Kubernetes中該保障機制的核心如下。
- 通過資源限額來確保不同的Pod只能占用指定的資源
- 允許集群的資源被超額分配,以提高集群的資源利用率
- 為Pod劃分等級,確保不同等級的Pod有不同的服務(wù)質(zhì)量(QoS),資源不足時,低等級的Pod會被清理,以確保高等級的Pod穩(wěn)定運行
Kubernetes集群里的節(jié)點提供的資源主要是計算資源,計算資源是可計量的能被申請、分配和使用的基礎(chǔ)資源,這使之區(qū)別于API資源(API Resources,例如Pod和Services等)。當(dāng)前Kubernetes集群中的計算資源主要包括CPU、GPU及Memory,絕大多數(shù)常規(guī)應(yīng)用是用不到GPU的,因此這里重點介紹CPU與Memory的資源管理問題
CPU與Memory是被Pod使用的,因此在配置Pod時可以通過參數(shù)CPU Request及Memory Request為其中的每個容器指定所需使用的CPU與Memory量,Kubernetes會根據(jù)Request的值去查找有足夠資源的Node來調(diào)度此Pod,如果沒有,則調(diào)度失敗。
2.Pod資源使用規(guī)范
我們知道,一個pod所使用的CPU與Memory是一個動態(tài)的量,確切地說,是一個范圍,跟它的負載密切相關(guān):負載增加時,CPU和Memory的使用量也會增加。因此最準(zhǔn)確的說法是,某個進程的CPU使用量為0.1個CPU~1個CPU,內(nèi)存占用則為500MB~1GB。對應(yīng)到Kubernetes的Pod容器上,cpu和Memory 分別有兩個限制:
- Requests 表示業(yè)務(wù)正常運行所需要資源 屬于預(yù)留資源
- Limit 表示業(yè)務(wù)最大使用資源 該值為不保障資源 資源足夠情況下最大使用資源值
其中CPU 為可壓縮資源 按照時間片進行調(diào)度,Memory 為不可壓縮資源 屬于硬限制資源類型,limits對應(yīng)資源量的上限,即最多允許使用這個上限的資源量。由于CPU資源是可壓縮的,進程無論如何也不可能突破上限,因此設(shè)置起來比較容易。對于Memory這種不可壓縮資源來說,它的Limit設(shè)置就是一個問題了,如果設(shè)置得小了,當(dāng)進程在業(yè)務(wù)繁忙期試圖請求超過Limit限制的Memory時,此進程就會被Kubernetes殺掉。因此,Memory的Request與Limit的值需要結(jié)合進程的實際需求謹慎設(shè)置。如果不設(shè)置CPU或Memory的Limit值,會怎樣呢?在這種情況下,該Pod的資源使用量有一個彈性范圍,我們不用絞盡腦汁去思考這兩個Limit的合理值,但問題也來了,考慮下面的例子:
Pod A的Memory Request被設(shè)置為1GB,Node A當(dāng)時空閑的Memory為1.2GB,符合Pod A的需求,因此Pod A被調(diào)度到Node A上。運行3天后,Pod A的訪問請求大增,內(nèi)存需要增加到1.5GB,此時Node A的剩余內(nèi)存只有200MB,由于PodA新增的內(nèi)存已經(jīng)超出系統(tǒng)資源,所以在這種情況下,Pod A就會被Kubernetes殺掉。
沒有設(shè)置Limit的Pod,或者只設(shè)置了CPU Limit或者Memory Limit兩者之一的Pod,表面看都是很有彈性的,但實際上,相對于4個參數(shù)都被設(shè)置的Pod,是處于一種相對不穩(wěn)定的狀態(tài)的,它們與4個參數(shù)都沒設(shè)置的Pod相比,只是穩(wěn)定一點而已。理解了這一點,就很容易理解Resource QoS問題了。
如果我們有成百上千個不同的Pod,那么先手動設(shè)置每個Pod的這4個參數(shù),再檢查并確保這些參數(shù)的設(shè)置,都是合理的。比如不能出現(xiàn)內(nèi)存超過2GB或者CPU占據(jù)2個核心的Pod。最后還得手工檢查不同租戶(Namespace)下的Pod的資源使用量是否超過限額。為此,Kubernetes提供了另外兩個相關(guān)對象:LimitRange及ResourceQuota,前者解決request與limit參數(shù)的默認值和合法取值范圍等問題,后者則解決約束租戶的資源配額問題。
- CPU 相關(guān)規(guī)則如下:
單位m,10m=0.01核,1核=1000m
Requests 根據(jù)業(yè)務(wù)實際使用量進行預(yù)估填寫
Limits = Requests * 20% + Requests
- Memory 相關(guān)規(guī)則如下:
單位Mi 1024Mi=1G內(nèi)存
Requests 根據(jù)業(yè)務(wù)實際使用量進行預(yù)估填寫
Limits = Requests * 20% + Requests
3.Namespace資源管理規(guī)范
業(yè)務(wù)實際Requests Limit 不超過整體80% 防止業(yè)務(wù)滾動更新無足夠資源創(chuàng)建Pod
3.1 多租戶資源使用策略
通過ResourceQuota限制對應(yīng)項目組資源用量
3.2 資源用量變更流程
4.資源監(jiān)控及檢查
4.1 資源使用監(jiān)控
- Namespace Reuqests資源使用率
- sum (kube_resourcequota{type="used",resource="requests.cpu"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="requests.cpu"}) by (resource,namespace) * 100
- sum (kube_resourcequota{type="used",resource="requests.memory"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="requests.memory"}) by (resource,namespace) * 100
- Namespace Limit資源使用率
- sum (kube_resourcequota{type="used",resource="limits.cpu"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="limits.cpu"}) by (resource,namespace) * 100
- sum (kube_resourcequota{type="used",resource="limits.memory"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="limits.memory"}) by (resource,namespace) * 100
4.2 通過Grafana 進行查看
- CPU請求率
- sum (kube_resourcequota{type="used",resource="requests.cpu",namespace=~"$NameSpace"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="requests.cpu",namespace=~"$NameSpace"}) by (resource,namespace)
- 內(nèi)存請求率
- sum (kube_resourcequota{type="used",resource="requests.memory",namespace=~"$NameSpace"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="requests.memory",namespace=~"$NameSpace"}) by (resource,namespace)
- CPU限制率
- sum (kube_resourcequota{type="used",resource="limits.cpu"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="limits.cpu"}) by (resource,namespace)
- 內(nèi)存限制率
- sum (kube_resourcequota{type="used",resource="limits.memory"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="limits.memory"}) by (resource,namespace)
4.3 集群內(nèi)查看資源使用
- 查看資源使用量
- [root@k8s-dev-slave04 yaml]# kubectl describe resourcequotas -n cloudchain--staging
- Name: mem-cpu-demo
- Namespace: cloudchain--staging
- Resource Used Hard
- -------- ---- ----
- limits.cpu 200m 500m
- limits.memory 200Mi 500Mi
- requests.cpu 150m 250m
- requests.memory 150Mi 250Mi
- 查看event事件 判斷是否正常創(chuàng)建
- [root@kevin ~]# kubectl get event -n default
- LAST SEEN TYPE REASON OBJECT MESSAGE
- 46m Warning FailedCreate replicaset/hpatest-57965d8c84 Error creating: pods "hpatest-57965d8c84-s78x6" is forbidden: exceeded quota: mem-cpu-demo, requested: limits.cpu=400m,limits.memory=400Mi, used: limits.cpu=200m,limits.memory=200Mi, limited: limits.cpu=500m,limits.memory=500Mi
- 29m Warning FailedCreate replicaset/hpatest-57965d8c84 Error creating: pods "hpatest-57965d8c84-5w6lk" is forbidden: exceeded quota: mem-cpu-demo, requested: limits.cpu=400m,limits.memory=400Mi, used: limits.cpu=200m,limits.memory=200Mi, limited: limits.cpu=500m,limits.memory=500Mi
- 13m Warning FailedCreate replicaset/hpatest-57965d8c84 Error creating: pods "hpatest-57965d8c84-w2qvz" is forbidden: exceeded quota: mem-cpu-demo, requested: limits.cpu=400m,limits.memory=400Mi, used: limits.cpu=200m,limits.memory=200Mi, limited: limits.cpu=500m,limits.memory=500Mi
本文轉(zhuǎn)載自微信公眾號「運維開發(fā)故事」