Skip to content

Commit c655645

Browse files
authored
Refactor FlavorAssigner (#3536)
1 parent 9624ed8 commit c655645

File tree

5 files changed

+47
-53
lines changed

5 files changed

+47
-53
lines changed

pkg/resources/requests.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ func ResourceQuantity(name corev1.ResourceName, v int64) resource.Quantity {
9292
}
9393
}
9494

95+
func ResourceQuantityString(name corev1.ResourceName, v int64) string {
96+
rq := ResourceQuantity(name, v)
97+
return rq.String()
98+
}
99+
95100
func (req Requests) CountIn(capacity Requests) int32 {
96101
var result *int32
97102
for rName, rValue := range req {

pkg/scheduler/flavorassigner/flavorassigner.go

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -603,47 +603,37 @@ func flavorSelector(spec *corev1.PodSpec, allowedKeys sets.Set[string]) nodeaffi
603603
func (a *FlavorAssigner) fitsResourceQuota(log logr.Logger, fr resources.FlavorResource, val int64, rQuota cache.ResourceQuota) (granularMode, bool, *Status) {
604604
var status Status
605605
var borrow bool
606-
used := a.cq.ResourceNode.Usage[fr]
607-
mode := noFit
608-
if val <= rQuota.Nominal {
609-
// The request can be satisfied by the nominal quota, assuming quota is
610-
// reclaimed from the cohort or assuming all active workloads in the
611-
// ClusterQueue are preempted.
612-
mode = preempt
613-
}
614606

615-
if a.canPreemptWhileBorrowing() {
616-
// when preemption with borrowing is enabled, we can succeed to admit the
617-
// workload if preemption is used.
618-
if (rQuota.BorrowingLimit == nil || val <= rQuota.Nominal+*rQuota.BorrowingLimit) && val <= a.cq.PotentialAvailable(fr) {
619-
mode = preempt
620-
borrow = val > rQuota.Nominal
621-
}
622-
}
623-
if rQuota.BorrowingLimit != nil && used+val > rQuota.Nominal+*rQuota.BorrowingLimit {
624-
status.append(fmt.Sprintf("borrowing limit for %s in flavor %s exceeded", fr.Resource, fr.Flavor))
625-
return mode, borrow, &status
626-
}
607+
available := a.cq.Available(fr)
608+
maxCapacity := a.cq.PotentialAvailable(fr)
627609

628-
if a.oracle.IsReclaimPossible(log, a.cq, *a.wl, fr, val) {
629-
mode = reclaim
610+
// No Fit
611+
if val > maxCapacity {
612+
status.append(fmt.Sprintf("insufficient quota for %s in flavor %s, request > maximum capacity (%s > %s)",
613+
fr.Resource, fr.Flavor, resources.ResourceQuantityString(fr.Resource, val), resources.ResourceQuantityString(fr.Resource, maxCapacity)))
614+
return noFit, false, &status
630615
}
631616

632-
lack := val - a.cq.Available(fr)
633-
if lack <= 0 {
634-
return fit, used+val > rQuota.Nominal, nil
617+
// Fit
618+
if val <= available {
619+
return fit, a.cq.ResourceNode.Usage[fr]+val > rQuota.Nominal, nil
635620
}
636621

637-
lackQuantity := resources.ResourceQuantity(fr.Resource, lack)
638-
msg := fmt.Sprintf("insufficient unused quota in cohort for %s in flavor %s, %s more needed", fr.Resource, fr.Flavor, &lackQuantity)
639-
if !a.cq.HasParent() {
640-
if mode == noFit {
641-
msg = fmt.Sprintf("insufficient quota for %s in flavor %s in ClusterQueue", fr.Resource, fr.Flavor)
642-
} else {
643-
msg = fmt.Sprintf("insufficient unused quota for %s in flavor %s, %s more needed", fr.Resource, fr.Flavor, &lackQuantity)
622+
// Check if preemption is possible
623+
mode := noFit
624+
if val <= rQuota.Nominal {
625+
mode = preempt
626+
if a.oracle.IsReclaimPossible(log, a.cq, *a.wl, fr, val) {
627+
mode = reclaim
644628
}
629+
} else if a.canPreemptWhileBorrowing() {
630+
mode = preempt
631+
borrow = true
645632
}
646-
status.append(msg)
633+
634+
status.append(fmt.Sprintf("insufficient unused quota for %s in flavor %s, %s more needed",
635+
fr.Resource, fr.Flavor, resources.ResourceQuantityString(fr.Resource, val-available)))
636+
647637
return mode, borrow, &status
648638
}
649639

pkg/scheduler/flavorassigner/flavorassigner_test.go

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package flavorassigner
1818

1919
import (
20-
"fmt"
2120
"testing"
2221

2322
"github.com/go-logr/logr"
@@ -254,7 +253,7 @@ func TestAssignFlavors(t *testing.T) {
254253
},
255254
Status: &Status{
256255
reasons: []string{
257-
"insufficient quota for memory in flavor b_one in ClusterQueue",
256+
"insufficient quota for memory in flavor b_one, request > maximum capacity (10Mi > 1Mi)",
258257
},
259258
},
260259
Count: 1,
@@ -366,9 +365,9 @@ func TestAssignFlavors(t *testing.T) {
366365
},
367366
Status: &Status{
368367
reasons: []string{
369-
"insufficient unused quota in cohort for cpu in flavor one, 1 more needed",
370-
"insufficient unused quota in cohort for memory in flavor two, 5Mi more needed",
371-
"insufficient unused quota in cohort for example.com/gpu in flavor b_one, 1 more needed",
368+
"insufficient quota for cpu in flavor one, request > maximum capacity (3 > 2)",
369+
"insufficient unused quota for memory in flavor two, 5Mi more needed",
370+
"insufficient unused quota for example.com/gpu in flavor b_one, 1 more needed",
372371
},
373372
},
374373
Count: 1,
@@ -407,8 +406,8 @@ func TestAssignFlavors(t *testing.T) {
407406
},
408407
Status: &Status{
409408
reasons: []string{
410-
"insufficient quota for cpu in flavor one in ClusterQueue",
411-
"insufficient quota for memory in flavor two in ClusterQueue",
409+
"insufficient quota for cpu in flavor one, request > maximum capacity (3 > 2)",
410+
"insufficient quota for memory in flavor two, request > maximum capacity (10Mi > 5Mi)",
412411
},
413412
},
414413
Count: 1,
@@ -836,7 +835,7 @@ func TestAssignFlavors(t *testing.T) {
836835
corev1.ResourceCPU: resource.MustParse("2"),
837836
},
838837
Status: &Status{
839-
reasons: []string{"insufficient unused quota in cohort for cpu in flavor one, 1 more needed"},
838+
reasons: []string{"insufficient quota for cpu in flavor one, request > maximum capacity (2 > 1)"},
840839
},
841840
Count: 1,
842841
}},
@@ -882,7 +881,7 @@ func TestAssignFlavors(t *testing.T) {
882881
},
883882

884883
Status: &Status{
885-
reasons: []string{"borrowing limit for cpu in flavor one exceeded"},
884+
reasons: []string{"insufficient unused quota for cpu in flavor one, 1 more needed"},
886885
},
887886
Count: 1,
888887
}},
@@ -963,7 +962,7 @@ func TestAssignFlavors(t *testing.T) {
963962
corev1.ResourceCPU: resource.MustParse("2"),
964963
},
965964
Status: &Status{
966-
reasons: []string{"insufficient unused quota in cohort for cpu in flavor one, 2 more needed"},
965+
reasons: []string{"insufficient unused quota for cpu in flavor one, 2 more needed"},
967966
},
968967
Count: 1,
969968
}},
@@ -1080,7 +1079,7 @@ func TestAssignFlavors(t *testing.T) {
10801079
},
10811080
Status: &Status{
10821081
reasons: []string{
1083-
"insufficient quota for cpu in flavor one in ClusterQueue",
1082+
"insufficient quota for cpu in flavor one, request > maximum capacity (12 > 4)",
10841083
"insufficient unused quota for cpu in flavor tainted, 3 more needed",
10851084
},
10861085
},
@@ -1176,7 +1175,7 @@ func TestAssignFlavors(t *testing.T) {
11761175
corev1.ResourcePods: resource.MustParse("3"),
11771176
},
11781177
Status: &Status{
1179-
reasons: []string{fmt.Sprintf("insufficient quota for %s in flavor default in ClusterQueue", corev1.ResourcePods)},
1178+
reasons: []string{"insufficient quota for pods in flavor default, request > maximum capacity (3 > 2)"},
11801179
},
11811180
Count: 3,
11821181
}},
@@ -1504,7 +1503,7 @@ func TestAssignFlavors(t *testing.T) {
15041503
corev1.ResourceCPU: {Name: "one", Mode: Preempt, TriedFlavorIdx: 0},
15051504
},
15061505
Status: &Status{
1507-
reasons: []string{"insufficient unused quota in cohort for cpu in flavor one, 10 more needed"},
1506+
reasons: []string{"insufficient unused quota for cpu in flavor one, 10 more needed"},
15081507
},
15091508
Requests: corev1.ResourceList{
15101509
corev1.ResourceCPU: resource.MustParse("12"),
@@ -1561,7 +1560,7 @@ func TestAssignFlavors(t *testing.T) {
15611560
corev1.ResourceCPU: {Name: "one", Mode: Preempt, TriedFlavorIdx: 0},
15621561
},
15631562
Status: &Status{
1564-
reasons: []string{"insufficient unused quota in cohort for cpu in flavor one, 10 more needed"},
1563+
reasons: []string{"insufficient unused quota for cpu in flavor one, 10 more needed"},
15651564
},
15661565
Requests: corev1.ResourceList{
15671566
corev1.ResourceCPU: resource.MustParse("12"),
@@ -1660,7 +1659,7 @@ func TestAssignFlavors(t *testing.T) {
16601659
{
16611660
Name: "main",
16621661
Status: &Status{
1663-
reasons: []string{"insufficient unused quota in cohort for cpu in flavor one, 11 more needed"},
1662+
reasons: []string{"insufficient quota for cpu in flavor one, request > maximum capacity (12 > 11)"},
16641663
},
16651664
Requests: corev1.ResourceList{
16661665
corev1.ResourceCPU: resource.MustParse("12"),
@@ -1813,7 +1812,7 @@ func TestAssignFlavors(t *testing.T) {
18131812
corev1.ResourcePods: resource.MustParse("1"),
18141813
},
18151814
Status: &Status{
1816-
reasons: []string{"insufficient unused quota in cohort for cpu in flavor one, 1 more needed"},
1815+
reasons: []string{"insufficient unused quota for cpu in flavor one, 1 more needed"},
18171816
},
18181817
Count: 1,
18191818
}},
@@ -1861,7 +1860,7 @@ func TestAssignFlavors(t *testing.T) {
18611860
corev1.ResourceCPU: {Name: "one", Mode: Preempt, TriedFlavorIdx: 0},
18621861
},
18631862
Status: &Status{
1864-
reasons: []string{"insufficient unused quota in cohort for cpu in flavor one, 10 more needed"},
1863+
reasons: []string{"insufficient unused quota for cpu in flavor one, 10 more needed"},
18651864
},
18661865
Requests: corev1.ResourceList{
18671866
corev1.ResourceCPU: resource.MustParse("12"),

test/integration/scheduler/fairsharing/fair_sharing_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ var _ = ginkgo.Describe("Scheduler", func() {
176176
Type: kueue.WorkloadQuotaReserved,
177177
Status: metav1.ConditionFalse,
178178
Reason: "Pending",
179-
Message: "couldn't assign flavors to pod set main: insufficient unused quota in cohort for cpu in flavor default, 2 more needed",
179+
Message: "couldn't assign flavors to pod set main: insufficient quota for cpu in flavor default, request > maximum capacity (10 > 8)",
180180
}, util.IgnoreConditionTimestampsAndObservedGeneration),
181181
))
182182
}, util.Timeout, util.Interval).Should(gomega.Succeed())

