mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-28 06:29:29 +01:00
Merge pull request #87 from aveshagarwal/master-pod-max-issue
Fix max pods to evict per node.
This commit is contained in:
@@ -54,7 +54,7 @@ func deleteDuplicatePods(client clientset.Interface, policyGroupVersion string,
|
|||||||
glog.V(1).Infof("%#v", creator)
|
glog.V(1).Infof("%#v", creator)
|
||||||
// i = 0 does not evict the first pod
|
// i = 0 does not evict the first pod
|
||||||
for i := 1; i < len(pods); i++ {
|
for i := 1; i < len(pods); i++ {
|
||||||
if nodepodCount[node]+1 > maxPodsToEvict {
|
if maxPodsToEvict > 0 && nodepodCount[node]+1 > maxPodsToEvict {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
success, err := evictions.EvictPod(client, pods[i], policyGroupVersion, dryRun)
|
success, err := evictions.EvictPod(client, pods[i], policyGroupVersion, dryRun)
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ func evictPods(inputPods []*v1.Pod,
|
|||||||
if IsNodeAboveTargetUtilization(nodeUsage, targetThresholds) && (*totalPods > 0 || *totalCpu > 0 || *totalMem > 0) {
|
if IsNodeAboveTargetUtilization(nodeUsage, targetThresholds) && (*totalPods > 0 || *totalCpu > 0 || *totalMem > 0) {
|
||||||
onePodPercentage := api.Percentage((float64(1) * 100) / float64(nodeCapacity.Pods().Value()))
|
onePodPercentage := api.Percentage((float64(1) * 100) / float64(nodeCapacity.Pods().Value()))
|
||||||
for _, pod := range inputPods {
|
for _, pod := range inputPods {
|
||||||
if *podsEvicted+1 > maxPodsToEvict {
|
if maxPodsToEvict > 0 && *podsEvicted+1 > maxPodsToEvict {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
cUsage := helper.GetResourceRequest(pod, v1.ResourceCPU)
|
cUsage := helper.GetResourceRequest(pod, v1.ResourceCPU)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func removePodsViolatingNodeAffinityCount(ds *options.DeschedulerServer, strateg
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
if nodepodCount[node]+1 > maxPodsToEvict {
|
if maxPodsToEvict > 0 && nodepodCount[node]+1 > maxPodsToEvict {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if pod.Spec.Affinity != nil && pod.Spec.Affinity.NodeAffinity != nil && pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil {
|
if pod.Spec.Affinity != nil && pod.Spec.Affinity.NodeAffinity != nil && pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil {
|
||||||
|
|||||||
@@ -143,16 +143,16 @@ func TestRemovePodsViolatingNodeAffinity(t *testing.T) {
|
|||||||
pods: addPodsToNode(nodeWithoutLabels),
|
pods: addPodsToNode(nodeWithoutLabels),
|
||||||
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
|
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
|
||||||
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
|
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
|
||||||
maxPodsToEvict: 1,
|
maxPodsToEvict: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Pod is scheduled on node without matching labels, another schedulable node available, maxPodsToEvict set to 0, should not be evicted",
|
description: "Pod is scheduled on node without matching labels, another schedulable node available, maxPodsToEvict set to 1, should not be evicted",
|
||||||
expectedEvictedPodCount: 0,
|
expectedEvictedPodCount: 1,
|
||||||
strategy: requiredDuringSchedulingIgnoredDuringExecutionStrategy,
|
strategy: requiredDuringSchedulingIgnoredDuringExecutionStrategy,
|
||||||
pods: addPodsToNode(nodeWithoutLabels),
|
pods: addPodsToNode(nodeWithoutLabels),
|
||||||
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
|
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
|
||||||
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
|
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
|
||||||
maxPodsToEvict: 0,
|
maxPodsToEvict: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Pod is scheduled on node without matching labels, but no node where pod fits is available, should not evict",
|
description: "Pod is scheduled on node without matching labels, but no node where pod fits is available, should not evict",
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func removePodsWithAffinityRules(client clientset.Interface, policyGroupVersion
|
|||||||
}
|
}
|
||||||
totalPods := len(pods)
|
totalPods := len(pods)
|
||||||
for i := 0; i < totalPods; i++ {
|
for i := 0; i < totalPods; i++ {
|
||||||
if nodePodCount[node]+1 > maxPodsToEvict {
|
if maxPodsToEvict > 0 && nodePodCount[node]+1 > maxPodsToEvict {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if checkPodsWithAntiAffinityExist(pods[i], pods) {
|
if checkPodsWithAntiAffinityExist(pods[i], pods) {
|
||||||
|
|||||||
@@ -32,63 +32,58 @@ func TestPodAntiAffinity(t *testing.T) {
|
|||||||
p1 := test.BuildTestPod("p1", 100, 0, node.Name)
|
p1 := test.BuildTestPod("p1", 100, 0, node.Name)
|
||||||
p2 := test.BuildTestPod("p2", 100, 0, node.Name)
|
p2 := test.BuildTestPod("p2", 100, 0, node.Name)
|
||||||
p3 := test.BuildTestPod("p3", 100, 0, node.Name)
|
p3 := test.BuildTestPod("p3", 100, 0, node.Name)
|
||||||
p3.Labels = map[string]string{"foo": "bar"}
|
p4 := test.BuildTestPod("p4", 100, 0, node.Name)
|
||||||
|
p2.Labels = map[string]string{"foo": "bar"}
|
||||||
p1.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
p1.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p2.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
p2.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p3.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
p3.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p1.Spec.Affinity = &v1.Affinity{
|
p4.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
PodAntiAffinity: &v1.PodAntiAffinity{
|
|
||||||
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
|
// set pod anti affinity
|
||||||
{
|
setPodAntiAffinity(p1)
|
||||||
LabelSelector: &metav1.LabelSelector{
|
setPodAntiAffinity(p3)
|
||||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
setPodAntiAffinity(p4)
|
||||||
{
|
|
||||||
Key: "foo",
|
// create fake client
|
||||||
Operator: metav1.LabelSelectorOpIn,
|
|
||||||
Values: []string{"bar"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TopologyKey: "region",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
p3.Spec.Affinity = &v1.Affinity{
|
|
||||||
PodAntiAffinity: &v1.PodAntiAffinity{
|
|
||||||
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
|
|
||||||
{
|
|
||||||
LabelSelector: &metav1.LabelSelector{
|
|
||||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: "foo",
|
|
||||||
Operator: metav1.LabelSelectorOpIn,
|
|
||||||
Values: []string{"bar"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TopologyKey: "region",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
fakeClient := &fake.Clientset{}
|
fakeClient := &fake.Clientset{}
|
||||||
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
return true, &v1.PodList{Items: []v1.Pod{*p1, *p2, *p3}}, nil
|
return true, &v1.PodList{Items: []v1.Pod{*p1, *p2, *p3, *p4}}, nil
|
||||||
})
|
})
|
||||||
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
return true, node, nil
|
return true, node, nil
|
||||||
})
|
})
|
||||||
npe := nodePodEvictedCount{}
|
npe := nodePodEvictedCount{}
|
||||||
npe[node] = 0
|
npe[node] = 0
|
||||||
expectedEvictedPodCount := 0
|
expectedEvictedPodCount := 3
|
||||||
podsEvicted := removePodsWithAffinityRules(fakeClient, "v1", []*v1.Node{node}, false, npe, 0)
|
podsEvicted := removePodsWithAffinityRules(fakeClient, "v1", []*v1.Node{node}, false, npe, 0)
|
||||||
if podsEvicted != expectedEvictedPodCount {
|
if podsEvicted != expectedEvictedPodCount {
|
||||||
t.Errorf("Unexpected no of pods evicted")
|
t.Errorf("Unexpected no of pods evicted: pods evicted: %d, expected: %d", podsEvicted, expectedEvictedPodCount)
|
||||||
}
|
}
|
||||||
|
npe[node] = 0
|
||||||
expectedEvictedPodCount = 1
|
expectedEvictedPodCount = 1
|
||||||
podsEvicted = removePodsWithAffinityRules(fakeClient, "v1", []*v1.Node{node}, false, npe, 1)
|
podsEvicted = removePodsWithAffinityRules(fakeClient, "v1", []*v1.Node{node}, false, npe, 1)
|
||||||
if podsEvicted != expectedEvictedPodCount {
|
if podsEvicted != expectedEvictedPodCount {
|
||||||
t.Errorf("Unexpected no of pods evicted")
|
t.Errorf("Unexpected no of pods evicted: pods evicted: %d, expected: %d", podsEvicted, expectedEvictedPodCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setPodAntiAffinity(inputPod *v1.Pod) {
|
||||||
|
inputPod.Spec.Affinity = &v1.Affinity{
|
||||||
|
PodAntiAffinity: &v1.PodAntiAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
|
||||||
|
{
|
||||||
|
LabelSelector: &metav1.LabelSelector{
|
||||||
|
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "foo",
|
||||||
|
Operator: metav1.LabelSelectorOpIn,
|
||||||
|
Values: []string{"bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TopologyKey: "region",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user