Add a new `bindingTimeout` field to DynamicResources plugin args and wire it
into PreBind.
Changes:
- API: add `bindingTimeout` to DynamicResourcesArgs (staging + internal types).
- Defaults: default to 600 seconds when BOTH DRADeviceBindingConditions and
DRAResourceClaimDeviceStatus are enabled.
- Validation: require >= 1s; forbid when either feature gate is disabled.
- Plugin: plumbs args into `pl.bindingTimeout` and uses it in
`wait.PollUntilContextTimeout` for binding-condition wait logic.
- Plugin: remove legacy `BindingTimeoutDefaultSeconds`.
Tests:
- Add/adjust unit tests for validation and PreBind timeout path.
- Ensure <1s and negative values are rejected; forbids when gates disabled.
The cache and scheduler event handlers cannot be registered separately in the
informer, that leads to a race (scheduler might schedule based on event before
cache is updated). Chaining event handlers (cache first, then scheduler) avoids
this.
This also ensures that the cache is up-to-date before the scheduler
starts (HasSynced of the handler registration for the cache is checked).
Other changes:
- renamed package to avoid clash with other "cache" packages
- clarified nil handling
- feature gate check before instantiating the cache
- per-test logging
- utilruntime.HandleErrorWithLogger
- simpler cache.DeletedFinalStateUnknown
Signed-off-by: Sai Ramesh Vanka <svanka@redhat.com>
class mapping
- Add a new interface "DeviceClassResolver" in the scheduler framework
- Add a global cache of mapping between the extended resource and the
device class
- Cache can be leveraged by the k8s api-server, controller-manager along with the scheduler
- This change helps in delegating the requests to the dynamicresource
plugin based on the mapping during the node update events and thus
avoiding an extra scheduling cycle
Signed-off-by: Sai Ramesh Vanka <svanka@redhat.com>
The taint toleration plugin records taint keys and values
from non-matching nodes. Taint keys and values may be
sensitive information in some environments.
Use a generic message, and show the info in logs instead.
Previously, the scheduler assumed an extended resource was maintained
by a device plugin if its name was present in the node's Allocatable
map, even if its value was zero. This blocked scheduling when a device
plugin was disconnected or uninstalled, because Kubelet still reported
the resource with Allocatable=0.
This change adds a check for the actual allocatable value in addition
to a key presence check, allowing nodes with uninstalled device
plugins to be considered for scheduling.
The core functionality was enabled by default in 1.34 without any issues that
would have suggested turning it off, so now we can lock it to on-by-default.
Tests which cover disabling the feature must use version emulation.
This prevents the mistake from 1.34 where the default-on
DRAResourceClaimDeviceStatus feature caused the use of the experimental
allocator implementation. The test fails without a fix for that.
In 1.34, the default feature gate selection picked the "experimental" allocator
implementation when it should have used the "incubating" allocator. No harm
came from that because the experimental allocator has all the necessary if
checks to disable the extra code and no bugs were introduced when implementing
it, but it means that our safety net wasn't there when we expected it to be.
The reason is that the "DRAResourceClaimDeviceStatus" feature gate is on by
default and was only listed as supported by the experimental implementation.
This could be fixed by listing it as supported also by the other
implementation, but that would be a bit odd because there is nothing to support
for it (the reason why this was missed in 1.34!). Instead, the allocator
features are now only indirectly related to feature gates, with a single
boolean controlling the implementation of binding conditions.
Copying from feature.Features to new fields in the plugin got a bit silly with
the long list of features that we have now. Embedding feature.Features is
simpler.
Two fields in feature.Features weren't named according to the feature gate, now
they are named consistently and the fields are sorted.
Currently volume and dynamic-resource plugin shares an AssumeCache
implementation. However, they features significantly different use case. DRA
call Assume() on objects returned by APIServer, but volume call Assume() on
objects yet to be sent to the APIServer.
VolumeBinding plugin only makes one update request, while DynamicResource makes
2 requests (add finalizer then update allocation status). Taking advantage of
this, currently the volume cache is simpler:
1. Reserve: assume PV/PVC will be updated
2. PreBind: really send the update request
3. AssumeCache receives an update from informer and overwrite the assumed state.
a. if Prebind succeeded, this will surely include the update from step 2.
b. if PreBind is not finished yet, and this is an irrelevant update, it is safe to
overwrite the assumed state, because our update in PreBind will surely fail with Conflict.
While for DynamicResource:
1. Reserve: add devices to inFlightAllocations
2. PreBind:
a. send the 2 update requests
b. add the returned object into AssumeCache
c. AssumeCache dispatch events synchronously to update allocatedDevices
d. remove devices from inFlightAllocations
DynamicResource needs some features from AssumeCache that is not necessary for VolumeBinding:
1. DynamicResource needs strictly ordered update events to update allocatedDevices,
including those from Assume() and Restore()
2. DynamicResource needs to compare ResourceVersion to prevent the assumed state from being
overwritten by older version from informer. While this works, the doc[1] says:
"you must not compare resource versions for greater-than or less-than relationships".
Given so much difference, it can be beneficial to fork another simpler
AssumeCache for VolumeBinding plugin. Because of no need to send events, the
lite AssumeCache is a passive component. It only record the assumed version
without copying all objects from informer into its local cache. When reading,
we read from both informer and local cache. So it will always be up-to-date
with informer, no need to wait for event handler.
This resolves a race condition where AssumeCache and scheduler queue both
receive events from informer. When a pod is scheduling due to PV update event,
the PVCache may be not updated yet because it has not processed the relevant
event.
The passive version still listens events from informer, but only for cleaning up
its local cache to save memory.
[1]: https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions