Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions apis/kueue/v1beta1/clusterqueue_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,16 @@ const (
TryNextFlavor FlavorFungibilityPolicy = "TryNextFlavor"
)

type FlavorFungibilityPreference string

const (
BorrowingOverPreemption FlavorFungibilityPreference = "BorrowingOverPreemption"
PreemptionOverBorrowing FlavorFungibilityPreference = "PreemptionOverBorrowing"
)

// FlavorFungibility determines whether a workload should try the next flavor
// before borrowing or preempting in current flavor.
// +kubebuilder:validation:XValidation:rule="!has(self.preference) || (self.whenCanBorrow == 'TryNextFlavor' && self.whenCanPreempt == 'TryNextFlavor')",message="preference can only be set when both whenCanBorrow and whenCanPreempt are TryNextFlavor"
type FlavorFungibility struct {
// whenCanBorrow determines whether a workload should try the next flavor
// before borrowing in current flavor. The possible values are:
Expand All @@ -414,6 +422,17 @@ type FlavorFungibility struct {
// +kubebuilder:validation:Enum={MayStopSearch,TryNextFlavor,Preempt}
// +kubebuilder:default="TryNextFlavor"
WhenCanPreempt FlavorFungibilityPolicy `json:"whenCanPreempt,omitempty"`
// preference selects the order between minimizing preemption and avoiding borrowing
// when both policies are set to TryNextFlavor. The possible values are:
Comment on lines +425 to +426
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// preference selects the order between minimizing preemption and avoiding borrowing
// when both policies are set to TryNextFlavor. The possible values are:
// preference guides the choosing of the flavor for admission in case all candidate flavors
// require either preemption, borrowing, or both. The possible values are:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sure aligned with the KEP

//
// - `BorrowingOverPreemption` (default): prefer lower borrowing distance before preferring lower preemption mode.
// - `PreemptionOverBorrowing`: prefer lower preemption mode before preferring lower borrowing distance.
Comment on lines +428 to +429
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// - `BorrowingOverPreemption` (default): prefer lower borrowing distance before preferring lower preemption mode.
// - `PreemptionOverBorrowing`: prefer lower preemption mode before preferring lower borrowing distance.
// - `BorrowingOverPreemption` (default): prefer to use borrowing rather than preemption
// when such a choice is possible. More technically it minimizes the borrowing distance
// in the cohort tree, and solves tie-breaks by preferring better preemption mode
// (reclaim over preemption within ClusterQueue).
// - `PreemptionOverBorrowing`: prefer to use preemption rather than borrowing
// when such a choice is possible. More technically it optimizes the preemption mode
// (reclaim over preemption within ClusterQueue), and solves tie-breaks by minimizing
// the borrowing distance in the cohort tree.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sure aligned with the KEP

//
// Deprecated values from earlier releases are not supported; please use the names above.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a new field, there are no depreacted values from earlier releases. Remove this line

//
// +kubebuilder:validation:Enum={BorrowingOverPreemption,PreemptionOverBorrowing}
// +optional
Preference *FlavorFungibilityPreference `json:"preference,omitempty"`
}

// ClusterQueuePreemption contains policies to preempt Workloads from this
Expand Down
2 changes: 2 additions & 0 deletions apis/kueue/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion apis/kueue/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions apis/kueue/v1beta2/clusterqueue_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,16 @@ const (
TryNextFlavor FlavorFungibilityPolicy = "TryNextFlavor"
)

type FlavorFungibilityPreference string

const (
BorrowingOverPreemption FlavorFungibilityPreference = "BorrowingOverPreemption"
PreemptionOverBorrowing FlavorFungibilityPreference = "PreemptionOverBorrowing"
)

// FlavorFungibility determines whether a workload should try the next flavor
// before borrowing or preempting in current flavor.
// +kubebuilder:validation:XValidation:rule="!has(self.preference) || (self.whenCanBorrow == 'TryNextFlavor' && self.whenCanPreempt == 'TryNextFlavor')",message="preference can only be set when both whenCanBorrow and whenCanPreempt are TryNextFlavor"
type FlavorFungibility struct {
// whenCanBorrow determines whether a workload should try the next flavor
// before borrowing in current flavor. The possible values are:
Expand All @@ -406,6 +414,15 @@ type FlavorFungibility struct {
// +kubebuilder:default="TryNextFlavor"
// +optional
WhenCanPreempt FlavorFungibilityPolicy `json:"whenCanPreempt,omitempty"`
// preference selects the order between minimizing preemption and avoiding borrowing
// when both policies are set to TryNextFlavor. The possible values are:
//
// - `BorrowingOverPreemption` (default): prefer lower borrowing distance before preferring lower preemption mode.
// - `PreemptionOverBorrowing`: prefer lower preemption mode before preferring lower borrowing distance.
//
// +kubebuilder:validation:Enum={BorrowingOverPreemption,PreemptionOverBorrowing}
// +optional
Preference *FlavorFungibilityPreference `json:"preference,omitempty"`
}

// ClusterQueuePreemption contains policies to preempt Workloads from this
Expand Down
7 changes: 6 additions & 1 deletion apis/kueue/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions charts/kueue/templates/crd/kueue.x-k8s.io_clusterqueues.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,19 @@ spec:
flavorFungibility defines whether a workload should try the next flavor
before borrowing or preempting in the flavor being evaluated.
properties:
preference:
description: |-
preference selects the order between minimizing preemption and avoiding borrowing
when both policies are set to TryNextFlavor. The possible values are:

- `BorrowingOverPreemption` (default): prefer lower borrowing distance before preferring lower preemption mode.
- `PreemptionOverBorrowing`: prefer lower preemption mode before preferring lower borrowing distance.

Deprecated values from earlier releases are not supported; please use the names above.
enum:
- BorrowingOverPreemption
- PreemptionOverBorrowing
type: string
whenCanBorrow:
default: MayStopSearch
description: |-
Expand Down Expand Up @@ -224,6 +237,9 @@ spec:
- Preempt
type: string
type: object
x-kubernetes-validations:
- message: preference can only be set when both whenCanBorrow and whenCanPreempt are TryNextFlavor
rule: '!has(self.preference) || (self.whenCanBorrow == ''TryNextFlavor'' && self.whenCanPreempt == ''TryNextFlavor'')'
namespaceSelector:
description: |-
namespaceSelector defines which namespaces are allowed to submit workloads to
Expand Down Expand Up @@ -940,6 +956,17 @@ spec:
flavorFungibility defines whether a workload should try the next flavor
before borrowing or preempting in the flavor being evaluated.
properties:
preference:
description: |-
preference selects the order between minimizing preemption and avoiding borrowing
when both policies are set to TryNextFlavor. The possible values are:

- `BorrowingOverPreemption` (default): prefer lower borrowing distance before preferring lower preemption mode.
- `PreemptionOverBorrowing`: prefer lower preemption mode before preferring lower borrowing distance.
enum:
- BorrowingOverPreemption
- PreemptionOverBorrowing
type: string
whenCanBorrow:
default: MayStopSearch
description: |-
Expand Down Expand Up @@ -968,6 +995,9 @@ spec:
- TryNextFlavor
type: string
type: object
x-kubernetes-validations:
- message: preference can only be set when both whenCanBorrow and whenCanPreempt are TryNextFlavor
rule: '!has(self.preference) || (self.whenCanBorrow == ''TryNextFlavor'' && self.whenCanPreempt == ''TryNextFlavor'')'
namespaceSelector:
description: |-
namespaceSelector defines which namespaces are allowed to submit workloads to
Expand Down
13 changes: 11 additions & 2 deletions client-go/applyconfiguration/kueue/v1beta1/flavorfungibility.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions client-go/applyconfiguration/kueue/v1beta2/flavorfungibility.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions config/components/crd/bases/kueue.x-k8s.io_clusterqueues.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,19 @@ spec:
flavorFungibility defines whether a workload should try the next flavor
before borrowing or preempting in the flavor being evaluated.
properties:
preference:
description: |-
preference selects the order between minimizing preemption and avoiding borrowing
when both policies are set to TryNextFlavor. The possible values are:

- `BorrowingOverPreemption` (default): prefer lower borrowing distance before preferring lower preemption mode.
- `PreemptionOverBorrowing`: prefer lower preemption mode before preferring lower borrowing distance.

Deprecated values from earlier releases are not supported; please use the names above.
enum:
- BorrowingOverPreemption
- PreemptionOverBorrowing
type: string
whenCanBorrow:
default: MayStopSearch
description: |-
Expand Down Expand Up @@ -195,6 +208,11 @@ spec:
- Preempt
type: string
type: object
x-kubernetes-validations:
- message: preference can only be set when both whenCanBorrow and
whenCanPreempt are TryNextFlavor
rule: '!has(self.preference) || (self.whenCanBorrow == ''TryNextFlavor''
&& self.whenCanPreempt == ''TryNextFlavor'')'
namespaceSelector:
description: |-
namespaceSelector defines which namespaces are allowed to submit workloads to
Expand Down Expand Up @@ -929,6 +947,17 @@ spec:
flavorFungibility defines whether a workload should try the next flavor
before borrowing or preempting in the flavor being evaluated.
properties:
preference:
description: |-
preference selects the order between minimizing preemption and avoiding borrowing
when both policies are set to TryNextFlavor. The possible values are:

- `BorrowingOverPreemption` (default): prefer lower borrowing distance before preferring lower preemption mode.
- `PreemptionOverBorrowing`: prefer lower preemption mode before preferring lower borrowing distance.
enum:
- BorrowingOverPreemption
- PreemptionOverBorrowing
type: string
whenCanBorrow:
default: MayStopSearch
description: |-
Expand Down Expand Up @@ -957,6 +986,11 @@ spec:
- TryNextFlavor
type: string
type: object
x-kubernetes-validations:
- message: preference can only be set when both whenCanBorrow and
whenCanPreempt are TryNextFlavor
rule: '!has(self.preference) || (self.whenCanBorrow == ''TryNextFlavor''
&& self.whenCanPreempt == ''TryNextFlavor'')'
namespaceSelector:
description: |-
namespaceSelector defines which namespaces are allowed to submit workloads to
Expand Down
12 changes: 10 additions & 2 deletions pkg/features/kube_features.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ const (
// owner: @pajakd
// kep: https://github.com/kubernetes-sigs/kueue/tree/main/keps/582-preempt-based-on-flavor-order
//
// In flavor fungibility, the preference whether to preempt or borrow is inferred from flavor fungibility policy
// This feature gate is going to be replaced by an API before graduation or deprecation.
// In flavor fungibility, the preference whether to preempt or borrow is inferred from flavor fungibility policy.
// Deprecated: planned to be removed in v0.17. Will remain enabled by default through v0.16.
FlavorFungibilityImplicitPreferenceDefault featuregate.Feature = "FlavorFungibilityImplicitPreferenceDefault"

// owner: @alaypatel07
Expand Down Expand Up @@ -297,6 +297,9 @@ var defaultVersionedFeatureGates = map[featuregate.Feature]featuregate.Versioned
},
FlavorFungibilityImplicitPreferenceDefault: {
{Version: version.MustParse("0.13"), Default: false, PreRelease: featuregate.Alpha},
// TODO: what to do with feature gate?
// {Version: version.MustParse("0.15"), Default: true, PreRelease: featuregate.Beta},
// {Version: version.MustParse("0.16"), Default: true, PreRelease: featuregate.Deprecated}, // remove in 0.17
Comment on lines +300 to +302
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// {Version: version.MustParse("0.15"), Default: false, PreRelease: featuregate.Deprecated}, // remove in 0.16

},
DynamicResourceAllocation: {
{Version: version.MustParse("0.14"), Default: false, PreRelease: featuregate.Alpha},
Expand Down Expand Up @@ -327,6 +330,11 @@ func Enabled(f featuregate.Feature) bool {
return utilfeature.DefaultFeatureGate.Enabled(f)
}

// Disabled is helper for `!utilfeature.DefaultFeatureGate.Enabled()`
func Disabled(f featuregate.Feature) bool {
return !Enabled(f)
}
Comment on lines +333 to +336
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why just not use !Enabled(f)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I don't see value in the extra helper


// SetEnable helper function that can be used to set the enabled value of a feature gate,
// it should only be used in integration test pending the merge of
// https://github.com/kubernetes/kubernetes/pull/118346
Expand Down
32 changes: 23 additions & 9 deletions pkg/scheduler/flavorassigner/flavorassigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,25 +379,39 @@ func isPreferred(a, b granularMode, fungibilityConfig kueue.FlavorFungibility) b
return true
}

