Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cpumanager): Do not release CPUs of init containers while they are being reused in app containers #104837

Merged
merged 1 commit into from
Jan 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions pkg/kubelet/cm/cpumanager/policy_static.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,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
Expand Down
56 changes: 56 additions & 0 deletions pkg/kubelet/cm/cpumanager/policy_static_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
{
Expand Down