Skip to content

Commit 06cab8e

Browse files
committed
fix: pod resource calculation to consider native sidecars
previously, descheduler code had copied an old version of PodRequestsAndLimits which does not consider native sidecars it will now rely on resourcehelper libs, which will continue to get upstream updates Signed-off-by: Amir Alavi <[email protected]>
1 parent 582641c commit 06cab8e

File tree

6 files changed

+535
-89
lines changed

6 files changed

+535
-89
lines changed

pkg/descheduler/node/node.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ func fitsRequest(nodeIndexer podutil.GetPodsAssignedToNodeFunc, pod *v1.Pod, nod
241241
return false, fmt.Errorf("insufficient %v", resource)
242242
}
243243
}
244-
// check pod num, at least one pod number is avaibalbe
244+
// check pod num, at least one pod number is available
245245
if quantity, ok := availableResources[v1.ResourcePods]; ok && quantity.MilliValue() <= 0 {
246246
return false, fmt.Errorf("insufficient %v", v1.ResourcePods)
247247
}

pkg/descheduler/node/node_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"k8s.io/apimachinery/pkg/runtime"
2929
"k8s.io/client-go/informers"
3030
"k8s.io/client-go/kubernetes/fake"
31+
"k8s.io/utils/ptr"
3132
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
3233
"sigs.k8s.io/descheduler/test"
3334
)
@@ -1020,6 +1021,64 @@ func TestNodeFit(t *testing.T) {
10201021
node: node,
10211022
podsOnNode: []*v1.Pod{},
10221023
},
1024+
{
1025+
description: "Pod with native sidecars with too much cpu does not fit on node",
1026+
pod: test.BuildTestPod("p1", 1, 100, "", func(pod *v1.Pod) {
1027+
pod.Spec.InitContainers = append(pod.Spec.InitContainers, v1.Container{
1028+
RestartPolicy: ptr.To(v1.ContainerRestartPolicyAlways), // native sidecar
1029+
Resources: v1.ResourceRequirements{
1030+
Requests: createResourceList(100000, 100*1000*1000, 0),
1031+
},
1032+
})
1033+
}),
1034+
node: node,
1035+
podsOnNode: []*v1.Pod{},
1036+
err: errors.New("insufficient cpu"),
1037+
},
1038+
{
1039+
description: "Pod with native sidecars with too much memory does not fit on node",
1040+
pod: test.BuildTestPod("p1", 1, 100, "", func(pod *v1.Pod) {
1041+
pod.Spec.InitContainers = append(pod.Spec.InitContainers, v1.Container{
1042+
RestartPolicy: ptr.To(v1.ContainerRestartPolicyAlways), // native sidecar
1043+
Resources: v1.ResourceRequirements{
1044+
Requests: createResourceList(100, 1000*1000*1000*1000, 0),
1045+
},
1046+
})
1047+
}),
1048+
node: node,
1049+
podsOnNode: []*v1.Pod{},
1050+
err: errors.New("insufficient memory"),
1051+
},
1052+
{
1053+
description: "Pod with small native sidecars fits on node",
1054+
pod: test.BuildTestPod("p1", 1, 100, "", func(pod *v1.Pod) {
1055+
pod.Spec.InitContainers = append(pod.Spec.InitContainers, v1.Container{
1056+
RestartPolicy: ptr.To(v1.ContainerRestartPolicyAlways), // native sidecar
1057+
Resources: v1.ResourceRequirements{
1058+
Requests: createResourceList(100, 100*1000*1000, 0),
1059+
},
1060+
})
1061+
}),
1062+
node: node,
1063+
podsOnNode: []*v1.Pod{},
1064+
},
1065+
{
1066+
description: "Pod with large overhead does not fit on node",
1067+
pod: test.BuildTestPod("p1", 1, 100, "", func(pod *v1.Pod) {
1068+
pod.Spec.Overhead = createResourceList(100000, 100*1000*1000, 0)
1069+
}),
1070+
node: node,
1071+
podsOnNode: []*v1.Pod{},
1072+
err: errors.New("insufficient cpu"),
1073+
},
1074+
{
1075+
description: "Pod with small overhead fits on node",
1076+
pod: test.BuildTestPod("p1", 1, 100, "", func(pod *v1.Pod) {
1077+
pod.Spec.Overhead = createResourceList(1, 1*1000*1000, 0)
1078+
}),
1079+
node: node,
1080+
podsOnNode: []*v1.Pod{},
1081+
},
10231082
}
10241083