test/integration/scheduler/scheduler_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2421,7 +2421,7 @@ var _ = ginkgo.Describe("Scheduler", func() {
24212421
Type: kueue.WorkloadQuotaReserved,
24222422
Status: metav1.ConditionFalse,
24232423
Reason: "Pending",
2424-
Message: "couldn't assign flavors to pod set main: insufficient unused quota in cohort for memory in flavor on-demand, 1Gi more needed",
2424+
Message: "couldn't assign flavors to pod set main: insufficient unused quota for memory in flavor on-demand, 1Gi more needed",
24252425
}, util.IgnoreConditionTimestampsAndObservedGeneration),
24262426
))
24272427
}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -2463,7 +2463,7 @@ var _ = ginkgo.Describe("Scheduler", func() {
24632463
Type: kueue.WorkloadQuotaReserved,
24642464
Status: metav1.ConditionFalse,
24652465
Reason: "Pending",
2466-
Message: "couldn't assign flavors to pod set main: insufficient unused quota in cohort for memory in flavor on-demand, 1Gi more needed",
2466+
Message: "couldn't assign flavors to pod set main: insufficient unused quota for memory in flavor on-demand, 1Gi more needed",
24672467
}, util.IgnoreConditionTimestampsAndObservedGeneration),
24682468
))
24692469
}, util.Timeout, util.Interval).Should(gomega.Succeed())

0 commit comments

Comments
 (0)