diff --git a/pkg/kubelet/eviction/eviction_manager_test.go b/pkg/kubelet/eviction/eviction_manager_test.go index 81562c671d31..75fe9fb9263d 100644 --- a/pkg/kubelet/eviction/eviction_manager_test.go +++ b/pkg/kubelet/eviction/eviction_manager_test.go @@ -117,6 +117,32 @@ func makePodWithDiskStats(name string, priority int32, requests v1.ResourceList, return pod, podStats } +func makePodWithLocalStorageCapacityIsolationOpen(name string, priority int32, requests v1.ResourceList, limits v1.ResourceList, memoryWorkingSet string) (*v1.Pod, statsapi.PodStats) { + vol := newVolume("local-volume", v1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{ + SizeLimit: resource.NewQuantity(requests.Memory().Value(), resource.BinarySI), + }, + }) + var vols []v1.Volume + vols = append(vols, vol) + pod := newPod(name, priority, []v1.Container{ + newContainer(name, requests, limits), + }, vols) + + var podStats statsapi.PodStats + switch name { + case "empty-dir": + podStats = newPodMemoryStats(pod, *resource.NewQuantity(requests.Memory().Value()*2, resource.BinarySI)) + case "container-ephemeral-storage-limit": + podStats = newPodMemoryStats(pod, *resource.NewQuantity(limits.StorageEphemeral().Value(), resource.BinarySI)) + case "pod-ephemeral-storage-limit": + podStats = newPodMemoryStats(pod, *resource.NewQuantity(limits.StorageEphemeral().Value()*2, resource.BinarySI)) + default: + podStats = newPodMemoryStats(pod, resource.MustParse(memoryWorkingSet)) + } + return pod, podStats +} + func makeMemoryStats(nodeAvailableBytes string, podStats map[*v1.Pod]statsapi.PodStats) *statsapi.Summary { val := resource.MustParse(nodeAvailableBytes) availableBytes := uint64(val.Value()) @@ -1784,3 +1810,70 @@ func TestUpdateMemcgThreshold(t *testing.T) { fakeClock.Step(2 * notifierRefreshInterval) manager.synchronize(diskInfoProvider, activePodsFunc) } + +func TestManagerWithLocalStorageCapacityIsolationOpen(t *testing.T) { + podMaker := makePodWithLocalStorageCapacityIsolationOpen + summaryStatsMaker := makeDiskStats + podsToMake := []podToMake{ + {name: "empty-dir", requests: newResourceList("", "900Mi", ""), limits: newResourceList("", "1Gi", "")}, + {name: "container-ephemeral-storage-limit", requests: newResourceList("", "", "900Mi"), limits: newResourceList("", "", "800Mi")}, + {name: "pod-ephemeral-storage-limit", requests: newResourceList("", "", "1Gi"), limits: newResourceList("", "", "800Mi")}, + } + + pods := []*v1.Pod{} + podStats := map[*v1.Pod]statsapi.PodStats{} + for _, podToMake := range podsToMake { + pod, podStat := podMaker(podToMake.name, podToMake.priority, podToMake.requests, podToMake.limits, podToMake.memoryWorkingSet) + pods = append(pods, pod) + podStats[pod] = podStat + } + + summaryProvider := &fakeSummaryProvider{result: summaryStatsMaker("1Gi", "200Mi", podStats)} + + config := Config{ + MaxPodGracePeriodSeconds: 5, + PressureTransitionPeriod: time.Minute * 5, + Thresholds: []evictionapi.Threshold{ + { + Signal: evictionapi.SignalAllocatableMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("1Gi"), + }, + }, + }, + } + + podKiller := &mockPodKiller{} + diskGC := &mockDiskGC{err: nil} + nodeRef := &v1.ObjectReference{Kind: "Node", Name: "test", UID: types.UID("test"), Namespace: ""} + fakeClock := testingclock.NewFakeClock(time.Now()) + diskInfoProvider := &mockDiskInfoProvider{dedicatedImageFs: false} + + mgr := &managerImpl{ + clock: fakeClock, + killPodFunc: podKiller.killPodNow, + imageGC: diskGC, + containerGC: diskGC, + config: config, + recorder: &record.FakeRecorder{}, + summaryProvider: summaryProvider, + nodeRef: nodeRef, + localStorageCapacityIsolation: true, + dedicatedImageFs: &diskInfoProvider.dedicatedImageFs, + } + + activePodsFunc := func() []*v1.Pod { + return pods + } + + evictedPods := mgr.synchronize(diskInfoProvider, activePodsFunc) + + if podKiller.pod == nil { + t.Fatalf("Manager should have selected a pod for eviction") + } + + if diff := cmp.Diff(pods, evictedPods); diff != "" { + t.Fatalf("Unexpected evicted pod (-want,+got):\n%s", diff) + } +} diff --git a/pkg/kubelet/eviction/helpers_test.go b/pkg/kubelet/eviction/helpers_test.go index 4bb8ac4cf3f8..0a7b3c51f8a4 100644 --- a/pkg/kubelet/eviction/helpers_test.go +++ b/pkg/kubelet/eviction/helpers_test.go @@ -2029,6 +2029,24 @@ func newPodMemoryStats(pod *v1.Pod, workingSet resource.Quantity) statsapi.PodSt Memory: &statsapi.MemoryStats{ WorkingSetBytes: &workingSetBytes, }, + VolumeStats: []statsapi.VolumeStats{ + { + FsStats: statsapi.FsStats{ + UsedBytes: &workingSetBytes, + }, + Name: "local-volume", + }, + }, + Containers: []statsapi.ContainerStats{ + { + Name: pod.Name, + Logs: &statsapi.FsStats{ + UsedBytes: &workingSetBytes, + }, + Rootfs: &statsapi.FsStats{UsedBytes: &workingSetBytes}, + }, + }, + EphemeralStorage: &statsapi.FsStats{UsedBytes: &workingSetBytes}, } }