Merge pull request #132791 from bitoku/cpu-weight

Update pod resize test to accept new cpu.weight conversion.
This commit is contained in:
Kubernetes Prow Robot 2025-09-11 16:20:08 -07:00 committed by GitHub
commit 1d80f35350
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 104 additions and 30 deletions

2
go.mod
View file

@ -46,7 +46,7 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
github.com/onsi/ginkgo/v2 v2.21.0
github.com/onsi/gomega v1.35.1
github.com/opencontainers/cgroups v0.0.2
github.com/opencontainers/cgroups v0.0.3
github.com/opencontainers/selinux v1.11.1
github.com/pmezard/go-difflib v1.0.0
github.com/prometheus/client_golang v1.23.2

4
go.sum
View file

@ -255,8 +255,8 @@ github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/opencontainers/cgroups v0.0.2 h1:A+mAPPMfgKNCEZUUtibESFx06uvhAmvo8sSz3Abwk7o=
github.com/opencontainers/cgroups v0.0.2/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs=
github.com/opencontainers/cgroups v0.0.3 h1:Jc9dWh/0YLGjdy6J/9Ln8NM5BfTA4W2BY0GMozy3aDU=
github.com/opencontainers/cgroups v0.0.3/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=

View file

@ -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

View file

@ -0,0 +1,50 @@
/*
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 (
"strconv"
libcontainercgroups "github.com/opencontainers/cgroups"
v1 "k8s.io/api/core/v1"
kubecm "k8s.io/kubernetes/pkg/kubelet/cm"
)
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 := libcontainercgroups.ConvertCPUSharesToCgroupV2Value(uint64(shares))
return []string{strconv.FormatInt(oldConverted, 10), strconv.FormatInt(int64(converted), 10)}
} else {
return []string{strconv.FormatInt(shares, 10)}
}
}

View file

@ -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{}
}

View file

@ -29,7 +29,7 @@ type Cgroup struct {
ScopePrefix string `json:"scope_prefix,omitempty"`
// Resources contains various cgroups settings to apply.
*Resources `json:"Resources,omitempty"`
*Resources
// Systemd tells if systemd should be used to manage cgroups.
Systemd bool `json:"Systemd,omitempty"`

View file

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"math"
"os"
"path/filepath"
"strconv"
@ -413,16 +414,30 @@ func WriteCgroupProc(dir string, pid int) error {
return err
}
// Since the OCI spec is designed for cgroup v1, in some cases
// there is need to convert from the cgroup v1 configuration to cgroup v2
// the formula for cpuShares is y = (1 + ((x - 2) * 9999) / 262142)
// convert from [2-262144] to [1-10000]
// 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)"
// ConvertCPUSharesToCgroupV2Value converts CPU shares, used by cgroup v1,
// to CPU weight, used by cgroup v2.
//
// Cgroup v1 CPU shares has a range of [2^1...2^18], i.e. [2...262144],
// and the default value is 1024.
//
// Cgroup v2 CPU weight has a range of [10^0...10^4], i.e. [1...10000],
// and the default value is 100.
func ConvertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 {
// The value of 0 means "unset".
if cpuShares == 0 {
return 0
}
return (1 + ((cpuShares-2)*9999)/262142)
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)))
}
// ConvertMemorySwapToCgroupV2Value converts MemorySwap value from OCI spec

2
vendor/modules.txt vendored
View file

@ -456,7 +456,7 @@ github.com/onsi/gomega/matchers/support/goraph/edge
github.com/onsi/gomega/matchers/support/goraph/node
github.com/onsi/gomega/matchers/support/goraph/util
github.com/onsi/gomega/types
# github.com/opencontainers/cgroups v0.0.2
# github.com/opencontainers/cgroups v0.0.3
## explicit; go 1.23.0
github.com/opencontainers/cgroups
github.com/opencontainers/cgroups/devices/config