From 2bfc98b313c2e9a4dd5312423c71a31a9ee9e7ad Mon Sep 17 00:00:00 2001 From: Ayato Tokubi Date: Mon, 7 Jul 2025 14:58:13 +0000 Subject: [PATCH] Update pod resize test to accept new cpu.weight conversion. Signed-off-by: Ayato Tokubi --- .../common/node/framework/cgroups/cgroups.go | 21 +----- .../node/framework/cgroups/cgroups_linux.go | 70 +++++++++++++++++++ .../framework/cgroups/cgroups_unsupported.go | 26 +++++++ 3 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 test/e2e/common/node/framework/cgroups/cgroups_linux.go create mode 100644 test/e2e/common/node/framework/cgroups/cgroups_unsupported.go diff --git a/test/e2e/common/node/framework/cgroups/cgroups.go b/test/e2e/common/node/framework/cgroups/cgroups.go index fc71e946c68..ce9f758341d 100644 --- a/test/e2e/common/node/framework/cgroups/cgroups.go +++ b/test/e2e/common/node/framework/cgroups/cgroups.go @@ -207,23 +207,6 @@ func getExpectedCPULimitFromCPUQuota(cpuQuota int64, podOnCgroupV2 bool) string return expectedCPULimitString } -func getExpectedCPUShares(rr *v1.ResourceRequirements, podOnCgroupv2 bool) int64 { - cpuRequest := rr.Requests.Cpu() - cpuLimit := rr.Limits.Cpu() - var shares int64 - if cpuRequest.IsZero() && !cpuLimit.IsZero() { - shares = int64(kubecm.MilliCPUToShares(cpuLimit.MilliValue())) - } else { - shares = int64(kubecm.MilliCPUToShares(cpuRequest.MilliValue())) - } - if podOnCgroupv2 { - // TODO: This fomula should be a shared function. - return 1 + ((shares-2)*9999)/262142 - } else { - return shares - } -} - func getExpectedMemLimitString(rr *v1.ResourceRequirements, podOnCgroupv2 bool) string { expectedMemLimitInBytes := rr.Limits.Memory().Value() expectedMemLimitString := strconv.FormatInt(expectedMemLimitInBytes, 10) @@ -236,7 +219,7 @@ func getExpectedMemLimitString(rr *v1.ResourceRequirements, podOnCgroupv2 bool) func verifyContainerCPUWeight(f *framework.Framework, pod *v1.Pod, containerName string, expectedResources *v1.ResourceRequirements, podOnCgroupv2 bool) error { cpuWeightCgPath := getCgroupCPURequestPath(cgroupFsPath, podOnCgroupv2) expectedCPUShares := getExpectedCPUShares(expectedResources, podOnCgroupv2) - if err := VerifyCgroupValue(f, pod, containerName, cpuWeightCgPath, strconv.FormatInt(expectedCPUShares, 10)); err != nil { + if err := VerifyCgroupValue(f, pod, containerName, cpuWeightCgPath, expectedCPUShares...); err != nil { return fmt.Errorf("failed to verify cpu request cgroup value: %w", err) } return nil @@ -286,7 +269,7 @@ func verifyPodCPUWeight(f *framework.Framework, pod *v1.Pod, expectedResources * cpuWeightCgPath = fmt.Sprintf("%s/%s", podCgPath, cgroupCPUSharesFile) } expectedCPUShares := getExpectedCPUShares(expectedResources, podOnCgroupv2) - if err := VerifyCgroupValue(f, pod, pod.Spec.Containers[0].Name, cpuWeightCgPath, strconv.FormatInt(expectedCPUShares, 10)); err != nil { + if err := VerifyCgroupValue(f, pod, pod.Spec.Containers[0].Name, cpuWeightCgPath, expectedCPUShares...); err != nil { return fmt.Errorf("pod cgroup cpu weight verification failed: %w", err) } return nil diff --git a/test/e2e/common/node/framework/cgroups/cgroups_linux.go b/test/e2e/common/node/framework/cgroups/cgroups_linux.go new file mode 100644 index 00000000000..c7f3064b508 --- /dev/null +++ b/test/e2e/common/node/framework/cgroups/cgroups_linux.go @@ -0,0 +1,70 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cgroups + +import ( + "math" + "strconv" + + v1 "k8s.io/api/core/v1" + kubecm "k8s.io/kubernetes/pkg/kubelet/cm" +) + +// convertCPUSharesToCgroupV2Value is copied from ConvertCPUSharesToCgroupV2Value in opencontainers/cgroups. +// https://github.com/opencontainers/cgroups/pull/20/files +func convertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 { + // The value of 0 means "unset". + if cpuShares == 0 { + return 0 + } + if cpuShares <= 2 { + return 1 + } + if cpuShares >= 262144 { + return 10000 + } + l := math.Log2(float64(cpuShares)) + // Quadratic function which fits min, max, and default. + exponent := (l*l+125*l)/612.0 - 7.0/34.0 + + return uint64(math.Ceil(math.Pow(10, exponent))) +} + +func getExpectedCPUShares(rr *v1.ResourceRequirements, podOnCgroupv2 bool) []string { + // This function is moved out from cgroups.go because opencontainers/cgroups can only be compiled in linux platforms. + cpuRequest := rr.Requests.Cpu() + cpuLimit := rr.Limits.Cpu() + var shares int64 + if cpuRequest.IsZero() && !cpuLimit.IsZero() { + shares = int64(kubecm.MilliCPUToShares(cpuLimit.MilliValue())) + } else { + shares = int64(kubecm.MilliCPUToShares(cpuRequest.MilliValue())) + } + if podOnCgroupv2 { + // Because of https://github.com/kubernetes/kubernetes/issues/131216, the way of conversion has been changed. + // runc: https://github.com/opencontainers/runc/pull/4785 + // crun: https://github.com/containers/crun/issues/1721 + // This is dependent on the container runtime version. In order not to break the tests when we upgrade the + // container runtimes, we check if either the old or the new conversion matches the actual value for now. + // TODO: Remove the old conversion once container runtimes are updated. + oldConverted := 1 + ((shares-2)*9999)/262142 + converted := convertCPUSharesToCgroupV2Value(uint64(shares)) + return []string{strconv.FormatInt(oldConverted, 10), strconv.FormatInt(int64(converted), 10)} + } else { + return []string{strconv.FormatInt(shares, 10)} + } +} diff --git a/test/e2e/common/node/framework/cgroups/cgroups_unsupported.go b/test/e2e/common/node/framework/cgroups/cgroups_unsupported.go new file mode 100644 index 00000000000..8f5c823c8f1 --- /dev/null +++ b/test/e2e/common/node/framework/cgroups/cgroups_unsupported.go @@ -0,0 +1,26 @@ +//go:build !linux + +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cgroups + +import v1 "k8s.io/api/core/v1" + +func getExpectedCPUShares(rr *v1.ResourceRequirements, podOnCgroupv2 bool) []string { + // cgroup is only supported in linux. + return []string{} +}