diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager.go b/pkg/kubelet/cm/cpumanager/cpu_manager.go index 5a6e5082f15..2e5b541ef01 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager.go @@ -101,6 +101,9 @@ type manager struct { // representation of state for the system to inspect and reconcile. state state.State + // lastUpdatedstate holds state for each container from the last time it was updated. + lastUpdateState state.State + // containerRuntime is the container runtime service interface needed // to make UpdateContainerResources() calls against the containers. containerRuntime runtimeService @@ -187,6 +190,7 @@ func NewManager(cpuPolicyName string, reconcilePeriod time.Duration, machineInfo manager := &manager{ policy: policy, reconcilePeriod: reconcilePeriod, + lastUpdateState: state.NewMemoryState(), topology: topo, nodeAllocatableReservation: nodeAllocatableReservation, stateFileDirectory: stateFileDirectory, @@ -248,6 +252,9 @@ func (m *manager) Allocate(p *v1.Pod, c *v1.Container) error { func (m *manager) AddContainer(pod *v1.Pod, container *v1.Container, containerID string) { m.Lock() defer m.Unlock() + if cset, exists := m.state.GetCPUSet(string(pod.UID), container.Name); exists { + m.lastUpdateState.SetCPUSet(string(pod.UID), container.Name, cset) + } m.containerMap.Add(string(pod.UID), container.Name, containerID) } @@ -272,6 +279,7 @@ func (m *manager) policyRemoveContainerByID(containerID string) error { err = m.policy.RemoveContainer(m.state, podUID, containerName) if err == nil { + m.lastUpdateState.Delete(podUID, containerName) m.containerMap.RemoveByContainerID(containerID) } @@ -281,6 +289,7 @@ func (m *manager) policyRemoveContainerByID(containerID string) error { func (m *manager) policyRemoveContainerByRef(podUID string, containerName string) error { err := m.policy.RemoveContainer(m.state, podUID, containerName) if err == nil { + m.lastUpdateState.Delete(podUID, containerName) m.containerMap.RemoveByContainerRef(podUID, containerName) } @@ -424,12 +433,16 @@ func (m *manager) reconcileState() (success []reconciledContainer, failure []rec continue } - klog.V(4).InfoS("ReconcileState: updating container", "pod", klog.KObj(pod), "containerName", container.Name, "containerID", containerID, "cpuSet", cset) - err = m.updateContainerCPUSet(containerID, cset) - if err != nil { - klog.ErrorS(err, "ReconcileState: failed to update container", "pod", klog.KObj(pod), "containerName", container.Name, "containerID", containerID, "cpuSet", cset) - failure = append(failure, reconciledContainer{pod.Name, container.Name, containerID}) - continue + lcset := m.lastUpdateState.GetCPUSetOrDefault(string(pod.UID), container.Name) + if !cset.Equals(lcset) { + klog.V(4).InfoS("ReconcileState: updating container", "pod", klog.KObj(pod), "containerName", container.Name, "containerID", containerID, "cpuSet", cset) + err = m.updateContainerCPUSet(containerID, cset) + if err != nil { + klog.ErrorS(err, "ReconcileState: failed to update container", "pod", klog.KObj(pod), "containerName", container.Name, "containerID", containerID, "cpuSet", cset) + failure = append(failure, reconciledContainer{pod.Name, container.Name, containerID}) + continue + } + m.lastUpdateState.SetCPUSet(string(pod.UID), container.Name, cset) } success = append(success, reconciledContainer{pod.Name, container.Name, containerID}) } diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager_test.go b/pkg/kubelet/cm/cpumanager/cpu_manager_test.go index 51c6ad99251..58ff1e56e44 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager_test.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager_test.go @@ -265,6 +265,7 @@ func TestCPUManagerAdd(t *testing.T) { assignments: state.ContainerCPUAssignments{}, defaultCPUSet: cpuset.NewCPUSet(1, 2, 3, 4), }, + lastUpdateState: state.NewMemoryState(), containerRuntime: mockRuntimeService{ err: testCase.updateErr, }, @@ -488,6 +489,7 @@ func TestCPUManagerAddWithInitContainers(t *testing.T) { mgr := &manager{ policy: policy, state: mockState, + lastUpdateState: state.NewMemoryState(), containerRuntime: mockRuntimeService{}, containerMap: containermap.NewContainerMap(), podStatusProvider: mockPodStatusProvider{}, @@ -670,6 +672,7 @@ func TestCPUManagerRemove(t *testing.T) { assignments: state.ContainerCPUAssignments{}, defaultCPUSet: cpuset.NewCPUSet(), }, + lastUpdateState: state.NewMemoryState(), containerRuntime: mockRuntimeService{}, containerMap: containerMap, activePods: func() []*v1.Pod { return nil }, @@ -936,6 +939,7 @@ func TestReconcileState(t *testing.T) { assignments: testCase.stAssignments, defaultCPUSet: testCase.stDefaultCPUSet, }, + lastUpdateState: state.NewMemoryState(), containerRuntime: mockRuntimeService{ err: testCase.updateErr, }, @@ -1026,6 +1030,7 @@ func TestCPUManagerAddWithResvList(t *testing.T) { assignments: state.ContainerCPUAssignments{}, defaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3), }, + lastUpdateState: state.NewMemoryState(), containerRuntime: mockRuntimeService{ err: testCase.updateErr, },