Skip to content

Commit 5a64597

Browse files
committed
Adding OOM Score adjustment formula changes that takes pod level resources into account
Signed-off-by: ndixita <[email protected]>
1 parent 5ea57fb commit 5a64597

File tree

3 files changed

+490
-4
lines changed

3 files changed

+490
-4
lines changed

pkg/kubelet/qos/helpers.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ package qos // import "k8s.io/kubernetes/pkg/kubelet/qos"
2727

2828
import (
2929
v1 "k8s.io/api/core/v1"
30+
resourcehelper "k8s.io/component-helpers/resource"
3031
)
3132

3233
// minRegularContainerMemory returns the minimum memory resource quantity
@@ -41,3 +42,30 @@ func minRegularContainerMemory(pod v1.Pod) int64 {
4142
}
4243
return memoryValue
4344
}
45+
46+
// remainingPodMemReqPerContainer calculates the remaining pod memory request per
47+
// container by:
48+
// 1. Taking the total pod memory requests
49+
// 2. Subtracting total container memory requests from pod memory requests
50+
// 3. Dividing the remainder by the number of containers.
51+
// This gives us the additional memory request that is not allocated to any
52+
// containers in the pod. This value will be divided equally among all containers to
53+
// calculate oom score adjusment.
54+
// See https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2837-pod-level-resource-spec/README.md#oom-score-adjustment
55+
// for more details.
56+
func remainingPodMemReqPerContainer(pod *v1.Pod) int64 {
57+
var remainingMemory int64
58+
if pod.Spec.Resources.Requests.Memory().IsZero() {
59+
return remainingMemory
60+
}
61+
62+
numContainers := len(pod.Spec.Containers) + len(pod.Spec.InitContainers)
63+
64+
// Aggregated requests of all containers.
65+
aggrContainerReqs := resourcehelper.AggregateContainerRequests(pod, resourcehelper.PodResourcesOptions{})
66+
67+
remainingMemory = pod.Spec.Resources.Requests.Memory().Value() - aggrContainerReqs.Memory().Value()
68+
69+
remainingMemoryPerContainer := remainingMemory / int64(numContainers)
70+
return remainingMemoryPerContainer
71+
}

pkg/kubelet/qos/policy.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package qos
1919
import (
2020
v1 "k8s.io/api/core/v1"
2121
utilfeature "k8s.io/apiserver/pkg/util/feature"
22+
resourcehelper "k8s.io/component-helpers/resource"
2223
v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
2324
"k8s.io/kubernetes/pkg/features"
2425
"k8s.io/kubernetes/pkg/kubelet/types"
@@ -63,14 +64,41 @@ func GetContainerOOMScoreAdjust(pod *v1.Pod, container *v1.Container, memoryCapa
6364
// which use more than their request will have an OOM score of 1000 and will be prime
6465
// targets for OOM kills.
6566
// Note that this is a heuristic, it won't work if a container has many small processes.
66-
memoryRequest := container.Resources.Requests.Memory().Value()
67-
oomScoreAdjust := 1000 - (1000*memoryRequest)/memoryCapacity
67+
containerMemReq := container.Resources.Requests.Memory().Value()
68+
69+
var oomScoreAdjust, remainingReqPerContainer int64
70+
// When PodLevelResources feature is enabled, the OOM score adjustment formula is modified
71+
// to account for pod-level memory requests. Any extra pod memory request that's
72+
// not allocated to the containers is divided equally among all containers and
73+
// added to their individual memory requests when calculating the OOM score
74+
// adjustment. Otherwise, only container-level memory requests are used. See
75+
// https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2837-pod-level-resource-spec/README.md#oom-score-adjustment
76+
// for more details.
77+
if utilfeature.DefaultFeatureGate.Enabled(features.PodLevelResources) &&
78+
resourcehelper.IsPodLevelRequestsSet(pod) {
79+
// TODO(ndixita): Refactor to use this formula in all cases, as
80+
// remainingReqPerContainer will be 0 when pod-level resources are not set.
81+
remainingReqPerContainer = remainingPodMemReqPerContainer(pod)
82+
oomScoreAdjust = 1000 - (1000 * (containerMemReq + remainingReqPerContainer) / memoryCapacity)
83+
} else {
84+
oomScoreAdjust = 1000 - (1000*containerMemReq)/memoryCapacity
85+
}
6886

6987
// adapt the sidecarContainer memoryRequest for OOM ADJ calculation
7088
// calculate the oom score adjustment based on: max-memory( currentSideCarContainer , min-memory(regular containers) ) .
7189
if utilfeature.DefaultFeatureGate.Enabled(features.SidecarContainers) && isSidecarContainer(pod, container) {
7290
// check min memory quantity in regular containers
7391
minMemoryRequest := minRegularContainerMemory(*pod)
92+
93+
// When calculating minMemoryOomScoreAdjust for sidecar containers with PodLevelResources enabled,
94+
// we add the per-container share of unallocated pod memory requests to the minimum memory request.
95+
// This ensures the OOM score adjustment i.e. minMemoryOomScoreAdjust
96+
// calculation remains consistent
97+
// with how we handle pod-level memory requests for regular containers.
98+
if utilfeature.DefaultFeatureGate.Enabled(features.PodLevelResources) &&
99+
resourcehelper.IsPodLevelRequestsSet(pod) {
100+
minMemoryRequest += remainingReqPerContainer
101+
}
74102
minMemoryOomScoreAdjust := 1000 - (1000*minMemoryRequest)/memoryCapacity
75103
// the OOM adjustment for sidecar container will match
76104
// or fall below the OOM score adjustment of regular containers in the Pod.

0 commit comments

Comments
 (0)