1
0
mirror of https://github.com/kubernetes-sigs/descheduler.git synced 2026-01-26 13:29:11 +01:00

RemovePodsViolatingTopologySpreadConstraint defaulting + moving arguments to its corresponding plugin

This commit is contained in:
vlc刘诚
2022-09-19 15:15:59 +08:00
parent 5a755e73f2
commit dc04abc0e6
10 changed files with 139 additions and 115 deletions

View File

@@ -27,7 +27,6 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog/v2"
"sigs.k8s.io/descheduler/pkg/apis/componentconfig"
"sigs.k8s.io/descheduler/pkg/descheduler/evictions"
"sigs.k8s.io/descheduler/pkg/descheduler/node"
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
@@ -51,7 +50,7 @@ type topology struct {
// RemovePodsViolatingTopologySpreadConstraint evicts pods which violate their topology spread constraints
type RemovePodsViolatingTopologySpreadConstraint struct {
handle framework.Handle
args *componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs
args *RemovePodsViolatingTopologySpreadConstraintArgs
podFilter podutil.FilterFunc
}
@@ -59,7 +58,7 @@ var _ framework.BalancePlugin = &RemovePodsViolatingTopologySpreadConstraint{}
// New builds plugin from its arguments while passing a handle
func New(args runtime.Object, handle framework.Handle) (framework.Plugin, error) {
pluginArgs, ok := args.(*componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs)
pluginArgs, ok := args.(*RemovePodsViolatingTopologySpreadConstraintArgs)
if !ok {
return nil, fmt.Errorf("want args to be of type RemovePodsViolatingTopologySpreadConstraintArgs, got %T", args)
}

View File

@@ -16,7 +16,6 @@ import (
"k8s.io/client-go/tools/events"
"sigs.k8s.io/descheduler/pkg/api"
"sigs.k8s.io/descheduler/pkg/apis/componentconfig"
"sigs.k8s.io/descheduler/pkg/descheduler/evictions"
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
"sigs.k8s.io/descheduler/pkg/framework"
@@ -33,7 +32,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
expectedEvictedPods []string // if specified, will assert specific pods were evicted
nodes []*v1.Node
namespaces []string
args componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs
args RemovePodsViolatingTopologySpreadConstraintArgs
nodeFit bool
}{
{
@@ -69,7 +68,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains, sizes [3,1], maxSkew=1, move 1 pod to achieve [2,2]",
@@ -97,7 +96,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 1,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains, sizes [3,1], maxSkew=1, move 1 pod to achieve [2,2] (soft constraints)",
@@ -132,7 +131,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 1,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{IncludeSoftConstraints: true},
args: RemovePodsViolatingTopologySpreadConstraintArgs{IncludeSoftConstraints: true},
},
{
name: "2 domains, sizes [3,1], maxSkew=1, no pods eligible, move 0 pods",
@@ -163,7 +162,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains, sizes [3,1], maxSkew=1, move 1 pod to achieve [2,2], exclude kube-system namespace",
@@ -191,7 +190,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 1,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{Namespaces: &api.Namespaces{Exclude: []string{"kube-system"}}},
args: RemovePodsViolatingTopologySpreadConstraintArgs{Namespaces: &api.Namespaces{Exclude: []string{"kube-system"}}},
nodeFit: true,
},
{
@@ -220,7 +219,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 1,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains, sizes [4,0], maxSkew=1, move 2 pods to achieve [2,2]",
@@ -243,7 +242,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 2,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains, sizes [4,0], maxSkew=1, only move 1 pod since pods with nodeSelector and nodeAffinity aren't evicted",
@@ -283,7 +282,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 1,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
nodeFit: true,
},
{
@@ -327,7 +326,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 2,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "3 domains, sizes [0, 1, 100], maxSkew=1, move 66 pods to get [34, 33, 34]",
@@ -351,7 +350,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 66,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "4 domains, sizes [0, 1, 3, 5], should move 3 to get [2, 2, 3, 2]",
@@ -381,7 +380,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 3,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains size [2 6], maxSkew=2, should move 1 to get [3 5]",
@@ -409,7 +408,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 1,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains size [2 6], maxSkew=2, can't move any because of node taints",
@@ -453,7 +452,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
nodeFit: true,
},
{
@@ -482,7 +481,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
nodeFit: true,
},
{
@@ -588,7 +587,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 1,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{IncludeSoftConstraints: true},
args: RemovePodsViolatingTopologySpreadConstraintArgs{IncludeSoftConstraints: true},
},
{
name: "3 domains size [8 7 0], maxSkew=1, should move 5 to get [5 5 5]",
@@ -614,7 +613,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
expectedEvictedCount: 5,
expectedEvictedPods: []string{"pod-5", "pod-6", "pod-7", "pod-8"},
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "3 domains size [5 5 5], maxSkew=1, should move 0 to retain [5 5 5]",
@@ -645,7 +644,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains, sizes [2,0], maxSkew=1, move 1 pod since pod tolerates the node with taint",
@@ -687,7 +686,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
expectedEvictedCount: 1,
expectedEvictedPods: []string{"pod-0"},
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains, sizes [2,0], maxSkew=1, move 0 pods since pod does not tolerate the tainted node",
@@ -720,7 +719,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains, sizes [2,0], maxSkew=1, move 0 pods since pod does not tolerate the tainted node, and NodeFit is enabled",
@@ -753,7 +752,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
nodeFit: true,
},
{
@@ -788,7 +787,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
expectedEvictedCount: 1,
expectedEvictedPods: []string{"pod-0"},
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
},
{
name: "2 domains, sizes [2,0], maxSkew=1, move 0 pod for node with unmatched label filtering",
@@ -811,7 +810,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{LabelSelector: getLabelSelector("foo", []string{"baz"}, metav1.LabelSelectorOpIn)},
args: RemovePodsViolatingTopologySpreadConstraintArgs{LabelSelector: getLabelSelector("foo", []string{"baz"}, metav1.LabelSelectorOpIn)},
},
{
name: "2 domains, sizes [2,0], maxSkew=1, move 1 pod for node with matched label filtering",
@@ -835,7 +834,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
expectedEvictedCount: 1,
expectedEvictedPods: []string{"pod-1"},
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{LabelSelector: getLabelSelector("foo", []string{"bar"}, metav1.LabelSelectorOpIn)},
args: RemovePodsViolatingTopologySpreadConstraintArgs{LabelSelector: getLabelSelector("foo", []string{"bar"}, metav1.LabelSelectorOpIn)},
},
{
name: "2 domains, sizes [2,0], maxSkew=1, move 1 pod for node with matched label filtering (NotIn op)",
@@ -859,7 +858,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
expectedEvictedCount: 1,
expectedEvictedPods: []string{"pod-1"},
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{LabelSelector: getLabelSelector("foo", []string{"baz"}, metav1.LabelSelectorOpNotIn)},
args: RemovePodsViolatingTopologySpreadConstraintArgs{LabelSelector: getLabelSelector("foo", []string{"baz"}, metav1.LabelSelectorOpNotIn)},
},
{
name: "2 domains, sizes [4,2], maxSkew=1, 2 pods in termination; nothing should be moved",
@@ -890,7 +889,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{LabelSelector: getLabelSelector("foo", []string{"bar"}, metav1.LabelSelectorOpIn)},
args: RemovePodsViolatingTopologySpreadConstraintArgs{LabelSelector: getLabelSelector("foo", []string{"bar"}, metav1.LabelSelectorOpIn)},
},
{
name: "3 domains, sizes [2,3,4], maxSkew=1, NodeFit is enabled, and not enough cpu on zoneA; nothing should be moved",
@@ -921,7 +920,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
nodeFit: true,
},
{
@@ -968,7 +967,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
nodeFit: true,
},
{
@@ -1008,7 +1007,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
expectedEvictedCount: 1,
expectedEvictedPods: []string{"pod-4"},
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
nodeFit: true,
},
{
@@ -1115,7 +1114,7 @@ func TestTopologySpreadConstraint(t *testing.T) {
}),
expectedEvictedCount: 0,
namespaces: []string{"ns1"},
args: componentconfig.RemovePodsViolatingTopologySpreadConstraintArgs{},
args: RemovePodsViolatingTopologySpreadConstraintArgs{},
nodeFit: true,
},
}

View File

@@ -0,0 +1,34 @@
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package removepodsviolatingtopologyspreadconstraint
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/descheduler/pkg/api"
)
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RemovePodsViolatingTopologySpreadConstraintArgs holds arguments used to configure RemovePodsViolatingTopologySpreadConstraint plugin.
type RemovePodsViolatingTopologySpreadConstraintArgs struct {
metav1.TypeMeta
Namespaces *api.Namespaces
LabelSelector *metav1.LabelSelector
IncludeSoftConstraints bool
}

