diff --git a/pkg/kubelet/cm/memorymanager/policy_static.go b/pkg/kubelet/cm/memorymanager/policy_static.go index ca267515cb2..0959d789215 100644 --- a/pkg/kubelet/cm/memorymanager/policy_static.go +++ b/pkg/kubelet/cm/memorymanager/policy_static.go @@ -18,7 +18,6 @@ package memorymanager import ( "fmt" - "reflect" "sort" cadvisorapi "github.com/google/cadvisor/info/v1" @@ -689,8 +688,25 @@ func areMachineStatesEqual(ms1, ms2 state.NUMANodeMap) bool { return false } - if !reflect.DeepEqual(*memoryState1, *memoryState2) { - klog.ErrorS(nil, "Memory states for the NUMA node and resource are different", "node", nodeID, "resource", resourceName, "memoryState1", *memoryState1, "memoryState2", *memoryState2) + if !areMemoryStatesEqual(memoryState1, memoryState2, nodeID, resourceName) { + return false + } + + tmpState1 := state.MemoryTable{} + tmpState2 := state.MemoryTable{} + for _, nodeID := range nodeState1.Cells { + tmpState1.Free += ms1[nodeID].MemoryMap[resourceName].Free + tmpState1.Reserved += ms1[nodeID].MemoryMap[resourceName].Reserved + tmpState2.Free += ms2[nodeID].MemoryMap[resourceName].Free + tmpState2.Reserved += ms2[nodeID].MemoryMap[resourceName].Reserved + } + + if tmpState1.Free != tmpState2.Free { + klog.InfoS("Memory states for the NUMA node and resource are different", "node", nodeID, "resource", resourceName, "field", "free", "free1", tmpState1.Free, "free2", tmpState2.Free, "memoryState1", *memoryState1, "memoryState2", *memoryState2) + return false + } + if tmpState1.Reserved != tmpState2.Reserved { + klog.InfoS("Memory states for the NUMA node and resource are different", "node", nodeID, "resource", resourceName, "field", "reserved", "reserved1", tmpState1.Reserved, "reserved2", tmpState2.Reserved, "memoryState1", *memoryState1, "memoryState2", *memoryState2) return false } } @@ -698,6 +714,24 @@ func areMachineStatesEqual(ms1, ms2 state.NUMANodeMap) bool { return true } +func areMemoryStatesEqual(memoryState1, memoryState2 *state.MemoryTable, nodeID int, resourceName v1.ResourceName) bool { + if memoryState1.TotalMemSize != memoryState2.TotalMemSize { + klog.ErrorS(nil, "Memory states for the NUMA node and resource are different", "node", nodeID, "resource", resourceName, "field", "TotalMemSize", "TotalMemSize1", memoryState1.TotalMemSize, "TotalMemSize2", memoryState2.TotalMemSize, "memoryState1", *memoryState1, "memoryState2", *memoryState2) + return false + } + + if memoryState1.SystemReserved != memoryState2.SystemReserved { + klog.ErrorS(nil, "Memory states for the NUMA node and resource are different", "node", nodeID, "resource", resourceName, "field", "SystemReserved", "SystemReserved1", memoryState1.SystemReserved, "SystemReserved2", memoryState2.SystemReserved, "memoryState1", *memoryState1, "memoryState2", *memoryState2) + return false + } + + if memoryState1.Allocatable != memoryState2.Allocatable { + klog.ErrorS(nil, "Memory states for the NUMA node and resource are different", "node", nodeID, "resource", resourceName, "field", "Allocatable", "Allocatable1", memoryState1.Allocatable, "Allocatable2", memoryState2.Allocatable, "memoryState1", *memoryState1, "memoryState2", *memoryState2) + return false + } + return true +} + func (p *staticPolicy) getDefaultMachineState() state.NUMANodeMap { defaultMachineState := state.NUMANodeMap{} nodeHugepages := map[int]uint64{} diff --git a/pkg/kubelet/cm/memorymanager/policy_static_test.go b/pkg/kubelet/cm/memorymanager/policy_static_test.go index b2e030c8d9a..064ef988066 100644 --- a/pkg/kubelet/cm/memorymanager/policy_static_test.go +++ b/pkg/kubelet/cm/memorymanager/policy_static_test.go @@ -1024,6 +1024,125 @@ func TestStaticPolicyStart(t *testing.T) { }, }, }, + { + description: "should validate the totalFree and totalReserved size for a resource within a group", + expectedAssignments: state.ContainerMemoryAssignments{ + "pod1": map[string][]state.Block{ + "container1": { + { + NUMAAffinity: []int{0, 1}, + Type: v1.ResourceMemory, + Size: 240 * mb, + }, + }, + }, + "pod2": map[string][]state.Block{ + "container2": { + { + NUMAAffinity: []int{0, 1}, + Type: v1.ResourceMemory, + Size: 10 * mb, + }, + }, + }, + }, + assignments: state.ContainerMemoryAssignments{ + "pod1": map[string][]state.Block{ + "container1": { + { + NUMAAffinity: []int{0, 1}, + Type: v1.ResourceMemory, + Size: 240 * mb, + }, + }, + }, + "pod2": map[string][]state.Block{ + "container2": { + { + NUMAAffinity: []int{0, 1}, + Type: v1.ResourceMemory, + Size: 10 * mb, + }, + }, + }, + }, + expectedMachineState: state.NUMANodeMap{ + 0: &state.NUMANodeState{ + MemoryMap: map[v1.ResourceName]*state.MemoryTable{ + v1.ResourceMemory: { + Allocatable: 220 * mb, + Free: 30 * mb, + Reserved: 190 * mb, + SystemReserved: 20 * mb, + TotalMemSize: 240 * mb, + }, + }, + Cells: []int{0, 1}, + NumberOfAssignments: 2, + }, + 1: &state.NUMANodeState{ + MemoryMap: map[v1.ResourceName]*state.MemoryTable{ + v1.ResourceMemory: { + Allocatable: 220 * mb, + Free: 160 * mb, + Reserved: 60 * mb, + SystemReserved: 20 * mb, + TotalMemSize: 240 * mb, + }, + }, + Cells: []int{0, 1}, + NumberOfAssignments: 2, + }, + }, + machineState: state.NUMANodeMap{ + 0: &state.NUMANodeState{ + MemoryMap: map[v1.ResourceName]*state.MemoryTable{ + v1.ResourceMemory: { + Allocatable: 220 * mb, + Free: 10 * mb, + Reserved: 210 * mb, + SystemReserved: 20 * mb, + TotalMemSize: 240 * mb, + }, + }, + Cells: []int{0, 1}, + NumberOfAssignments: 2, + }, + 1: &state.NUMANodeState{ + MemoryMap: map[v1.ResourceName]*state.MemoryTable{ + v1.ResourceMemory: { + Allocatable: 220 * mb, + Free: 180 * mb, + Reserved: 40 * mb, + SystemReserved: 20 * mb, + TotalMemSize: 240 * mb, + }, + }, + Cells: []int{0, 1}, + NumberOfAssignments: 2, + }, + }, + systemReserved: systemReservedMemory{ + 0: map[v1.ResourceName]uint64{ + v1.ResourceMemory: 20 * mb, + }, + 1: map[v1.ResourceName]uint64{ + v1.ResourceMemory: 20 * mb, + }, + }, + machineInfo: &cadvisorapi.MachineInfo{ + Topology: []cadvisorapi.Node{ + { + Id: 0, + Memory: 240 * mb, + }, + { + Id: 1, + Memory: 240 * mb, + }, + }, + }, + }, } for _, testCase := range testCases {