Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix pending workload from StrictFIFO CQ doesn't block borrowing from other CQ #1399

Merged
merged 1 commit into from
Jan 10, 2024

Conversation

yaroslava-serdiuk
Copy link
Contributor

@yaroslava-serdiuk yaroslava-serdiuk commented Dec 4, 2023

Which issue(s) this PR fixes:

related to #1283

Does this PR introduce a user-facing change?

Pending workload from StrictFIFO ClusterQueue doesn't block borrowing from other ClusterQueues

@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. kind/feature Categorizes issue or PR as related to a new feature. labels Dec 4, 2023
@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Dec 4, 2023
Copy link

netlify bot commented Dec 4, 2023

Deploy Preview for kubernetes-sigs-kueue canceled.

Name Link
🔨 Latest commit 380ad7d
🔍 Latest deploy log https://app.netlify.com/sites/kubernetes-sigs-kueue/deploys/659ef7abd75eff00097db422

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. release-note-none Denotes a PR that doesn't merit a release note. and removed release-note Denotes a PR that will be considered when it comes time to generate release notes. labels Dec 4, 2023
@yaroslava-serdiuk yaroslava-serdiuk changed the title WIP: Add feature gate for priorities sorting in a cohort WIP: Scheduler test Dec 5, 2023
@alculquicondor
Copy link
Contributor

/cc

test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Show resolved Hide resolved
@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 15, 2023
@yaroslava-serdiuk yaroslava-serdiuk changed the title WIP: Scheduler test Make sure pending workload strictFIFO doesn't block borrowing from other CQ Jan 3, 2024
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jan 3, 2024
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 3, 2024
@yaroslava-serdiuk yaroslava-serdiuk force-pushed the scheduler-test branch 2 times, most recently from 4912c7e to 0658449 Compare January 3, 2024 21:51
@yaroslava-serdiuk yaroslava-serdiuk changed the title Make sure pending workload strictFIFO doesn't block borrowing from other CQ Make sure pending workload from StrictFIFO CQ doesn't block borrowing from other CQ Jan 3, 2024
@yaroslava-serdiuk
Copy link
Contributor Author

/assign @alculquicondor

@alculquicondor
Copy link
Contributor

This definitely requires a release note.

Copy link
Contributor

@alculquicondor alculquicondor left a comment

Choose a reason for hiding this comment

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

We should also have unit test coverage for the new logic

pkg/scheduler/flavorassigner/flavorassigner.go Outdated Show resolved Hide resolved
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
pkg/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Show resolved Hide resolved
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
Comment on lines 332 to 337
if cqFlavor.Name == flavor {
cqQuota = cqFlavor.Resources
}
Copy link
Member

Choose a reason for hiding this comment

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

@alculquicondor In this implementation, the cqQuota will have only the last flavor's resources, right?
So, should we add all resources to the cqQuota?

if cqFlavor.Name == flavor {
    for name, quota := range cqFlavor.Resources {
        cqQuota[name] = quota
    }
}

(This is a pseudo code.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My bad, you're right. Should be fixed now.

@yaroslava-serdiuk
Copy link
Contributor Author

/remove-kind feature
/kind bug

@k8s-ci-robot k8s-ci-robot added kind/bug Categorizes issue or PR as related to a bug. and removed kind/feature Categorizes issue or PR as related to a new feature. labels Jan 10, 2024
@yaroslava-serdiuk yaroslava-serdiuk changed the title Make sure pending workload from StrictFIFO CQ doesn't block borrowing from other CQ Fix pending workload from StrictFIFO CQ doesn't block borrowing from other CQ Jan 10, 2024
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
test/integration/scheduler/scheduler_test.go Show resolved Hide resolved
@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 10, 2024
Copy link
Contributor Author

@yaroslava-serdiuk yaroslava-serdiuk left a comment

Choose a reason for hiding this comment

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

Updated reservedResources if CQ is borrowing

pkg/scheduler/scheduler.go Outdated Show resolved Hide resolved
@@ -1894,3 +1904,81 @@ func TestRequeueAndUpdate(t *testing.T) {
})
}
}

func TestResourcesToReserve(t *testing.T) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TestSchedule test quite complex logic. I've added integration tests to test the full functionality

test/integration/scheduler/scheduler_test.go Show resolved Hide resolved
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 10, 2024
reservedUsage[flavor][resource] = min(usage, cqQuota.Nominal-cq.Usage[flavor][resource])
} else if cqQuota.BorrowingLimit != nil {
// if cq is borrowing, cq usage can't exceed nominal + borrowing limit
reservedUsage[flavor][resource] = min(usage, cqQuota.Nominal+*cqQuota.BorrowingLimit-cq.Usage[flavor][resource])
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't want to block up to the borrowing limit. We only want to block up to nominal.

Copy link
Contributor

Choose a reason for hiding this comment

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

@mimowo what do you think should we do if borrowing with preemption? I guess we should block all of the usage in that case?

Copy link
Contributor Author

@yaroslava-serdiuk yaroslava-serdiuk Jan 10, 2024

Choose a reason for hiding this comment

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

Updated, cq usage shouldn't go over cqQuota.Nominal+*cqQuota.BorrowingLimit if borrowing limit is set

Copy link
Contributor

@mimowo mimowo Jan 11, 2024

Choose a reason for hiding this comment

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

@mimowo what do you think should we do if borrowing with preemption? I guess we should block all of the usage in that case?

TBH, I'm not sure, I'm wondering if we can simplify

if cqQuota.BorrowingLimit == nil {
  reservedUsage[flavor][resource] = usage
} else {
  reservedUsage[flavor][resource] = min(usage, cqQuota.Nominal+*cqQuota.BorrowingLimit-cq.Usage[flavor][resource])
}

to just

reservedUsage[flavor][resource] = usage

@yaroslava-serdiuk do you know a scenario when this is needed?

This looks odd to me at the moment, because in the scenario of single shared CQ as here when cqQuota.Nominal=0, then if borrowingLimit=null we reserve usage, but if borrowingLimit=nominal for the shared (essentially the same a null), and cq.Usage[flavor][resource]=borrowigLimit, then we reserve 0.

Copy link
Contributor

Choose a reason for hiding this comment

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

we shouldn't go over cqQuota.Nominal+*cqQuota.BorrowingLimit if borrowing limit is set

Correct, but this is verified already in

if (rQuota.BorrowingLimit == nil || val <= rQuota.Nominal+*rQuota.BorrowingLimit) && val <= cohortAvailable {
mode = Preempt
borrow = val > rQuota.Nominal
}
. I think it is ok to go beyond cqQuota.Nominal+*cqQuota.BorrowingLimit-cq.Usage[flavor][resource]

Copy link
Contributor Author

@yaroslava-serdiuk yaroslava-serdiuk Jan 11, 2024

Choose a reason for hiding this comment

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

Had discussion with @mimowo offline. I explained the condition:

  reservedUsage[flavor][resource] = usage
} else {
  reservedUsage[flavor][resource] = min(usage, cqQuota.Nominal+*cqQuota.BorrowingLimit-cq.Usage[flavor][resource])
}

