您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“Kubernetes Resource QoS Classes概念是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Kubernetes Resource QoS Classes概念是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
Kubernetes根據Pod中Containers Resource的request和limit的值來定義Pod的QoS Class。其中,指定容器request,代表系統確保能夠提供的資源下限值。指定容器limit,代表系統允許提供的資源上限值。
Pods需要保證長期穩定運行需要設定“確保運行的最少資源”,然而pod能夠使用的資源經常是不能確保的。
通常,Kubernetes通過設置request和limit的值來指定超賣比例,進而提升資源利用率。K8S的調度基于request,而不是limit。Borg通過使用“non-guranteed”的資源,提升了20%的資源利用率。
在一個資源被“超賣”的系統(總limits > machine capacity),容器在資源被耗盡的情況下會被kill。理想情況是那些“不重要”的容器先被kill。
對于每一種Resource都可以將容器分為3中QoS Classes: Guaranteed, Burstable, and Best-Effort,它們的QoS級別依次遞減。K8S底層實際上是通過 limit和request值來實現不同等級QoS的劃分。
Guaranteed 如果Pod中所有Container的所有Resource的limit和request都相等且不為0,則這個Pod的QoS Class就是Guaranteed。
注意,如果一個容器只指明了limit,而未指明request,則表明request的值等于limit的值。
Examples: containers: name: foo resources: limits: cpu: 10m memory: 1Gi name: bar resources: limits: cpu: 100m memory: 100Mi containers: name: foo resources: limits: cpu: 10m memory: 1Gi requests: cpu: 10m memory: 1Gi name: bar resources: limits: cpu: 100m memory: 100Mi requests: cpu: 100m memory: 100Mi
Best-Effort 如果Pod中所有容器的所有Resource的request和limit都沒有賦值,則這個Pod的QoS Class就是Best-Effort.
Examples: containers: name: foo resources: name: bar resources:
Burstable 除了符合Guaranteed和Best-Effort的場景,其他場景的Pod QoS Class都屬于Burstable。 當limit值未指定時,其有效值其實是對應Node Resource的Capacity。
Examples: 容器bar沒有對Resource進行指定。
containers: name: foo resources: limits: cpu: 10m memory: 1Gi requests: cpu: 10m memory: 1Gi name: bar
容器foo和bar對不同的Resource進行了指定。
containers: name: foo resources: limits: memory: 1Gi name: bar resources: limits: cpu: 100m
容器foo未指定limit,容器bar未指定request和limit。
containers: name: foo resources: requests: cpu: 10m memory: 1Gi name: bar
kube-scheduler調度時,是基于Pod的request值進行Node Select完成調度的。Pod和它的所有Container都不允許Consume limit指定的有效值(if have)。
request和limit如何生效,依賴于資源是否是壓縮的
目前僅支持CPU。
Pods確保可以獲取請求的CPU總量,但并不能獲得額外的CPU時間。這并不能完全確保容器能夠用到設置的資源下限值,因為CPU隔離是容器級別的。之后會引入Pod級別的cgroups資源隔離來解決這個問題。
過量/競爭使用CPU資源,會基于CPU request設置。可通過cpu.share來分派不同比例的時間片來理解,如果某個容器A的request 設置為600 milli,容器B設置為300mili , 兩者競爭CPU時間時,通過2:1的比例來分配。
如果達到Pod CPU資源limit上限,CPU會減速(throttled),而不是kill pod。如果pod沒有設置limit上限,pods可以使用超過CPU limit上限。
目前僅支持內存。
Pods可以拿到requests設置的內存總量。如果某個pod超過memory request值,當其他pod需要內存時,這個pod可能被kill掉。但是如果pods使用內存少于request值,它們不會被kill,除非系統任務或daemon需要更多資源。(說白了,還是要看觸發oom killer時,遍歷系統上所有進程打分的情況。)
當Pods使用內存超過了limit,某個在pod中容器內進程使用了大量內存,則該進程會被內核kill掉.
Pods由kubelet 確認和 scheduler 調度,會基于分配給容器的requests值,確保所有容器的requests總量在Node可分配容量的范圍之內。https://github.com/fabric8io/jenkinshift/blob/master/vendor/k8s.io/kubernetes/docs/proposals/node-allocatable.md
CPU 當CPU使用不能達到request值,比如系統任務和daemons使用了大量CPU,則Pods不會被kill,CPU效率會下降(throttled)。
Memory 內存是不可壓縮資源,從內存管理的角度做如下區分:
Best-Effort pods 優先級最低。如果系統內存耗盡,該類型的pods中的進程最先被kill。這些容器可以使用系統上任意量的空閑內存。
Guaranteed pods 優先級最高。它們能夠確保不達到容器設置的limit上限一定不會被kill。只有在系統存在內存壓力且沒有更低優先級容器時才被驅逐。
Burstable pods 有一些形式的最小資源保證,但當需要時可以使用更多資源。在系統存在內存瓶頸時,一旦內存超過他們的request值并且沒有Best-Effort 類型的容器存在,這些容器就先被kill掉。
mm/oom_kill.c 中的badness()給每個進程一個OOM score,更高OOM得分的進程更容易被kill。得分取決于:
主要是看進程的內存消耗情況,包括駐留內存、pagetable和swap的使用
一般是內存耗費的百分比*10(percent-times-ten)
參考用戶權限,比如root權限啟動的進程,打分會減少30。
OOM打分因子:/proc/pid/oom_score_adj (加減) 和 /proc/pid/oom_adj(乘除)
oom_adj: -15~ 15的系數調整
oom_score_adj:oom_score會加上oom_score_adj這個值
最終oom score的值 還是在 0~1000
這里提供一個計算系統上oom_score分數TPO10進程(最容易被oom killer殺掉的進程)腳本:
# vim oomscore.sh #!/bin/bash for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do printf "%2d %5d %s\n" \ "$(cat $proc/oom_score)" \ "$(basename $proc)" \ "$(cat $proc/cmdline | tr '\0' ' ' | head -c 50)" done 2>/dev/null | sort -nr | head -n 10
以下是幾種K8S QoS 等級的OOM score:
Set OOM_SCORE_ADJ: 1000
所以best-effort容器的OOM_SCORE 值為1000
Set OOM_SCORE_ADJ: -998
所以guaranteed容器的OOM_SCORE 值為0 或 1
如果總的memory request 大于 99.9%的可用內存,OOM_SCORE_ADJ設置為 2。否則, OOM_SCORE_ADJ = 1000 - 10 * (% of memory requested),這確保了burstable的 POD OOM_SCORE > 1
如果memory request設置為0,OOM_SCORE_ADJ 默認設置為999。所以如果burstable pods和guaranteed pods沖突時,前者會被kill。
如果burstable pod使用的內存少于request值,那它的OOM_SCORE < 1000。如果best-effort pod和這些 burstable pod沖突時,best-effort pod會先被kill掉。
如果 burstable pod容器中進程使用比request值的內存更多,OOM_SCORE設置為1000。反之,OOM_SCORES少于1000。
在一堆burstable pod中,使用內存超過request值的pod,優先于內存使用少于request值的pod被kill。
如果 burstable pod 有多個進程沖突,則OOM_SCORE會被隨機設置,不受“request & limit”限制。
OOM_SCORE_ADJ: -998
OOM_SCORE_ADJ: -999 (won’t be OOM killed)
系統上的關鍵進程,如果和guranteed 進程沖突,則會優先被kill 。將來會被放到一個單獨的cgroup中,并且限制內存。
支持swap: 當前QoS策略默認swap關閉。如果開啟swap,那些guaranteed 容器資源使用達到limit值,還可以使用磁盤來提供內存分配。最終,當swap空間不夠時,pod中的進程才會被kill.此時,node需要在提供隔離策略時,把swap空間考慮進去。
提供用戶指定優先級:用戶讓kubelet指定哪些tasks可以被kill.
QoS的源碼位于:pkg/kubelet/qos,代碼非常簡單,主要就兩個文件pkg/kubelet/qos/policy.go,pkg/kubelet/qos/qos.go。 上面討論的各個QoS Class對應的OOM_SCORE_ADJ定義在:
pkg/kubelet/qos/policy.go:21 const ( PodInfraOOMAdj int = -998 KubeletOOMScoreAdj int = -999 DockerOOMScoreAdj int = -999 KubeProxyOOMScoreAdj int = -999 guaranteedOOMScoreAdj int = -998 besteffortOOMScoreAdj int = 1000 )
容器的OOM_SCORE_ADJ的計算方法定義在:
pkg/kubelet/qos/policy.go:40 func GetContainerOOMScoreAdjust(pod *v1.Pod, container *v1.Container, memoryCapacity int64) int { switch GetPodQOS(pod) { case Guaranteed: // Guaranteed containers should be the last to get killed. return guaranteedOOMScoreAdj case BestEffort: return besteffortOOMScoreAdj } // Burstable containers are a middle tier, between Guaranteed and Best-Effort. Ideally, // we want to protect Burstable containers that consume less memory than requested. // The formula below is a heuristic. A container requesting for 10% of a system's // memory will have an OOM score adjust of 900. If a process in container Y // uses over 10% of memory, its OOM score will be 1000. The idea is that containers // which use more than their request will have an OOM score of 1000 and will be prime // targets for OOM kills. // Note that this is a heuristic, it won't work if a container has many small processes. 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) }
獲取Pod的QoS Class的方法為:
pkg/kubelet/qos/qos.go:50 // GetPodQOS returns the QoS class of a pod. // A pod is besteffort if none of its containers have specified any requests or limits. // A pod is guaranteed only when requests and limits are specified for all the containers and they are equal. // A pod is burstable if limits and requests do not match across all containers. func GetPodQOS(pod *v1.Pod) QOSClass { requests := v1.ResourceList{} limits := v1.ResourceList{} zeroQuantity := resource.MustParse("0") isGuaranteed := true for _, container := range pod.Spec.Containers { // process requests for name, quantity := range container.Resources.Requests { if !supportedQoSComputeResources.Has(string(name)) { continue } if quantity.Cmp(zeroQuantity) == 1 { delta := quantity.Copy() 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 !supportedQoSComputeResources.Has(string(name)) { continue } if quantity.Cmp(zeroQuantity) == 1 { qosLimitsFound.Insert(string(name)) delta := quantity.Copy() if _, exists := limits[name]; !exists { limits[name] = *delta } else { delta.Add(limits[name]) limits[name] = *delta } } } if len(qosLimitsFound) != len(supportedQoSComputeResources) { isGuaranteed = false } } if len(requests) == 0 && len(limits) == 0 { return BestEffort } // 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 Guaranteed } return Burstable }
PodQoS會在eviction_manager和scheduler的Predicates階段被調用,也就說會在k8s處理超配和調度預選階段中被使用。
讀到這里,這篇“Kubernetes Resource QoS Classes概念是什么”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。