-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
KEP-5027 + 5055: DRA: admin-controlled device attributes + device taints #5034
base: master
Are you sure you want to change the base?
Conversation
/cc @KobayashiD27 For the "device priority" use case. /cc @byako For device health. |
@pohly: GitHub didn't allow me to request PR reviews from the following users: KobayashiD27. Note that only kubernetes members and repo collaborators can review this PR, and authors cannot review their own PRs. In response to this:
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-sigs/prow repository. |
keps/sig-node/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
/wg device-management |
keps/sig-node/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
keps/sig-node/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
531a905
to
cddc84f
Compare
cddc84f
to
c4a6f66
Compare
These are two different KEPs that provide two features that can be enabled and disabled independently. However, both use the same new ResourceSliceOverride type and thus get described and implemented together.
c4a6f66
to
41cdbf5
Compare
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.
There was earlier discussion of common (driver independent) tool(ing) for listing, adding and removing device taints. Would it make sense to mention something about that in the tainting KEP?
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 deeply appreciated for your quick action for device taints/tolerations KEP!! I left some comments. PTAL.
keps/sig-node/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
If a CEL expression fails for a device, the override does not apply and an | ||
event will be generated for the ResourceSlicePatch with the faulty CEL | ||
expression. |
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.
Does "fail" in this context mean an invalid CEL expression caused by something like a syntax error, and not that it cleanly evaluates to false
?
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.
"fails to evaluate to a boolean (runtime error, wrong result type)".
Syntax errors are caught during validation, but the attribute lookup is not type safe (devices.attributes[...].someField
may or may not be a bool) and can cause key lookup exceptions (in this case, if someField
isn't matching some attribute).
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 updated the paragraph.
keps/sig-scheduling/5055-device-taints-and-tolerations/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Show resolved
Hide resolved
// satisfied by a device to be patched. | ||
// | ||
// +optional | ||
DeviceClass *string |
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 worth naming this DeviceClassName
to be consistent with that field in ResourceClaims?
Also perhaps Pool
-> PoolName
?
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.
Yes, it should be consistent, and thus DeviceClassName
.
But driver, pool, and device are referred to without the Name
suffix (https://github.com/kubernetes/kubernetes/blob/03bf94bac074ce43228ee906a8cadea6176873c0/staging/src/k8s.io/api/resource/v1beta1/types.go#L1012-L1035).
This is based on an API guideline which says "use *Name only for API objects". DeviceClass is an API object, "pool" isn't. I personally would have preferred "DriverName" instead of "Driver" because there is a difference between a "driver" (the thing, perhaps described by a struct) and a "driver name" (one particular attribute of it) and and had that in initial revisions of the API, but was told to remove the suffix for the sake of consistency with other APIs.
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.
Hrrm. "DeviceClassName" next to "Driver/Pool/Device" looks odd. Not sure what a good solution is here. Also, suppose we do add a "resource.Driver" type similar to "storage.CSIDriver". Then "DriverName" suddenly would become more suitable than "Driver". Still not a fan of this API convention.... 🤷
I'm going with "consistent with other fields" for now, but we may have to revisit as part of the final API review.
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've also added comments that explain what those other fields are.
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Show resolved
Hide resolved
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Show resolved
Hide resolved
keps/sig-scheduling/5055-device-taints-and-tolerations/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5055-device-taints-and-tolerations/README.md
Outdated
Show resolved
Hide resolved
|
||
The other usage is to influence which devices are picked when there are | ||
multiple viable alternatives. This is a first step towards providing a more | ||
comprehensive [scoring](https://github.com/kubernetes/enhancements/issues/4970) |
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.
Can we add more information on how scoring can be achieved?
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 need to remove this and the preceeding paragraph. Device priority is no longer part of this KEP and health is a separate one now.
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.
Done.
--> | ||
|
||
One E2E test scenario is to mark all devices as offline and then verify that | ||
pods don't get scheduled. Another is to set different priorities and check that |
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.
based on this comment E2E tests also needs to be changed.
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.
Thanks for the reminder. Fixed.
This gets added for the sake of completeness.
keps/sig-scheduling/5055-device-taints-and-tolerations/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5055-device-taints-and-tolerations/README.md
Outdated
Show resolved
Hide resolved
// In contrast to attributes in a ResourceSlice, entries here are allowed to | ||
// be marked as empty by setting their null field. Such entries remove the | ||
// corresponding attribute in a ResourceSlice, if there is one, instead of | ||
// overriding it. |
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 worth enforcing that null cannot be set in a ResourceSlice? If it's allowed, that would leave the option open for drivers to do so in case they want to communicate some nuance like "I think users may expect this attribute to exist, but it intentionally does not."
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 that's too nuanced and adds one more thing that users writing CEL expressions would have to be prepared for, in addition to the "can I access this attribute without getting a lookup error".
// NullValue, if set, marks an intentionally empty attribute. | ||
// | ||
// May be used inside a ResourceSlicePatch to remove attributes, | ||
// but not in a ResourceSlice. | ||
// | ||
// +optional | ||
// +oneOf=ValueType | ||
NullValue *NullValue `json:"null,omitempty"` |
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 the CEL environment, will null values be omitted entirely from the device.attributes
map if we don't handle them specially? If not, enabling that might be worthwhile since I can see that being a little more ergonomic for authors of CEL expressions than if they have to handle "explicit null" and "actually undefined" differently.
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 guess my question here boils down to "how does a Go map with a value of nil
manifest in the CEL environment, and is that different from a Go map without that key/value pair at all?"
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.
Because ResourceSlices contain no null values and null values in a ResourceSlicePatch cause the attribute to be removed, there's never a situation where a CEL expression gets a null value when looking up an attribute. That is deliberate: we already have "attribute not set in map", we don't need "attribute set with null value". That is semantically so close that I don't see the need.
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
// ^^^^ | ||
// The assumption here is that all device types will have attributes and capacities, | ||
// similar to the current BasicDevice type. Therefore the overrides are not made | ||
// specific to certain device types. | ||
} | ||
|
||
// DevicePatchFilter defines which device(s) a [DevicePatch] applies to. | ||
type DevicePatchFilter struct { |
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 may be something out of the scope of this KEP, can an external controller add a selector that can be later consumed by the machinery described in the KEP?
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.
This touches on the question whether DevicePatchFilter
is immutable: it isn't, so whenever a selector gets added or removed, it changes how the scheduler evaluates the patch.
The machinery in this KEP doesn't care who does the updating, so it could be a controller.
Creating a ResourceSlicePatch is racing with on-going scheduling attempts, | ||
which is unavoidable. |
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.
Just for my own understanding, is the worst-case scenario here something like this?
- A Pod comes into the scheduler and a ResourceSlicePatch is created at the same time.
- The scheduler successfully schedules the Pod, having not yet observed the new ResourceSlicePatch.
- The ResourceSlicePatch makes modifications such that the Pod's ResourceClaims no longer match the devices it was allocated (e.g. changing an attribute referenced in a selector).
- The scheduled Pod continues to run with the unsuitable allocated device.
And does this same race condition already exist today when updating ResourceSlices since the scheduler's view of ResourceSlices is driven by an informer?
Is the "correct" answer to this to use only taints instead of attributes/capacity for anything that should cause a Pod to be evicted at runtime?
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.
Your understanding is correct, on all points.
// ^^^ | ||
// `NullableDeviceAttribute` as an extension ensures that the OpenAPI | ||
// for ResourceSlice remains unchanged. Using the same type with | ||
// a `NullValue` that can be set only in one type is less clear. |
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.
@aaron-prindle: will a NullableDeviceAttribute with some "oneOf" alternatives inside the embedded DeviceAttribute and one more outside of it work for declarative validation?
It should work right now (OpenAPI flattens embedded structs) and it is more natural in Go (can use a NullableDeviceAttribute to initialize a DeviceAttribute without manually written copy code).
But if this then poses a problem for declarative validation, then it will be difficult to switch because the embedding leads to different protobuf encoding.
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.
Given how early declarative validation is, I feel confident saying "we can make it work". I don't think it is something we handle in the dev-branch prototype, but it seems reasonably well defined.
What you're doing here isn't obvious at first blush (even I started writing an alternative), but this comes back to a hard-learned lesson: Don't make "nothing" mean something. The absence of a value in a patch cannot mean "remove", it has to mean "don't know".
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.
Yes, exactly, hence the explicit "null". One alternative in a prior comment thread in this PR was an explicit remove: true
(but then what does remove: false
mean?) or remove: {}
.
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 reference: this idea originated in #5034 (comment)
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Show resolved
Hide resolved
keps/sig-scheduling/5055-device-taints-and-tolerations/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5055-device-taints-and-tolerations/README.md
Outdated
Show resolved
Hide resolved
Taints are cumulative as long as the key and effect pairs are different: | ||
- Taints defined by an admin in a ResourceSliceOverride get added to the | ||
set of taints defined by the DRA driver in a ResourceSlice. | ||
- Taints with the same key and effect get overwritten, using the same | ||
precedence as for attributes. |
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.
Don't we want to allow to delete the taints?
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.
Maybe? So the goal is to let the driver set a taint and then the admin decides that "no, this this taint shouldn't really taint the device"?
Let's see what an API for that could look like... What if we allowed an effect called "None"? Then a driver can publish a taint {Key: dra.example.com/temperature, Value: 200, Effect: NoExecute}
and an admin can replace that with {Key: dra.example.com/temperature, Value: 0, Effect: None}
.
The scheduler and eviction controller ignore such taints with "no effect". The difference is that Effect: None
replaces other taints with the same key during patching, instead of adding the taint to the set.
I'm not sure whether it makes sense, but I would also allow such entries in a ResourceSlice.
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 general, I think actors on the taints should act only on their own taints, but naturally they should be able to remove those taints when they are not relevant any more.
Eg. after admin has finished upgrading the device firmware, and verified its working with a test pod tolerating the FirmwareUpgrade
taint, he should be able to remove that taint so that other pods can again be scheduled on the upgraded device.
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.
The comment here is about ResourceSlicePatch and how it relates to taints in the ResourceSlice ("cumulative").
Of course each actor can and should remove their own taint. That's so normal, I didn't even bother mentioning that in the KEP 😅 Should I?
So do we not need the ability for an admin to modify some device taint set by the driver?
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 driver has not set any taint yet, how k8s would know that admin patches a taint that driver is "supposed" to manage? Or was your question about admin masking out ("removing") a taint set by the driver?
I would assume allowing these would be simpler. It would be nice if (some future) k8s tool for setting device taints would give a warning if driver has already set the specified taint, but I think its fine to allow it (-force).
Disallowing it would be fine too though. If driver adds taint that admin does not care about, admin could always use taint toleration. And maybe drivers could include options for disabling tainting, in case admin wants something else to handle that.
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.
Or was your question about admin masking out ("removing") a taint set by the driver?
This thread here is about admins deleting taints set be a driver. The way the API is defined right now, an admin can add its own taint, but they cannot remove a taint set by a driver ("cumulative"). If we want to allow that, we need a special API for it. #5034 (comment) is an attempt to define such an API.
As with node taints, the key is typically a short string. The meaning of the value | ||
depends on the key. It is allowed to be longer. The core v1 API does not impose | ||
length limitations for these fields. The `resource.k8s.io` API does. |
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.
Should the proposed length limitations be a part of the KEP?
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 was wrong and already removed this: the core API uses the validation for label names and keys and thus has length limits. They are just not documented specifically for the taint API.
I think that makes sense because defining "label name" and "label key" in all APIs that use them would be very repetitive. Therefore I have done the same here and only said that the strings must be label names and keys.
What is missing in the KEP is a specification of how many taints per device and patch are allowed. I think each taint is relatively small compared to the potentially large attributes, so how about we allow 16?
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.
While taints may differ between devices, I do not see single device having that many different taints. Possibly few error metric taints from driver, couple of admin taints and potentially several metric related taints. If device collects half a dozen taints before it gets decommissioned, that seems rather problematic device to keep in use...
It's possible that taint names change with time though, and some devices in large & old clusters could have eventually collected set of taints with obsolete names. Such things should not prevent device getting relevant taints. 16 should be way more that enough for that though.
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 agree that a few (3-4 at most) seems likely, perhaps even just one. 16 is meant to provide some buffer for unexpected usages.
keps/sig-scheduling/5055-device-taints-and-tolerations/README.md
Outdated
Show resolved
Hide resolved
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Outdated
Show resolved
Hide resolved
I just finished a full pass over both README.md while @macsko was reviewing. I need to double-check whether I addressed some of his comments already. @johnbelamaric: I also filled out the required PRR sections. |
keps/sig-scheduling/5027-dra-admin-controlled-device-attributes/README.md
Show resolved
Hide resolved
both cases it starts with listing all devices. That information is local can | ||
comes either from an informer cache or a cache of patched devices. |
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.
Should this read as something like this?
both cases it starts with listing all devices. That information is local can | |
comes either from an informer cache or a cache of patched devices. | |
both cases it starts with listing all devices. That information is local and | |
comes either from an informer cache or a cache of patched devices. |
Filtering and patching are local operations, with no impact on the cluster. To | ||
prevent doing the same work repeatedly, it will be implemented so that it gets | ||
done once and then only processes changes. This increases CPU and RAM | ||
consumption. But even all devices should get patched (which is unlikely), memory |
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.
Similarly here?
consumption. But even all devices should get patched (which is unlikely), memory | |
consumption. But even if all devices should get patched (which is unlikely), memory |
Patching attributes dynamically sounds like a good idea, but I wonder if there is a similar mechanism already implemented in k8s? I haven't found any, so I wonder whether it wasn't needed, or just no one did it this way. My only worry is that this approach brings quite a lot complexity, especially since these overrides have to be consumed in unknown number of places. Do you think that the benefit of updating multiple objects at once is a sufficient argument? Why patching the objects in the background is not acceptable (even when keeping the Alternatively, shouldn't such mechanism become a part of the framework, so that components get objects with already applied patches in informers? |
One-line PR description: DRA: admin-controlled device attributes + device attributes
Issue links:
Other comments: first revision
/cc @johnbelamaric