Merge pull request #104837 from eggiter/fix-release-reused-cpus

fix(cpumanager): Do not release CPUs of init containers while they are being reused in app containers
This commit is contained in:
Kubernetes Prow Robot 2022-01-06 11:46:38 -08:00 committed by GitHub
commit 03ee86c09c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 0 deletions

View File

@ -292,11 +292,26 @@ func (p *staticPolicy) Allocate(s state.State, pod *v1.Pod, container *v1.Contai
return nil
}
// getAssignedCPUsOfSiblings returns assigned cpus of given container's siblings(all containers other than the given container) in the given pod `podUID`.
func getAssignedCPUsOfSiblings(s state.State, podUID string, containerName string) cpuset.CPUSet {
assignments := s.GetCPUAssignments()
cset := cpuset.NewCPUSet()
for name, cpus := range assignments[podUID] {
if containerName == name {
continue
}
cset = cset.Union(cpus)
}
return cset
}
func (p *staticPolicy) RemoveContainer(s state.State, podUID string, containerName string) error {
klog.InfoS("Static policy: RemoveContainer", "podUID", podUID, "containerName", containerName)
cpusInUse := getAssignedCPUsOfSiblings(s, podUID, containerName)
if toRelease, ok := s.GetCPUSet(podUID, containerName); ok {
s.Delete(podUID, containerName)
// Mutate the shared pool, adding released cpus.
toRelease = toRelease.Difference(cpusInUse)
s.SetDefaultCPUSet(s.GetDefaultCPUSet().Union(toRelease))
}
return nil

View File

@ -558,6 +558,62 @@ func runStaticPolicyTestCase(t *testing.T, testCase staticPolicyTest) {
}
}
func TestStaticPolicyReuseCPUs(t *testing.T) {
testCases := []struct {
staticPolicyTest
expCSetAfterAlloc cpuset.CPUSet
expCSetAfterRemove cpuset.CPUSet
}{
{
staticPolicyTest: staticPolicyTest{
description: "SingleSocketHT, DeAllocOneInitContainer",
topo: topoSingleSocketHT,
pod: makeMultiContainerPod(
[]struct{ request, limit string }{
{"4000m", "4000m"}}, // 0, 1, 4, 5
[]struct{ request, limit string }{
{"2000m", "2000m"}}), // 0, 4
containerName: "initContainer-0",
stAssignments: state.ContainerCPUAssignments{},
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
},
expCSetAfterAlloc: cpuset.NewCPUSet(2, 3, 6, 7),
expCSetAfterRemove: cpuset.NewCPUSet(1, 2, 3, 5, 6, 7),
},
}
for _, testCase := range testCases {
policy, _ := NewStaticPolicy(testCase.topo, testCase.numReservedCPUs, cpuset.NewCPUSet(), topologymanager.NewFakeManager(), nil)
st := &mockState{
assignments: testCase.stAssignments,
defaultCPUSet: testCase.stDefaultCPUSet,
}
pod := testCase.pod
// allocate
for _, container := range append(pod.Spec.InitContainers, pod.Spec.Containers...) {
policy.Allocate(st, pod, &container)
}
if !reflect.DeepEqual(st.defaultCPUSet, testCase.expCSetAfterAlloc) {
t.Errorf("StaticPolicy Allocate() error (%v). expected default cpuset %v but got %v",
testCase.description, testCase.expCSetAfterAlloc, st.defaultCPUSet)
}
// remove
policy.RemoveContainer(st, string(pod.UID), testCase.containerName)
if !reflect.DeepEqual(st.defaultCPUSet, testCase.expCSetAfterRemove) {
t.Errorf("StaticPolicy RemoveContainer() error (%v). expected default cpuset %v but got %v",
testCase.description, testCase.expCSetAfterRemove, st.defaultCPUSet)
}
if _, found := st.assignments[string(pod.UID)][testCase.containerName]; found {
t.Errorf("StaticPolicy RemoveContainer() error (%v). expected (pod %v, container %v) not be in assignments %v",
testCase.description, testCase.podUID, testCase.containerName, st.assignments)
}
}
}
func TestStaticPolicyRemove(t *testing.T) {
testCases := []staticPolicyTest{
{