View File

@@ -0,0 +1,38 @@
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package removepodsviolatingtopologyspreadconstraint
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ValidateRemovePodsViolatingTopologySpreadConstraintArgs validates RemovePodsViolatingTopologySpreadConstraint arguments
func ValidateRemovePodsViolatingTopologySpreadConstraintArgs(args *RemovePodsViolatingTopologySpreadConstraintArgs) error {
// At most one of include/exclude can be set
if args.Namespaces != nil && len(args.Namespaces.Include) > 0 && len(args.Namespaces.Exclude) > 0 {
return fmt.Errorf("only one of Include/Exclude namespaces can be set")
}
if args.LabelSelector != nil {
if _, err := metav1.LabelSelectorAsSelector(args.LabelSelector); err != nil {
return fmt.Errorf("failed to get label selectors from strategy's params: %+v", err)
}
}
return nil
}

View File

@@ -0,0 +1,63 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package removepodsviolatingtopologyspreadconstraint
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
api "sigs.k8s.io/descheduler/pkg/api"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RemovePodsViolatingTopologySpreadConstraintArgs) DeepCopyInto(out *RemovePodsViolatingTopologySpreadConstraintArgs) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Namespaces != nil {
in, out := &in.Namespaces, &out.Namespaces
*out = new(api.Namespaces)
(*in).DeepCopyInto(*out)
}
if in.LabelSelector != nil {
in, out := &in.LabelSelector, &out.LabelSelector
*out = new(v1.LabelSelector)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemovePodsViolatingTopologySpreadConstraintArgs.
func (in *RemovePodsViolatingTopologySpreadConstraintArgs) DeepCopy() *RemovePodsViolatingTopologySpreadConstraintArgs {
if in == nil {
return nil
}
out := new(RemovePodsViolatingTopologySpreadConstraintArgs)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *RemovePodsViolatingTopologySpreadConstraintArgs) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}