您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“kubernetes資源QOS機制實現(xiàn)原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“kubernetes資源QOS機制實現(xiàn)原理是什么”吧!
QOS是k8s中一種資源保護機制,其主要是針對不可壓縮資源比如的內(nèi)存的一種控制技術(shù),比如在內(nèi)存中其通過為不同的Pod和容器構(gòu)造OOM評分,并且通過內(nèi)核的策略的輔助,從而實現(xiàn)當節(jié)點內(nèi)存資源不足的時候,內(nèi)核可以按照策略的優(yōu)先級,優(yōu)先kill掉哪些優(yōu)先級比較低(分值越高優(yōu)先級越低)的Pod,今天來分析下背后的實現(xiàn)
在Linux中一切皆文件,控制CGroup本身也是通過配置文件進行的,這是我創(chuàng)建的一個內(nèi)存Lmits為200M的Pod的容器的配置
# pwd /sys/fs/cgroup # cat ./memory/kubepods/pod8e172a5c-57f5-493d-a93d-b0b64bca26df/f2fe67dc90cbfd57d873cd8a81a972213822f3f146ec4458adbe54d868cf410c/memory.limit_in_bytes 209715200
這里我們重點關(guān)注內(nèi)存相關(guān)的兩個配置:VMOvercommitMemory其值為1,表示運行分配所有的物理內(nèi)存資源,注意不包括SWAP資源VMPanicOnOOM其值為0:表示當內(nèi)存不足的時候觸發(fā)oom_killer進行選擇部分進程進行kill,QOS也是通過影響其kill流程來實現(xiàn)的
func setupKernelTunables(option KernelTunableBehavior) error { desiredState := map[string]int{ utilsysctl.VMOvercommitMemory: utilsysctl.VMOvercommitMemoryAlways, utilsysctl.VMPanicOnOOM: utilsysctl.VMPanicOnOOMInvokeOOMKiller, utilsysctl.KernelPanic: utilsysctl.KernelPanicRebootTimeout, utilsysctl.KernelPanicOnOops: utilsysctl.KernelPanicOnOopsAlways, utilsysctl.RootMaxKeys: utilsysctl.RootMaxKeysSetting, utilsysctl.RootMaxBytes: utilsysctl.RootMaxBytesSetting, }
QOS打分機制主要是根據(jù)Requests和limits里面的資源限制來進行類型判定與打分的,我們就來快速看下這部分的實現(xiàn)
遍歷所有的容器列表,注意這里會包含所有的初始化容器和業(yè)務(wù)容器
requests := v1.ResourceList{} limits := v1.ResourceList{} zeroQuantity := resource.MustParse("0") isGuaranteed := true allContainers := []v1.Container{} allContainers = append(allContainers, pod.Spec.Containers...) // 追加所有的初始化容器 allContainers = append(allContainers, pod.Spec.InitContainers...)
這里遍歷所有的Requests和Limits限制的資源,分別加入到不同的資源集合匯總,其中判定是不是Guaranteed主要是根據(jù)limits里面的資源是否包含CPU和內(nèi)存兩種資源,都包含才可能是Guaranteed
for _, container := range allContainers { // process requests for name, quantity := range container.Resources.Requests { if !isSupportedQoSComputeResource(name) { continue } if quantity.Cmp(zeroQuantity) == 1 { delta := quantity.DeepCopy() if _, exists := requests[name]; !exists { requests[name] = delta } else { delta.Add(requests[name]) requests[name] = delta } } } // process limits qosLimitsFound := sets.NewString() for name, quantity := range container.Resources.Limits { if !isSupportedQoSComputeResource(name) { continue } if quantity.Cmp(zeroQuantity) == 1 { qosLimitsFound.Insert(string(name)) delta := quantity.DeepCopy() if _, exists := limits[name]; !exists { limits[name] = delta } else { delta.Add(limits[name]) limits[name] = delta } } } if !qosLimitsFound.HasAll(string(v1.ResourceMemory), string(v1.ResourceCPU)) { // 必須是全部包含cpu和內(nèi)存限制 isGuaranteed = false } }
如果Pod里面的容器沒有任何requests和limits的限制則就是BestEffort
if len(requests) == 0 && len(limits) == 0 { return v1.PodQOSBestEffort }
要是Guaranteed必須是資源相等,并且限定的數(shù)量相同
// Check is requests match limits for all resources. if isGuaranteed { for name, req := range requests { if lim, exists := limits[name]; !exists || lim.Cmp(req) != 0 { isGuaranteed = false break } } } if isGuaranteed && len(requests) == len(limits) { return v1.PodQOSGuaranteed }
如果不是上面兩種就是最后一種burstable了
return v1.PodQOSBurstable
其中g(shù)uaranteedOOMScoreAdj是-998其實這跟OOM實現(xiàn)有關(guān)系,一臺node節(jié)點上主要是三部分組成:kubelet主進程、docker進程、業(yè)務(wù)容器進程,而OOM的打分里面-1000表示該進程不會被oom所kill, 那一個業(yè)務(wù)進程最少也就只能是-999因為你不能保證自己的業(yè)務(wù)永遠不會出現(xiàn)問題,所以在QOS里面-999其實就是kubelet和docker進程所保留的,剩下的才能作為業(yè)務(wù)容器分配(分值越高越容易被kill)
// KubeletOOMScoreAdj is the OOM score adjustment for Kubelet KubeletOOMScoreAdj int = -999 // DockerOOMScoreAdj is the OOM score adjustment for Docker DockerOOMScoreAdj int = -999 // KubeProxyOOMScoreAdj is the OOM score adjustment for kube-proxy KubeProxyOOMScoreAdj int = -999 guaranteedOOMScoreAdj int = -998 besteffortOOMScoreAdj int = 1000
關(guān)鍵Pod是一種特殊的存在,它可以是Burstable或者BestEffort類型的Pod,但是OOM打分卻可以跟Guaranteed一樣,這種類型的Pod主要包含三種:靜態(tài)Pod、鏡像Pod和高優(yōu)先級Pod
if types.IsCriticalPod(pod) { return guaranteedOOMScoreAdj }
判定實現(xiàn)
func IsCriticalPod(pod *v1.Pod) bool { if IsStaticPod(pod) { return true } if IsMirrorPod(pod) { return true } if pod.Spec.Priority != nil && IsCriticalPodBasedOnPriority(*pod.Spec.Priority) { return true } return false }
這兩種類型都有各自默認的值分別為Guaranteed(-998)和BestEffort(1000)
switch v1qos.GetPodQOS(pod) { case v1.PodQOSGuaranteed: // Guaranteed containers should be the last to get killed. return guaranteedOOMScoreAdj case v1.PodQOSBestEffort: return besteffortOOMScoreAdj }
其中關(guān)鍵的一行就是:oomScoreAdjust := 1000 - (1000memoryRequest)/memoryCapacity,從這個計算里面可以看出,如果我們申請的資源越多,那么 (1000memoryRequest)/memoryCapacity這個里面計算出來的時機值就會越小,即最終結(jié)果就越大,其實也就表明如果我們占用的內(nèi)存越少,則打分就越高,這類容器就相對比較容易被kill
memoryRequest := container.Resources.Requests.Memory().Value() oomScoreAdjust := 1000 - (1000*memoryRequest)/memoryCapacity // A guaranteed pod using 100% of memory can have an OOM score of 10. Ensure that burstable pods have a higher OOM score adjustment. if int(oomScoreAdjust) < (1000 + guaranteedOOMScoreAdj) { return (1000 + guaranteedOOMScoreAdj) } // Give burstable pods a higher chance of survival over besteffort pods. if int(oomScoreAdjust) == besteffortOOMScoreAdj { return int(oomScoreAdjust - 1) } return int(oomScoreAdjust)
到此,相信大家對“kubernetes資源QOS機制實現(xiàn)原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。