mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-26 05:14:13 +01:00
RemoveFailedPods defaulting + moving arguments to its corresponding plugin
This commit is contained in:
@@ -5,5 +5,5 @@ go build -o "${OS_OUTPUT_BINPATH}/conversion-gen" "k8s.io/code-generator/cmd/con
|
||||
|
||||
${OS_OUTPUT_BINPATH}/conversion-gen \
|
||||
--go-header-file "hack/boilerplate/boilerplate.go.txt" \
|
||||
--input-dirs "${PRJ_PREFIX}/pkg/apis/componentconfig/v1alpha1,${PRJ_PREFIX}/pkg/api/v1alpha1" \
|
||||
--input-dirs "${PRJ_PREFIX}/pkg/apis/componentconfig/v1alpha1,${PRJ_PREFIX}/pkg/api/v1alpha1,${PRJ_PREFIX}/pkg/framework/plugins/removefailedpods" \
|
||||
--output-file-base zz_generated.conversion
|
||||
|
||||
@@ -5,6 +5,6 @@ go build -o "${OS_OUTPUT_BINPATH}/deepcopy-gen" "k8s.io/code-generator/cmd/deepc
|
||||
|
||||
${OS_OUTPUT_BINPATH}/deepcopy-gen \
|
||||
--go-header-file "hack/boilerplate/boilerplate.go.txt" \
|
||||
--input-dirs "${PRJ_PREFIX}/pkg/apis/componentconfig,${PRJ_PREFIX}/pkg/apis/componentconfig/v1alpha1,${PRJ_PREFIX}/pkg/api,${PRJ_PREFIX}/pkg/api/v1alpha1,${PRJ_PREFIX}/pkg/framework/plugins/defaultevictor/" \
|
||||
--input-dirs "${PRJ_PREFIX}/pkg/apis/componentconfig,${PRJ_PREFIX}/pkg/apis/componentconfig/v1alpha1,${PRJ_PREFIX}/pkg/api,${PRJ_PREFIX}/pkg/api/v1alpha1,${PRJ_PREFIX}/pkg/framework/plugins/defaultevictor/,${PRJ_PREFIX}/pkg/framework/plugins/removefailedpods" \
|
||||
--output-file-base zz_generated.deepcopy
|
||||
|
||||
|
||||
@@ -35,20 +35,6 @@ type RemovePodsViolatingNodeTaintsArgs struct {
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// RemoveFailedPodsArgs holds arguments used to configure RemoveFailedPods plugin.
|
||||
type RemoveFailedPodsArgs struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
Namespaces *api.Namespaces
|
||||
LabelSelector *metav1.LabelSelector
|
||||
ExcludeOwnerKinds []string
|
||||
MinPodLifetimeSeconds *uint
|
||||
Reasons []string
|
||||
IncludingInitContainers bool
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// RemovePodsViolatingNodeAffinityArgs holds arguments used to configure RemovePodsViolatingNodeAffinity plugin.
|
||||
type RemovePodsViolatingNodeAffinityArgs struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
@@ -43,14 +43,6 @@ func ValidateRemovePodsViolatingNodeTaintsArgs(args *componentconfig.RemovePodsV
|
||||
)
|
||||
}
|
||||
|
||||
// ValidateRemoveFailedPodsArgs validates RemoveFailedPods arguments
|
||||
func ValidateRemoveFailedPodsArgs(args *componentconfig.RemoveFailedPodsArgs) error {
|
||||
return errorsAggregate(
|
||||
validateNamespaceArgs(args.Namespaces),
|
||||
validateLabelSelectorArgs(args.LabelSelector),
|
||||
)
|
||||
}
|
||||
|
||||
// ValidateRemovePodsHavingTooManyRestartsArgs validates RemovePodsHavingTooManyRestarts arguments
|
||||
func ValidateRemovePodsHavingTooManyRestartsArgs(args *componentconfig.RemovePodsHavingTooManyRestartsArgs) error {
|
||||
return errorsAggregate(
|
||||
|
||||
@@ -205,56 +205,6 @@ func (in *RemoveDuplicatesArgs) DeepCopyObject() runtime.Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RemoveFailedPodsArgs) DeepCopyInto(out *RemoveFailedPodsArgs) {
|
||||
*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)
|
||||
}
|
||||
if in.ExcludeOwnerKinds != nil {
|
||||
in, out := &in.ExcludeOwnerKinds, &out.ExcludeOwnerKinds
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.MinPodLifetimeSeconds != nil {
|
||||
in, out := &in.MinPodLifetimeSeconds, &out.MinPodLifetimeSeconds
|
||||
*out = new(uint)
|
||||
**out = **in
|
||||
}
|
||||
if in.Reasons != nil {
|
||||
in, out := &in.Reasons, &out.Reasons
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoveFailedPodsArgs.
|
||||
func (in *RemoveFailedPodsArgs) DeepCopy() *RemoveFailedPodsArgs {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RemoveFailedPodsArgs)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *RemoveFailedPodsArgs) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RemovePodsHavingTooManyRestartsArgs) DeepCopyInto(out *RemovePodsHavingTooManyRestartsArgs) {
|
||||
*out = *in
|
||||
|
||||
@@ -67,7 +67,7 @@ var pluginsMap = map[string]func(ctx context.Context, nodes []*v1.Node, params *
|
||||
if failedPodsParams == nil {
|
||||
failedPodsParams = &api.FailedPods{}
|
||||
}
|
||||
args := &componentconfig.RemoveFailedPodsArgs{
|
||||
args := &removefailedpods.RemoveFailedPodsArgs{
|
||||
Namespaces: params.Namespaces,
|
||||
LabelSelector: params.LabelSelector,
|
||||
IncludingInitContainers: failedPodsParams.IncludingInitContainers,
|
||||
@@ -75,7 +75,7 @@ var pluginsMap = map[string]func(ctx context.Context, nodes []*v1.Node, params *
|
||||
ExcludeOwnerKinds: failedPodsParams.ExcludeOwnerKinds,
|
||||
Reasons: failedPodsParams.Reasons,
|
||||
}
|
||||
if err := validation.ValidateRemoveFailedPodsArgs(args); err != nil {
|
||||
if err := removefailedpods.ValidateRemoveFailedPodsArgs(args); err != nil {
|
||||
klog.V(1).ErrorS(err, "unable to validate plugin arguments", "pluginName", removefailedpods.PluginName)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
|
||||
"sigs.k8s.io/descheduler/pkg/framework"
|
||||
@@ -38,7 +37,7 @@ const PluginName = "RemoveFailedPods"
|
||||
// RemoveFailedPods evicts pods in failed status phase that match the given args criteria
|
||||
type RemoveFailedPods struct {
|
||||
handle framework.Handle
|
||||
args *componentconfig.RemoveFailedPodsArgs
|
||||
args *RemoveFailedPodsArgs
|
||||
podFilter podutil.FilterFunc
|
||||
}
|
||||
|
||||
@@ -46,7 +45,7 @@ var _ framework.DeschedulePlugin = &RemoveFailedPods{}
|
||||
|
||||
// New builds plugin from its arguments while passing a handle
|
||||
func New(args runtime.Object, handle framework.Handle) (framework.Plugin, error) {
|
||||
failedPodsArgs, ok := args.(*componentconfig.RemoveFailedPodsArgs)
|
||||
failedPodsArgs, ok := args.(*RemoveFailedPodsArgs)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("want args to be of type RemoveFailedPodsArgs, got %T", args)
|
||||
}
|
||||
@@ -114,7 +113,7 @@ func (d *RemoveFailedPods) Deschedule(ctx context.Context, nodes []*v1.Node) *fr
|
||||
}
|
||||
|
||||
// validateCanEvict looks at failedPodArgs to see if pod can be evicted given the args.
|
||||
func validateCanEvict(pod *v1.Pod, failedPodArgs *componentconfig.RemoveFailedPodsArgs) error {
|
||||
func validateCanEvict(pod *v1.Pod, failedPodArgs *RemoveFailedPodsArgs) error {
|
||||
var errs []error
|
||||
|
||||
if failedPodArgs.MinPodLifetimeSeconds != nil {
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/client-go/tools/events"
|
||||
"sigs.k8s.io/descheduler/pkg/apis/componentconfig"
|
||||
"sigs.k8s.io/descheduler/pkg/framework"
|
||||
|
||||
"sigs.k8s.io/descheduler/pkg/descheduler/evictions"
|
||||
@@ -45,8 +44,8 @@ func TestRemoveFailedPods(t *testing.T) {
|
||||
createRemoveFailedPodsArgs := func(
|
||||
includingInitContainers bool,
|
||||
reasons, excludeKinds []string,
|
||||
minAgeSeconds *uint) componentconfig.RemoveFailedPodsArgs {
|
||||
return componentconfig.RemoveFailedPodsArgs{
|
||||
minAgeSeconds *uint) RemoveFailedPodsArgs {
|
||||
return RemoveFailedPodsArgs{
|
||||
IncludingInitContainers: includingInitContainers,
|
||||
Reasons: reasons,
|
||||
MinPodLifetimeSeconds: minAgeSeconds,
|
||||
@@ -57,14 +56,14 @@ func TestRemoveFailedPods(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
nodes []*v1.Node
|
||||
args componentconfig.RemoveFailedPodsArgs
|
||||
args RemoveFailedPodsArgs
|
||||
expectedEvictedPodCount uint
|
||||
pods []*v1.Pod
|
||||
nodeFit bool
|
||||
}{
|
||||
{
|
||||
description: "default empty args, 0 failures, 0 evictions",
|
||||
args: componentconfig.RemoveFailedPodsArgs{},
|
||||
args: RemoveFailedPodsArgs{},
|
||||
nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)},
|
||||
expectedEvictedPodCount: 0,
|
||||
pods: []*v1.Pod{}, // no pods come back with field selector phase=Failed
|
||||
@@ -323,7 +322,7 @@ func TestRemoveFailedPods(t *testing.T) {
|
||||
t.Fatalf("Unable to initialize the plugin: %v", err)
|
||||
}
|
||||
|
||||
plugin, err := New(&componentconfig.RemoveFailedPodsArgs{
|
||||
plugin, err := New(&RemoveFailedPodsArgs{
|
||||
Reasons: tc.args.Reasons,
|
||||
MinPodLifetimeSeconds: tc.args.MinPodLifetimeSeconds,
|
||||
IncludingInitContainers: tc.args.IncludingInitContainers,
|
||||
|
||||
34
pkg/framework/plugins/removefailedpods/types.go
Normal file
34
pkg/framework/plugins/removefailedpods/types.go
Normal 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 removefailedpods
|
||||
|
||||
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
|
||||
|
||||
// RemoveFailedPodsArgs holds arguments used to configure RemoveFailedPods plugin.
|
||||
type RemoveFailedPodsArgs struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
Namespaces *api.Namespaces
|
||||
LabelSelector *metav1.LabelSelector
|
||||
ExcludeOwnerKinds []string
|
||||
MinPodLifetimeSeconds *uint
|
||||
Reasons []string
|
||||
IncludingInitContainers bool
|
||||
}
|
||||
36
pkg/framework/plugins/removefailedpods/validation.go
Normal file
36
pkg/framework/plugins/removefailedpods/validation.go
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
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 removefailedpods
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// ValidateRemoveFailedPodsArgs validates RemoveFailedPods arguments
|
||||
func ValidateRemoveFailedPodsArgs(args *RemoveFailedPodsArgs) 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
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
//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 removefailedpods
|
||||
|
||||
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 *RemoveFailedPodsArgs) DeepCopyInto(out *RemoveFailedPodsArgs) {
|
||||
*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)
|
||||
}
|
||||
if in.ExcludeOwnerKinds != nil {
|
||||
in, out := &in.ExcludeOwnerKinds, &out.ExcludeOwnerKinds
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.MinPodLifetimeSeconds != nil {
|
||||
in, out := &in.MinPodLifetimeSeconds, &out.MinPodLifetimeSeconds
|
||||
*out = new(uint)
|
||||
**out = **in
|
||||
}
|
||||
if in.Reasons != nil {
|
||||
in, out := &in.Reasons, &out.Reasons
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoveFailedPodsArgs.
|
||||
func (in *RemoveFailedPodsArgs) DeepCopy() *RemoveFailedPodsArgs {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RemoveFailedPodsArgs)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *RemoveFailedPodsArgs) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/descheduler/pkg/apis/componentconfig"
|
||||
"sigs.k8s.io/descheduler/pkg/framework"
|
||||
frameworkfake "sigs.k8s.io/descheduler/pkg/framework/fake"
|
||||
"sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor"
|
||||
@@ -39,27 +38,27 @@ func TestFailedPods(t *testing.T) {
|
||||
defer clientSet.CoreV1().Namespaces().Delete(ctx, testNamespace.Name, metav1.DeleteOptions{})
|
||||
testCases := map[string]struct {
|
||||
expectedEvictedCount uint
|
||||
args *componentconfig.RemoveFailedPodsArgs
|
||||
args *removefailedpods.RemoveFailedPodsArgs
|
||||
}{
|
||||
"test-failed-pods-default-args": {
|
||||
expectedEvictedCount: 1,
|
||||
args: &componentconfig.RemoveFailedPodsArgs{},
|
||||
args: &removefailedpods.RemoveFailedPodsArgs{},
|
||||
},
|
||||
"test-failed-pods-reason-unmatched": {
|
||||
expectedEvictedCount: 0,
|
||||
args: &componentconfig.RemoveFailedPodsArgs{
|
||||
args: &removefailedpods.RemoveFailedPodsArgs{
|
||||
Reasons: []string{"ReasonDoesNotMatch"},
|
||||
},
|
||||
},
|
||||
"test-failed-pods-min-age-unmet": {
|
||||
expectedEvictedCount: 0,
|
||||
args: &componentconfig.RemoveFailedPodsArgs{
|
||||
args: &removefailedpods.RemoveFailedPodsArgs{
|
||||
MinPodLifetimeSeconds: &oneHourPodLifetimeSeconds,
|
||||
},
|
||||
},
|
||||
"test-failed-pods-exclude-job-kind": {
|
||||
expectedEvictedCount: 0,
|
||||
args: &componentconfig.RemoveFailedPodsArgs{
|
||||
args: &removefailedpods.RemoveFailedPodsArgs{
|
||||
ExcludeOwnerKinds: []string{"Job"},
|
||||
},
|
||||
},
|
||||
@@ -100,7 +99,7 @@ func TestFailedPods(t *testing.T) {
|
||||
|
||||
t.Logf("Running RemoveFailedPods strategy for %s", name)
|
||||
|
||||
plugin, err := removefailedpods.New(&componentconfig.RemoveFailedPodsArgs{
|
||||
plugin, err := removefailedpods.New(&removefailedpods.RemoveFailedPodsArgs{
|
||||
Reasons: tc.args.Reasons,
|
||||
MinPodLifetimeSeconds: tc.args.MinPodLifetimeSeconds,
|
||||
IncludingInitContainers: tc.args.IncludingInitContainers,
|
||||
|
||||
Reference in New Issue
Block a user