However this is unlikely will be used, since the borrowing limit is often nil.
I also constructed example when the condition unblock another workload from borrowing:
https://github.com/kubernetes-sigs/kueue/assets/43413443/3ee2a4f6-d8ee-4bb4-96d8-2e9662e8869c

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for the sync and explanations indeed.

One thing that it let me understand is that the StrictFIFO isn't really the main point here (as the title suggests). If the queue has only one workload it does not matter what is its type. Maybe we could say in the release notes:
"Fix a bug that a preempting workload in one CQ could block another pending workload in another CQ even if the other workload could be scheduled by borrowing".

Regarding the extra condition I think it adds complexity (and the code is already complex). The scenario isn't tested currently by integration tests. Also, the importance of the scenario from the user perspective seems questionable, because it is only relevant if borrowingLimit<nominalQuota of shared CQ. I could open a PR to simplify. WDYT @alculquicondor ?

Copy link
Member

Choose a reason for hiding this comment

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

Also, the importance of the scenario from the user perspective seems questionable, because it is only relevant if borrowingLimit<nominalQuota of shared CQ.

@mimowo, Could you clarify this situation? Which does this mean, a: borrowingLimit<(nominalQuota of shared CQ) or b: (borrowingLimit<nominalQuota) of shared CQ?

If you mean a, I think a will often happen. I guess admins want to set borrowingLimit<(nominalQuota of shared CQ) in each ClusterQueue since admins want to prevent situations where one of the CQ monopolizes all shared capacity.

If my understanding is incorrect , please let me know.

Copy link
Contributor

Choose a reason for hiding this comment

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

@mimowo, Could you clarify this situation? Which does this mean, a: borrowingLimit<(nominalQuota of shared CQ) or b: (borrowingLimit<nominalQuota) of shared CQ?

I meant (a) borrowingLimit<(nominalQuota of shared CQ).

If you mean a, I think a will often happen. I guess admins want to set borrowingLimit<(nominalQuota of shared CQ) in each ClusterQueue since admins want to prevent situations where one of the CQ monopolizes all shared capacity.

Makes sense, I was thinking about the scenario as in here, but both are relevant.

So the remaining question: do we care about the scenario, that a workload that is borrowing (B) could get blocked by another workload (A) that is preempting and borrowing in the cohort. The trade-off does not seem obviousm because letting the other workload run may cause the waiting workload wait longer.

Copy link
Contributor

Choose a reason for hiding this comment

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

Feel free to open a PR

pkg/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
reservedUsage[flavor][resource] = min(usage, cqQuota.Nominal-cq.Usage[flavor][resource])
} else if cqQuota.BorrowingLimit != nil {
// if cq is borrowing, cq usage can't exceed nominal + borrowing limit
reservedUsage[flavor][resource] = min(usage, cqQuota.Nominal+*cqQuota.BorrowingLimit-cq.Usage[flavor][resource])
Copy link
Contributor

Choose a reason for hiding this comment

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

@mimowo what do you think should we do if borrowing with preemption? I guess we should block all of the usage in that case?

Comment on lines 329 to 330
for resource, usage := range resourceUsage {
reservedUsage[flavor] = make(map[corev1.ResourceName]int64)
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
for resource, usage := range resourceUsage {
reservedUsage[flavor] = make(map[corev1.ResourceName]int64)
reservedUsage[flavor] = make(map[corev1.ResourceName]int64)
for resource, usage := range resourceUsage {

test/integration/scheduler/scheduler_test.go Outdated Show resolved Hide resolved
…her CQ

Apply suggestions from code review

Co-authored-by: Aldo Culquicondor <1299064+alculquicondor@users.noreply.github.com>
@alculquicondor
Copy link
Contributor

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jan 10, 2024
@k8s-ci-robot
Copy link
Contributor

LGTM label has been added.

Git tree hash: 8f26d378f3d6b62823e674f008cb2380ff3706b4

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: alculquicondor, yaroslava-serdiuk

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jan 10, 2024
@k8s-ci-robot k8s-ci-robot merged commit eb853f1 into kubernetes-sigs:main Jan 10, 2024
14 checks passed
@k8s-ci-robot k8s-ci-robot added this to the v0.6 milestone Jan 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants