From f07a3a3f26375c00b88c7ff8e824072e73944b54 Mon Sep 17 00:00:00 2001 From: qingwave Date: Thu, 17 Aug 2023 07:45:25 +0000 Subject: [PATCH] calculate sidecar container resource in pod autoscaler Signed-off-by: qingwave --- .../podautoscaler/replica_calculator.go | 8 +- .../podautoscaler/replica_calculator_test.go | 109 ++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/pkg/controller/podautoscaler/replica_calculator.go b/pkg/controller/podautoscaler/replica_calculator.go index db2bd16c3d8..4f77fbb53ea 100644 --- a/pkg/controller/podautoscaler/replica_calculator.go +++ b/pkg/controller/podautoscaler/replica_calculator.go @@ -425,7 +425,13 @@ func calculatePodRequests(pods []*v1.Pod, container string, resource v1.Resource requests := make(map[string]int64, len(pods)) for _, pod := range pods { podSum := int64(0) - for _, c := range pod.Spec.Containers { + containers := append([]v1.Container{}, pod.Spec.Containers...) + for _, c := range pod.Spec.InitContainers { + if c.RestartPolicy != nil && *c.RestartPolicy == v1.ContainerRestartPolicyAlways { + containers = append(containers, c) + } + } + for _, c := range containers { if container == "" || container == c.Name { if containerRequest, ok := c.Resources.Requests[resource]; ok { podSum += containerRequest.MilliValue() diff --git a/pkg/controller/podautoscaler/replica_calculator_test.go b/pkg/controller/podautoscaler/replica_calculator_test.go index e82efe64307..0a40d172691 100644 --- a/pkg/controller/podautoscaler/replica_calculator_test.go +++ b/pkg/controller/podautoscaler/replica_calculator_test.go @@ -1999,3 +1999,112 @@ func TestGroupPods(t *testing.T) { }) } } + +func TestCalculatePodRequests(t *testing.T) { + containerRestartPolicyAlways := v1.ContainerRestartPolicyAlways + testPod := "test-pod" + + tests := []struct { + name string + pods []*v1.Pod + container string + resource v1.ResourceName + expectedRequests map[string]int64 + expectedError error + }{ + { + name: "void", + pods: []*v1.Pod{}, + container: "", + resource: v1.ResourceCPU, + expectedRequests: map[string]int64{}, + expectedError: nil, + }, + { + name: "one pod", + pods: []*v1.Pod{{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPod, + Namespace: testNamespace, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + {Name: "container1", Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI)}}}, + {Name: "container2", Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceCPU: *resource.NewMilliQuantity(50, resource.DecimalSI)}}}, + }, + }, + }}, + container: "", + resource: v1.ResourceCPU, + expectedRequests: map[string]int64{testPod: 150}, + expectedError: nil, + }, + { + name: "calculate requests with special container", + pods: []*v1.Pod{{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPod, + Namespace: testNamespace, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + {Name: "container1", Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI)}}}, + {Name: "container2", Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceCPU: *resource.NewMilliQuantity(50, resource.DecimalSI)}}}, + }, + }, + }}, + container: "container1", + resource: v1.ResourceCPU, + expectedRequests: map[string]int64{testPod: 100}, + expectedError: nil, + }, + { + name: "pod missing requests", + pods: []*v1.Pod{{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPod, + Namespace: testNamespace, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + {Name: "container1"}, + }, + }, + }}, + container: "", + resource: v1.ResourceCPU, + expectedRequests: nil, + expectedError: fmt.Errorf("missing request for %s in container %s of Pod %s", v1.ResourceCPU, "container1", testPod), + }, + { + name: "pod with sidecar containers", + pods: []*v1.Pod{{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPod, + Namespace: testNamespace, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + {Name: "container1", Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI)}}}, + }, + InitContainers: []v1.Container{ + {Name: "init-container1", Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceCPU: *resource.NewMilliQuantity(20, resource.DecimalSI)}}}, + {Name: "sidecar1", RestartPolicy: &containerRestartPolicyAlways, Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceCPU: *resource.NewMilliQuantity(50, resource.DecimalSI)}}}, + }, + }, + }}, + container: "", + resource: v1.ResourceCPU, + expectedRequests: map[string]int64{testPod: 150}, + expectedError: nil, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + requests, err := calculatePodRequests(tc.pods, tc.container, tc.resource) + assert.Equal(t, tc.expectedRequests, requests, "requests should be as expected") + assert.Equal(t, tc.expectedError, err, "error should be as expected") + }) + } +}