mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-07-01 14:38:33 +00:00
Merge pull request #13140 from fidencio/topic/fix-besteffort-sandbox-cpu-sizing
runtime: oci: Only derive sandbox CPUs from shares when quota is unconstrained
This commit is contained in:
@@ -1513,9 +1513,16 @@ func CalculateSandboxSizing(spec *specs.Spec) (numCPU float32, memSizeMB uint32)
|
||||
numCPU, memSizeMB = calculateVMResources(period, quota, memory)
|
||||
|
||||
// When cpuManagerPolicy=static is in use, kubelet sets quota=-1
|
||||
// (unconstrained) and assigns CPUs via cpuset instead. Fall back
|
||||
// to deriving the CPU count from shares (1024 shares per CPU).
|
||||
if numCPU == 0 && shares > 0 {
|
||||
// (unconstrained) and assigns CPUs via cpuset instead. In that case
|
||||
// we derive the CPU count from the CPU shares (1024 shares per CPU).
|
||||
//
|
||||
// We must gate this on quota being explicitly unconstrained (< 0)
|
||||
// rather than on numCPU == 0: a quota of 0 (or absent) means a
|
||||
// BestEffort sandbox with no CPU request, which has to contribute 0
|
||||
// vCPUs. Such a sandbox still carries the cgroup-floor shares value
|
||||
// (2), and deriving from it would inflate every sandbox by one vCPU
|
||||
// (e.g. peer-pods would boot default_vcpus+1).
|
||||
if quota < 0 && numCPU == 0 && shares > 0 {
|
||||
numCPU = float32(math.Ceil(float64(shares) / 1024.0))
|
||||
}
|
||||
|
||||
|
||||
@@ -1263,6 +1263,13 @@ func makeSizingAnnotations(memory, quota, period string) *specs.Spec {
|
||||
return &spec
|
||||
}
|
||||
|
||||
func makeSizingAnnotationsWithShares(memory, quota, period, shares string) *specs.Spec {
|
||||
spec := makeSizingAnnotations(memory, quota, period)
|
||||
spec.Annotations[ctrAnnotations.SandboxCPUShares] = shares
|
||||
|
||||
return spec
|
||||
}
|
||||
|
||||
func TestCalculateContainerSizing(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
@@ -1376,6 +1383,42 @@ func TestCalculateSandboxSizing(t *testing.T) {
|
||||
expectedCPU: 4,
|
||||
expectedMem: 4096,
|
||||
},
|
||||
// cpuManagerPolicy=static: kubelet leaves the quota
|
||||
// unconstrained (-1) and pins CPUs via cpuset, so the CPU
|
||||
// count must be derived from the shares (1024 shares per CPU).
|
||||
{
|
||||
spec: makeSizingAnnotationsWithShares("1048576", "-1", "100", "2048"),
|
||||
expectedCPU: 2,
|
||||
expectedMem: 1,
|
||||
},
|
||||
// Shares that don't divide evenly are rounded up.
|
||||
{
|
||||
spec: makeSizingAnnotationsWithShares("0", "-1", "100", "1536"),
|
||||
expectedCPU: 2,
|
||||
expectedMem: 0,
|
||||
},
|
||||
// BestEffort sandbox: no CPU request means quota is 0/absent,
|
||||
// but the cgroup still carries the floor shares value (2). This
|
||||
// must contribute 0 vCPUs, otherwise every sandbox (e.g. a
|
||||
// peer-pod) would be inflated by one vCPU.
|
||||
{
|
||||
spec: makeSizingAnnotationsWithShares("0", "0", "100", "2"),
|
||||
expectedCPU: 0,
|
||||
expectedMem: 0,
|
||||
},
|
||||
// An explicit quota always wins over shares: the shares-based
|
||||
// fallback only applies when the quota is unconstrained.
|
||||
{
|
||||
spec: makeSizingAnnotationsWithShares("0", "200", "100", "8192"),
|
||||
expectedCPU: 2,
|
||||
expectedMem: 0,
|
||||
},
|
||||
// Unconstrained quota but no shares set: nothing to derive from.
|
||||
{
|
||||
spec: makeSizingAnnotationsWithShares("0", "-1", "100", "0"),
|
||||
expectedCPU: 0,
|
||||
expectedMem: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
|
||||
Reference in New Issue
Block a user