Skip to content

Commit

Permalink
Preemption while borrowing WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
mimowo committed Dec 18, 2023
1 parent a9d1d9f commit 67a8bce
Show file tree
Hide file tree
Showing 13 changed files with 740 additions and 17 deletions.
32 changes: 32 additions & 0 deletions apis/kueue/v1beta1/clusterqueue_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,10 @@ type ClusterQueuePreemption struct {
// +kubebuilder:validation:Enum=Never;LowerPriority;Any
ReclaimWithinCohort PreemptionPolicy `json:"reclaimWithinCohort,omitempty"`

// borrowWithinCohort provides configuration to allow preemption within
// cohort while borrowing.
BorrowWithinCohort *BorrowWithinCohort `json:"borrowFromCohortConfig,omitempty"`

// withinClusterQueue determines whether a pending Workload that doesn't fit
// within the nominal quota for its ClusterQueue, can preempt active Workloads in
// the ClusterQueue. The possible values are:
Expand All @@ -382,6 +386,34 @@ type ClusterQueuePreemption struct {
WithinClusterQueue PreemptionPolicy `json:"withinClusterQueue,omitempty"`
}

type BorrowWithinCohortPolicy string

const (
BorrowWithinCohortPolicyNever BorrowWithinCohortPolicy = "Never"
BorrowWithinCohortPolicyLowerPriority BorrowWithinCohortPolicy = "LowerPriority"
)

// BorrowWithinCohort contains configuration which allows to preempt workloads
// within cohort while borrowing.
type BorrowWithinCohort struct {
// policy determines the policy for preemption to reclaim quota within cohort while borrowing.
// Possible values are:
// - `Never` (default): do not reclaim quota within ClusterQueue while borrowing.
// - `LowerPriority`: allow preempting workloads to reclaim quota within the cohort,
// but only by preempting lower-priority workloads.
//
// +kubebuilder:default=Never
// +kubebuilder:validation:Enum=Never;LowerPriority
Policy BorrowWithinCohortPolicy `json:"policy,omitempty"`

// maxPriorityThreshold allows to restrict the set of workloads for preemption
// to reclaim quota within the cohort, to only workloads with priority below
// or equal the specified level.
//
// +optional
MaxPriorityThreshold *int32 `json:"maxPriorityThreshold,omitempty"`
}

//+genclient
//+genclient:nonNamespaced
//+kubebuilder:object:root=true
Expand Down
27 changes: 26 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.

24 changes: 24 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 @@ -176,6 +176,30 @@ spec:
of Workloads to preempt to accomomdate the pending Workload, preempting
Workloads with lower priority first."
properties:
borrowFromCohortConfig:
description: borrowWithinCohort provides configuration to allow
preemption within cohort while borrowing.
properties:
maxPriorityThreshold:
description: maxPriorityThreshold allows to restrict the set
of workloads for preemption to reclaim quota within the
cohort, to only workloads with priority below or equal the
specified level.
format: int32
type: integer
policy:
default: Never
description: 'policy determines the policy for preemption
to reclaim quota within cohort while borrowing. Possible
values are: - `Never` (default): do not reclaim quota within
ClusterQueue while borrowing. - `LowerPriority`: allow preempting
workloads to reclaim quota within the cohort, but only by
preempting lower-priority workloads.'
enum:
- Never
- LowerPriority
type: string
type: object
reclaimWithinCohort:
default: Never
description: "reclaimWithinCohort determines whether a pending
Expand Down
51 changes: 51 additions & 0 deletions client-go/applyconfiguration/kueue/v1beta1/borrowwithincohort.go

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

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

2 changes: 2 additions & 0 deletions client-go/applyconfiguration/utils.go

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

24 changes: 24 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,30 @@ spec:
of Workloads to preempt to accomomdate the pending Workload, preempting
Workloads with lower priority first."
properties:
borrowFromCohortConfig:
description: borrowWithinCohort provides configuration to allow
preemption within cohort while borrowing.
properties:
maxPriorityThreshold:
description: maxPriorityThreshold allows to restrict the set
of workloads for preemption to reclaim quota within the
cohort, to only workloads with priority below or equal the
specified level.
format: int32
type: integer
policy:
default: Never
description: 'policy determines the policy for preemption
to reclaim quota within cohort while borrowing. Possible
values are: - `Never` (default): do not reclaim quota within
ClusterQueue while borrowing. - `LowerPriority`: allow preempting
workloads to reclaim quota within the cohort, but only by
preempting lower-priority workloads.'
enum:
- Never
- LowerPriority
type: string
type: object
reclaimWithinCohort:
default: Never
description: "reclaimWithinCohort determines whether a pending
Expand Down
16 changes: 14 additions & 2 deletions pkg/scheduler/flavorassigner/flavorassigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ func (a *Assignment) findFlavorForResourceGroup(
if mode < representativeMode {
representativeMode = mode
}
needsBorrowing = needsBorrowing || (mode == Fit && borrow > 0)
needsBorrowing = needsBorrowing || ((mode == Fit || mode == Preempt) && borrow > 0)
if representativeMode == NoFit {
// The flavor doesn't fit, no need to check other resources.
break
Expand Down Expand Up @@ -483,7 +483,9 @@ func shouldTryNextFlavor(representativeMode FlavorAssignmentMode, flavorFungibil
policyPreempt := flavorFungibility.WhenCanPreempt
policyBorrow := flavorFungibility.WhenCanBorrow
if representativeMode == Preempt && policyPreempt == kueue.Preempt {
return false
if !needsBorrowing || policyBorrow == kueue.Borrow {
return false
}
}

if representativeMode == Fit && needsBorrowing && policyBorrow == kueue.Borrow {
Expand Down Expand Up @@ -558,6 +560,13 @@ func fitsResourceQuota(fName kueue.ResourceFlavorReference, rName corev1.Resourc
// ClusterQueue are preempted.
mode = Preempt
}
if cq.Preemption.BorrowWithinCohort != nil && cq.Preemption.BorrowWithinCohort.Policy != kueue.BorrowWithinCohortPolicyNever {
// when preemption with borrowing is enabled, we can succeeded admitting the
// workload if preemption is used.
if rQuota.BorrowingLimit != nil && val <= rQuota.Nominal+*rQuota.BorrowingLimit {
mode = Preempt
}
}
if rQuota.BorrowingLimit != nil && used+val > rQuota.Nominal+*rQuota.BorrowingLimit {
status.append(fmt.Sprintf("borrowing limit for %s in flavor %s exceeded", rName, fName))
return mode, 0, &status
Expand Down Expand Up @@ -589,6 +598,9 @@ func fitsResourceQuota(fName kueue.ResourceFlavorReference, rName corev1.Resourc
}
}
status.append(msg)
if borrow := val - rQuota.Nominal; borrow > 0 && mode == Preempt {
return mode, borrow, &status
}
return mode, 0, &status
}

Expand Down
Loading

0 comments on commit 67a8bce

Please sign in to comment.