if !features.Enabled(features.FlavorFungibilityImplicitPreferenceDefault) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/hold
We cannot just remove the feature gate. We need to introduce API instead which will be able to express the preferences.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/unhold

borrowingOverPreemption := func() bool {
if a.preemptionMode != b.preemptionMode {
return a.preemptionMode > b.preemptionMode
} else {
return a.borrowingLevel.betterThan(b.borrowingLevel)
}
return a.borrowingLevel.betterThan(b.borrowingLevel)
}

if fungibilityConfig.WhenCanBorrow == kueue.TryNextFlavor {
preemptionOverBorrowing := func() bool {
if a.borrowingLevel != b.borrowingLevel {
return a.borrowingLevel.betterThan(b.borrowingLevel)
}
return a.preemptionMode > b.preemptionMode
} else {
if a.preemptionMode != b.preemptionMode {
return a.preemptionMode > b.preemptionMode
}

if fungibilityConfig.Preference != nil {
switch *fungibilityConfig.Preference {
case kueue.BorrowingOverPreemption:
return preemptionOverBorrowing()
case kueue.PreemptionOverBorrowing:
return borrowingOverPreemption()
}
return a.borrowingLevel.betterThan(b.borrowingLevel)
}

// BorrowingOverPreemption preference
if features.Disabled(features.FlavorFungibilityImplicitPreferenceDefault) {
return borrowingOverPreemption()
}

// PreemptionOverBorrowing preference
if fungibilityConfig.WhenCanBorrow == kueue.TryNextFlavor {
return preemptionOverBorrowing()
}
// BorrowingOverPreemption preference
return borrowingOverPreemption()
}

func fromPreemptionPossibility(preemptionPossibility preemptioncommon.PreemptionPossibility) preemptionMode {
Expand Down
Loading