// 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. funcGetPodQOS(pod *v1.Pod) v1.PodQOSClass { 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...) 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)) { isGuaranteed = false } } iflen(requests) == 0 && len(limits) == 0 { return v1.PodQOSBestEffort } // 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 } return v1.PodQOSBurstable }
// rankMemoryPressure orders the input pods for eviction in response to memory pressure. // It ranks by whether or not the pod's usage exceeds its requests, then by priority, and // finally by memory usage above requests. funcrankMemoryPressure(pods []*v1.Pod, stats statsFunc) { orderedBy(exceedMemoryRequests(stats), priority, memory(stats)).Sort(pods) }
const ( // KubeletOOMScoreAdj is the OOM score adjustment for Kubelet KubeletOOMScoreAdj int = -999 // KubeProxyOOMScoreAdj is the OOM score adjustment for kube-proxy KubeProxyOOMScoreAdj int = -999 guaranteedOOMScoreAdj int = -997 besteffortOOMScoreAdj int = 1000 )
// GetContainerOOMScoreAdjust returns the amount by which the OOM score of all processes in the // container should be adjusted. // The OOM score of a process is the percentage of memory it consumes // multiplied by 10 (barring exceptional cases) + a configurable quantity which is between -1000 // and 1000. Containers with higher OOM scores are killed if the system runs out of memory. // See https://lwn.net/Articles/391222/ for more information. funcGetContainerOOMScoreAdjust(pod *v1.Pod, container *v1.Container, memoryCapacity int64)int { if types.IsNodeCriticalPod(pod) { // Only node critical pod should be the last to get killed. return guaranteedOOMScoreAdj }
switch v1qos.GetPodQOS(pod) { case v1.PodQOSGuaranteed: // Guaranteed containers should be the last to get killed. return guaranteedOOMScoreAdj case v1.PodQOSBestEffort: 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. ifint(oomScoreAdjust) < (1000 + guaranteedOOMScoreAdj) { return (1000 + guaranteedOOMScoreAdj) } // Give burstable pods a higher chance of survival over besteffort pods. ifint(oomScoreAdjust) == besteffortOOMScoreAdj { returnint(oomScoreAdjust - 1) } returnint(oomScoreAdjust) }