-
Notifications
You must be signed in to change notification settings - Fork 38.7k
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
feat: implement "queue-sort" extension point for scheduling framework #77529
feat: implement "queue-sort" extension point for scheduling framework #77529
Conversation
/assign @bsalamat @misterikkit This is a preliminary implementation for scheduling framework. I'll add more unit tests after the design is good to go :) |
2df3136
to
57f14f5
Compare
type QueueSortPlugin interface { | ||
Plugin | ||
// Less are used to sort pods in the scheduling queue. | ||
Less(*internalqueue.PodInfo, *internalqueue.PodInfo) bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it better to name it Sort
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed the KEP definition:
These plugins are used to sort pods in the scheduling queue. A queue sort plugin essentially will provide a "less(pod1, pod2)" function. Only one queue sort plugin may be enabled at a time.
And the sort package in golang also prefers Less
in this scenario, e.g. func Slice(slice interface{}, less func(i, j int) bool)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All right, understand.
type QueueSortPlugin interface { | ||
Plugin | ||
// Less are used to sort pods in the scheduling queue. | ||
Less(*internalqueue.PodInfo, *internalqueue.PodInfo) bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plugins will not be able to use internalqueue.PodInfo if they import scheduler's code. We should probably move PodInfo outside of the internal.
cc/ @misterikkit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could move the PodInfo
into this file if it is appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels a bit odd to move PodInfo here, but since we want plugins to use it, I guess we don't have any other option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
out of the scope of this pr, but @bsalamat does the same logic apply for NodeInfoSnapshot
used here, which is also under internal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels a bit odd to move PodInfo here, but since we want plugins to use it, I guess we don't have any other option.
Moved LessFunc and PodInfo to the framework interface. PTAL
/retest |
de393e4
to
39b37cb
Compare
/retest |
} | ||
|
||
// only active one at a time. | ||
return f.queueSortPlugins[0].Less |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative to this approach is to support multiple plugins for QueueSort. We could rename Less
function to Cmp
and let it return -1, 0, or 1. A returned 0 means that the values are equal. In that case, we can call the next plugin Cmp until one returns non-zero. For now, I think we can stay with the current implementation.
d9ae14d
to
58ceeda
Compare
58ceeda
to
d60bccc
Compare
/test pull-kubernetes-dependencies |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
/approve
Thanks, @draveness!
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: bsalamat, draveness 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 |
/retest |
@draveness: The following test failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
@@ -69,6 +70,10 @@ func NewFramework(r Registry, _ *runtime.Unknown) (Framework, error) { | |||
// TODO: For now, we assume any plugins that implements an extension | |||
// point wants to be called at that extension point. We should change this | |||
// later and add these plugins based on the configuration. | |||
if qsp, ok := p.(QueueSortPlugin); ok { | |||
f.queueSortPlugins = append(f.queueSortPlugins, qsp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the current implementation, when len(f.queueSortPlugins) reaches 1, we don't need to append more plugin.
Not sure if this is this PR, but I've noticed this flake:
|
Interestingly, I haven't been able to reproduce this flake (still I think it should be looked at it looks pretty bad). I managed to trigger another one though:
|
It seems like there is no difference if we pass a nil framework into the initialiser which both cases indeed passed nil. So we can not get into the if branch. comp := activeQComp
if fwk != nil {
if queueSortFunc := fwk.QueueSortFunc(); queueSortFunc != nil {
comp = func(podInfo1, podInfo2 interface{}) bool {
pInfo1 := podInfo1.(*framework.PodInfo)
pInfo2 := podInfo2.(*framework.PodInfo)
return queueSortFunc(pInfo1, pInfo2)
}
}
} Could you give me some inputs on how to trigger the failure of |
That should trigger the failure pretty quickly |
There's some problem with bazel on my laptop. I ran the tests 100 times with $ go test ./pkg/scheduler/internal/queue/... -count=100
ok k8s.io/kubernetes/pkg/scheduler/internal/queue 191.594s |
Using bazel, it is easy to reproduce: |
I revert the commit, and the test fails the same. I'll open a flaky test issue. #78064 |
Thanks for tracking this! Have you opened an issue for the race condition or managed to investigate it? |
No, I didn't open an issue for the race condition problem. Do you have links to failing CI jobs? |
The one described in #77529 (comment). A race condition could also be responsible for the other error. |
Tried the following:
The test still fails with bazel |
What type of PR is this?
/kind feature
/priority important-soon
/sig scheduling
What this PR does / why we need it:
Implement "queue-sort" extension point for scheduling framework
Which issue(s) this PR fixes:
Fixes #77524
KEP: kubernetes/enhancements#624
Does this PR introduce a user-facing change?: