diff --git a/README.md b/README.md index 982fa1f7d..c8837fd44 100644 --- a/README.md +++ b/README.md @@ -317,10 +317,14 @@ This strategy makes sure that pods violating [topology spread constraints](https are evicted from nodes. Specifically, it tries to evict the minimum number of pods required to balance topology domains to within each constraint's `maxSkew`. This strategy requires k8s version 1.18 at a minimum. +By default, this strategy only deals with hard constraints, setting parameter `includeSoftConstraints` to `true` will +include soft constraints. + **Parameters:** |Name|Type| |---|---| +|`includeSoftConstraints`|bool| |`thresholdPriority`|int (see [priority filtering](#priority-filtering))| |`thresholdPriorityClassName`|string (see [priority filtering](#priority-filtering))| |`namespaces`|(see [namespace filtering](#namespace-filtering))| @@ -333,6 +337,8 @@ kind: "DeschedulerPolicy" strategies: "RemovePodsViolatingTopologySpreadConstraint": enabled: true + params: + includeSoftConstraints: false ``` diff --git a/pkg/api/types.go b/pkg/api/types.go index be899ebb5..013f687ac 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -69,6 +69,7 @@ type StrategyParameters struct { PodsHavingTooManyRestarts *PodsHavingTooManyRestarts PodLifeTime *PodLifeTime RemoveDuplicates *RemoveDuplicates + IncludeSoftConstraints bool Namespaces *Namespaces ThresholdPriority *int32 ThresholdPriorityClassName string diff --git a/pkg/api/v1alpha1/types.go b/pkg/api/v1alpha1/types.go index f5717b33d..9f7f4e583 100644 --- a/pkg/api/v1alpha1/types.go +++ b/pkg/api/v1alpha1/types.go @@ -67,6 +67,7 @@ type StrategyParameters struct { PodsHavingTooManyRestarts *PodsHavingTooManyRestarts `json:"podsHavingTooManyRestarts,omitempty"` PodLifeTime *PodLifeTime `json:"podLifeTime,omitempty"` RemoveDuplicates *RemoveDuplicates `json:"removeDuplicates,omitempty"` + IncludeSoftConstraints bool `json:"includeSoftConstraints"` Namespaces *Namespaces `json:"namespaces"` ThresholdPriority *int32 `json:"thresholdPriority"` ThresholdPriorityClassName string `json:"thresholdPriorityClassName"` diff --git a/pkg/api/v1alpha1/zz_generated.conversion.go b/pkg/api/v1alpha1/zz_generated.conversion.go index e94a9cf4d..288f15621 100644 --- a/pkg/api/v1alpha1/zz_generated.conversion.go +++ b/pkg/api/v1alpha1/zz_generated.conversion.go @@ -284,6 +284,7 @@ func autoConvert_v1alpha1_StrategyParameters_To_api_StrategyParameters(in *Strat out.PodsHavingTooManyRestarts = (*api.PodsHavingTooManyRestarts)(unsafe.Pointer(in.PodsHavingTooManyRestarts)) out.PodLifeTime = (*api.PodLifeTime)(unsafe.Pointer(in.PodLifeTime)) out.RemoveDuplicates = (*api.RemoveDuplicates)(unsafe.Pointer(in.RemoveDuplicates)) + out.IncludeSoftConstraints = in.IncludeSoftConstraints out.Namespaces = (*api.Namespaces)(unsafe.Pointer(in.Namespaces)) out.ThresholdPriority = (*int32)(unsafe.Pointer(in.ThresholdPriority)) out.ThresholdPriorityClassName = in.ThresholdPriorityClassName @@ -301,6 +302,7 @@ func autoConvert_api_StrategyParameters_To_v1alpha1_StrategyParameters(in *api.S out.PodsHavingTooManyRestarts = (*PodsHavingTooManyRestarts)(unsafe.Pointer(in.PodsHavingTooManyRestarts)) out.PodLifeTime = (*PodLifeTime)(unsafe.Pointer(in.PodLifeTime)) out.RemoveDuplicates = (*RemoveDuplicates)(unsafe.Pointer(in.RemoveDuplicates)) + out.IncludeSoftConstraints = in.IncludeSoftConstraints out.Namespaces = (*Namespaces)(unsafe.Pointer(in.Namespaces)) out.ThresholdPriority = (*int32)(unsafe.Pointer(in.ThresholdPriority)) out.ThresholdPriorityClassName = in.ThresholdPriorityClassName diff --git a/pkg/descheduler/strategies/topologyspreadconstraint.go b/pkg/descheduler/strategies/topologyspreadconstraint.go index e4b0d8048..fd8dd520f 100644 --- a/pkg/descheduler/strategies/topologyspreadconstraint.go +++ b/pkg/descheduler/strategies/topologyspreadconstraint.go @@ -125,9 +125,8 @@ func RemovePodsViolatingTopologySpreadConstraint( namespaceTopologySpreadConstraints := make(map[v1.TopologySpreadConstraint]struct{}) for _, pod := range namespacePods.Items { for _, constraint := range pod.Spec.TopologySpreadConstraints { - // Only deal with hard topology constraints - // TODO(@damemi): add support for soft constraints - if constraint.WhenUnsatisfiable != v1.DoNotSchedule { + // Ignore soft topology constraints if they are not included + if (strategy.Params == nil || !strategy.Params.IncludeSoftConstraints) && constraint.WhenUnsatisfiable != v1.DoNotSchedule { continue } namespaceTopologySpreadConstraints[constraint] = struct{}{}