10251084
for _, tc := range tests {

pkg/utils/pod.go

Lines changed: 6 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,10 @@ import (
1111
v1 "k8s.io/api/core/v1"
1212
"k8s.io/apimachinery/pkg/api/resource"
1313
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+
resourcehelper "k8s.io/component-helpers/resource"
1415
"k8s.io/klog/v2"
1516
)
1617

17-
// GetResourceRequest finds and returns the request value for a specific resource.
18-
func GetResourceRequest(pod *v1.Pod, resource v1.ResourceName) int64 {
19-
if resource == v1.ResourcePods {
20-
return 1
21-
}
22-
23-
requestQuantity := GetResourceRequestQuantity(pod, resource)
24-
25-
if resource == v1.ResourceCPU {
26-
return requestQuantity.MilliValue()
27-
}
28-
29-
return requestQuantity.Value()
30-
}
31-
3218
// GetResourceRequestQuantity finds and returns the request quantity for a specific resource.
3319
func GetResourceRequestQuantity(pod *v1.Pod, resourceName v1.ResourceName) resource.Quantity {
3420
requestQuantity := resource.Quantity{}
@@ -42,26 +28,8 @@ func GetResourceRequestQuantity(pod *v1.Pod, resourceName v1.ResourceName) resou
4228
requestQuantity = resource.Quantity{Format: resource.DecimalSI}
4329
}
4430

45-
for _, container := range pod.Spec.Containers {
46-
if rQuantity, ok := container.Resources.Requests[resourceName]; ok {
47-
requestQuantity.Add(rQuantity)
48-
}
49-
}
50-
51-
for _, container := range pod.Spec.InitContainers {
52-
if rQuantity, ok := container.Resources.Requests[resourceName]; ok {
53-
if requestQuantity.Cmp(rQuantity) < 0 {
54-
requestQuantity = rQuantity.DeepCopy()
55-
}
56-
}
57-
}
58-
59-
// We assume pod overhead feature gate is enabled.
60-
// We can't import the scheduler settings so we will inherit the default.
61-
if pod.Spec.Overhead != nil {
62-
if podOverhead, ok := pod.Spec.Overhead[resourceName]; ok && !requestQuantity.IsZero() {
63-
requestQuantity.Add(podOverhead)
64-
}
31+
if rQuantity, ok := resourcehelper.PodRequests(pod, resourcehelper.PodResourcesOptions{})[resourceName]; ok {
32+
requestQuantity.Add(rQuantity)
6533
}
6634

6735
return requestQuantity
@@ -171,59 +139,9 @@ func GetPodSource(pod *v1.Pod) (string, error) {
171139
// containers of the pod. If PodOverhead feature is enabled, pod overhead is added to the
172140
// total container resource requests and to the total container limits which have a
173141
// non-zero quantity.
174-
func PodRequestsAndLimits(pod *v1.Pod) (reqs, limits v1.ResourceList) {
175-
reqs, limits = v1.ResourceList{}, v1.ResourceList{}
176-
for _, container := range pod.Spec.Containers {
177-
addResourceList(reqs, container.Resources.Requests)
178-
addResourceList(limits, container.Resources.Limits)
179-
}
180-
// init containers define the minimum of any resource
181-
for _, container := range pod.Spec.InitContainers {
182-
maxResourceList(reqs, container.Resources.Requests)
183-
maxResourceList(limits, container.Resources.Limits)
184-
}
185-
186-
// We assume pod overhead feature gate is enabled.
187-
// We can't import the scheduler settings so we will inherit the default.
188-
if pod.Spec.Overhead != nil {
189-
addResourceList(reqs, pod.Spec.Overhead)
190-
191-
for name, quantity := range pod.Spec.Overhead {
192-
if value, ok := limits[name]; ok && !value.IsZero() {
193-
value.Add(quantity)
194-
limits[name] = value
195-
}
196-
}
197-
}
198-
199-
return
200-
}
201-
202-
// addResourceList adds the resources in newList to list
203-
func addResourceList(list, newList v1.ResourceList) {
204-
for name, quantity := range newList {
205-
if value, ok := list[name]; !ok {
206-
list[name] = quantity.DeepCopy()
207-
} else {
208-
value.Add(quantity)
209-
list[name] = value
210-
}
211-
}
212-
}
213-
214-
// maxResourceList sets list to the greater of list/newList for every resource
215-
// either list
216-
func maxResourceList(list, new v1.ResourceList) {
217-
for name, quantity := range new {
218-
if value, ok := list[name]; !ok {
219-
list[name] = quantity.DeepCopy()
220-
continue
221-
} else {
222-
if quantity.Cmp(value) > 0 {
223-
list[name] = quantity.DeepCopy()
224-
}
225-
}
226-
}
142+
func PodRequestsAndLimits(pod *v1.Pod) (v1.ResourceList, v1.ResourceList) {
143+
opts := resourcehelper.PodResourcesOptions{}
144+
return resourcehelper.PodRequests(pod, opts), resourcehelper.PodLimits(pod, opts)
227145
}
228146

229147
// PodToleratesTaints returns true if a pod tolerates one node's taints

vendor/k8s.io/component-helpers/resource/OWNERS

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)