-
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
Fix a bug that out-of-tree plugin is misplaced when using scheduler v1beta3 config #108613
Conversation
@Huang-Wei: This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the The 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. |
/retest |
With this PR, any testing plugin will be appended (not prepend) to the default plugins, that caused an integration test failure cuz DefaultBind would fail (due to the testing context), that failed the pod's scheduling as well as further TestBind plugin's execution. |
/retest |
newPlugins := reflect.New(reflect.TypeOf(e.slicePtr).Elem()).Elem() | ||
// part 1 | ||
deletionCnt := 0 | ||
for i, name := range enabledSet.list { |
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.
In Golang, the iteration order of a map is uncertain, and thus this PR introduces an orderedSet.
Another alternative is to use slice to replace enabledSet, but in that case, we need extra logic to deal with duplicated plugins.
@damemi This PR is ready for review. |
|
||
newPlugins := reflect.Append(plugins, reflect.ValueOf(pg)) | ||
plugins.Set(newPlugins) | ||
} | ||
|
||
// Reorder plugins if needed. Here is the expected order: |
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 seems like we rearrange all the plugin orders here. So when len(profile.Plugins.MultiPoint.Enabled) > 0
, we no longer need above updatePluginList
process anymore, right? If this makes sense, we should merge them together.
kubernetes/pkg/scheduler/framework/runtime/framework.go
Lines 334 to 338 in e9af399
for _, e := range f.getExtensionPoints(profile.Plugins) { | |
if err := updatePluginList(e.slicePtr, *e.plugins, pluginsMap); err != nil { | |
return nil, err | |
} | |
} |
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 still prefer to keep them separate. When len(profile.Plugins.MultiPoint.Enabled) > 0
, it's not necessarily going to rearrange the plugins - e.g., all plugins defined in multipoint has been specified (say reconfigured) in the regular extension point.
Thanks for working on this @Huang-Wei, I will take add some review soon when I have a moment |
enabledSet.delete(name) | ||
} | ||
} | ||
// enabledSet.isEmpty() implies part 3 is empty, so don't need to continue |
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.
If I understood correctly, we can harmless remove https://github.com/kubernetes/kubernetes/blob/8ef5ccdad6bba8b664b51a8b29fd1a5ce396a59d/pkg/scheduler/framework/runtime/framework.go#L532-L535 and
kubernetes/pkg/scheduler/framework/runtime/framework.go
Lines 480 to 481 in 897f2f7
newPlugins := reflect.Append(plugins, reflect.ValueOf(pg)) | |
plugins.Set(newPlugins) |
After removal, program still behaves the same but more clearly to read. Separate the reading and writing process.
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.
SG. It reads better.
c856910
to
912f320
Compare
/retest |
t.Fatal(err) | ||
} | ||
|
||
// plugin config |
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.
nit: replace with out-of-tree plugin config v1beta2
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.
will update along with other comments.
plugins.Set(newPlugins) | ||
// Reorder plugins. Here is the expected order: | ||
// - part 1: overridePlugins. Their order stay intact as how they're specified in regular extension point. | ||
// - part 2: multiPointEnabled - i.e., plugin defined in multipoint but not overriding regular extension point. |
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.
s/not overriding/not overrided by/
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.
not really, it's the multi-point plugin overriding others instead of the other way around.
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.
Aren't both correct? This is the set of multipoint plugins that aren't overriding (ie, not in part 1) but also they aren't being overridden (otherwise, they would be in part 1 as their overridden config). Part 1 includes explicitly reconfigured multiPoint plugins right?
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.
Correct, it's bi-directional. This may lead to less ambiguity?
// - part 2: multiPointEnabled - i.e., plugins defined in multipoint but not in regular extension point.
Some nits, then LGTM. Left for @damemi for a further review. |
/retest |
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.
Looks good to me overall. I think breaking the logic out into 3 distinct sets makes it a bit clearer how the precedence works
/approve
} | ||
|
||
func newOrderedSet() *orderedSet { | ||
return &orderedSet{set: make(map[string]int)} |
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.
do you need to initialize the list
too?
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.
A nil slice is functionally equivalent to a zero-length slice. If we won't gone to use Marshal
and reflect. DeepEqual
with this field, freely to us. So I think we can omit it here.
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.
yup, we usually don't need to initialize a slice. And in terms of using a slice: var s []string
are in favor of s := []string
.
@@ -656,6 +656,44 @@ func TestNewFrameworkMultiPointExpansion(t *testing.T) { | |||
PostBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, | |||
}, | |||
}, | |||
{ | |||
name: "Reorder MultiPoint plugins (specified extension only takes precedence when it exists in MultiPoint)", |
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 think this test covers the mix of use cases well
plugins.Set(newPlugins) | ||
// Reorder plugins. Here is the expected order: | ||
// - part 1: overridePlugins. Their order stay intact as how they're specified in regular extension point. | ||
// - part 2: multiPointEnabled - i.e., plugin defined in multipoint but not overriding regular extension point. |
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.
Aren't both correct? This is the set of multipoint plugins that aren't overriding (ie, not in part 1) but also they aren't being overridden (otherwise, they would be in part 1 as their overridden config). Part 1 includes explicitly reconfigured multiPoint plugins right?
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: damemi, Huang-Wei 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 |
912f320
to
b74574f
Compare
Commits squashed. @damemi please take a another look when you get a chance. |
@damemi could you please take another look? |
Sorry @Huang-Wei, I only had those 2 nits. The rest looks good, thanks for fixing this |
/retest |
We should rebase the code as we changed the |
The Kubernetes project has merge-blocking tests that are currently too flaky to consistently pass. This bot retests PRs for certain kubernetes repos according to the following rules:
You can:
/retest |
b74574f
to
d82ff1d
Compare
d82ff1d
to
d330f4d
Compare
/lgtm Thanks. @Huang-Wei |
/retest |
…08613-upstream-release-1.23 Automated cherry pick of #108613: Fix a bug that out-of-tree plugin is misplaced when using
What type of PR is this?
/kind bug
/sig scheduling
What this PR does / why we need it:
When custom plugins are specified via regular extension points in v1beta3, the current logic places them at the head,, and then appends internal default plugins (in
expandMultiPointPlugins()
).However, the eventual order should be like this:
This PR changes the logic of
expandMultiPointPlugins()
to order the plugins when necessary.Which issue(s) this PR fixes:
Fixes #108083
Special notes for your reviewer:
Does this PR introduce a user-facing change?