From 372bf95a4f208473aed21b4142b1d673aade0d0c Mon Sep 17 00:00:00 2001 From: ianlang Date: Sun, 27 Oct 2019 23:27:00 +0800 Subject: [PATCH 1/2] reject pods when under disk pressure --- pkg/kubelet/eviction/eviction_manager.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/kubelet/eviction/eviction_manager.go b/pkg/kubelet/eviction/eviction_manager.go index 1e3fce78e17..dd79d809e01 100644 --- a/pkg/kubelet/eviction/eviction_manager.go +++ b/pkg/kubelet/eviction/eviction_manager.go @@ -137,8 +137,10 @@ func (m *managerImpl) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAd if kubelettypes.IsCriticalPod(attrs.Pod) { return lifecycle.PodAdmitResult{Admit: true} } - // the node has memory pressure, admit if not best-effort - if hasNodeCondition(m.nodeConditions, v1.NodeMemoryPressure) { + + // Conditions other than memory pressure reject all pods + nodeOnlyHasMemoryPressureCondition := hasNodeCondition(m.nodeConditions, v1.NodeMemoryPressure) && len(m.nodeConditions) == 1 + if nodeOnlyHasMemoryPressureCondition { notBestEffort := v1.PodQOSBestEffort != v1qos.GetPodQOS(attrs.Pod) if notBestEffort { return lifecycle.PodAdmitResult{Admit: true} From 22d8e054bcc69c8ac1f7eb8de28f2c477a2a3474 Mon Sep 17 00:00:00 2001 From: ianlang Date: Mon, 28 Oct 2019 11:32:53 +0800 Subject: [PATCH 2/2] unit test: TestAdmitUnderNodeConditions --- pkg/kubelet/eviction/eviction_manager_test.go | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/pkg/kubelet/eviction/eviction_manager_test.go b/pkg/kubelet/eviction/eviction_manager_test.go index fa407d8679a..2087002da7a 100644 --- a/pkg/kubelet/eviction/eviction_manager_test.go +++ b/pkg/kubelet/eviction/eviction_manager_test.go @@ -391,6 +391,52 @@ func TestMemoryPressure(t *testing.T) { } } +func makeContainersByQOS(class v1.PodQOSClass) []v1.Container { + resource := newResourceList("100m", "1Gi", "") + switch class { + case v1.PodQOSGuaranteed: + return []v1.Container{newContainer("guaranteed-container", resource, resource)} + case v1.PodQOSBurstable: + return []v1.Container{newContainer("burtable-container", resource, nil)} + case v1.PodQOSBestEffort: + fallthrough + default: + return []v1.Container{newContainer("best-effort-container", nil, nil)} + } +} + +func TestAdmitUnderNodeConditions(t *testing.T) { + manager := &managerImpl{} + pods := []*v1.Pod{ + newPod("guaranteed-pod", scheduling.DefaultPriorityWhenNoDefaultClassExists, makeContainersByQOS(v1.PodQOSGuaranteed), nil), + newPod("burstable-pod", scheduling.DefaultPriorityWhenNoDefaultClassExists, makeContainersByQOS(v1.PodQOSBurstable), nil), + newPod("best-effort-pod", scheduling.DefaultPriorityWhenNoDefaultClassExists, makeContainersByQOS(v1.PodQOSBestEffort), nil), + } + + expected := []bool{true, true, true} + for i, pod := range pods { + if result := manager.Admit(&lifecycle.PodAdmitAttributes{Pod: pod}); expected[i] != result.Admit { + t.Errorf("Admit pod: %v, expected: %v, actual: %v", pod, expected[i], result.Admit) + } + } + + manager.nodeConditions = []v1.NodeConditionType{v1.NodeMemoryPressure} + expected = []bool{true, true, false} + for i, pod := range pods { + if result := manager.Admit(&lifecycle.PodAdmitAttributes{Pod: pod}); expected[i] != result.Admit { + t.Errorf("Admit pod: %v, expected: %v, actual: %v", pod, expected[i], result.Admit) + } + } + + manager.nodeConditions = []v1.NodeConditionType{v1.NodeMemoryPressure, v1.NodeDiskPressure} + expected = []bool{false, false, false} + for i, pod := range pods { + if result := manager.Admit(&lifecycle.PodAdmitAttributes{Pod: pod}); expected[i] != result.Admit { + t.Errorf("Admit pod: %v, expected: %v, actual: %v", pod, expected[i], result.Admit) + } + } +} + // parseQuantity parses the specified value (if provided) otherwise returns 0 value func parseQuantity(value string) resource.Quantity { if len(value) == 0 {