KEP-5945: DRA Optional Node Operations
KEP-5945: DRA Optional Node Operations
- Release Signoff Checklist
- Summary
- Motivation
- Proposal
- Design Details
- Production Readiness Review Questionnaire
- Implementation History
- Drawbacks
- Alternatives
Release Signoff Checklist
Items marked with (R) are required prior to targeting to a milestone / release.
- (R) Enhancement issue in release milestone, which links to KEP dir in kubernetes/enhancements (not the initial KEP PR)
- (R) KEP approvers have approved the KEP status as
implementable - (R) Design details are appropriately documented
- (R) Test plan is in place, giving consideration to SIG Architecture and SIG Testing input (including test refactors)
- e2e Tests for all Beta API Operations (endpoints)
- (R) Ensure GA e2e tests meet requirements for Conformance Tests
- (R) Minimum Two Week Window for GA e2e tests to prove flake free
- (R) Graduation criteria is in place
- (R) all GA Endpoints must be hit by Conformance Tests within one minor version of promotion to GA
- (R) Production readiness review completed
- (R) Production readiness review approved
- “Implementation History” section is up-to-date for milestone
- User-facing documentation has been created in kubernetes/website, for publication to kubernetes.io
- Supporting documentation—e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes
Summary
This KEP introduces Optional Node Operations to Dynamic Resource Allocation
(DRA), allowing resource drivers to declare that node preparation and/or node
unpreparation is not required for their devices. Currently, the kubelet assumes
it must always coordinate with a node-local DRA driver via gRPC to prepare
allocated devices before container start (NodePrepareResources), and to
unprepare them during pod termination (NodeUnprepareResources).
In some cases, node preparation or cleanup is a pure no-op. Requiring it forces administrators and vendors to deploy and maintain empty node-local drivers on every node, which introduces unnecessary operational complexity and risk.
By introducing a SkipNodeOperations field to the
ResourceSliceSpec and propagating it to the device allocation results at
scheduling time, the kubelet can safely skip driver lookup and gRPC calls for
devices that do not require these node-local actions.
Motivation
In Dynamic Resource Allocation (DRA), the kubelet coordinates with a node-local
driver via gRPC to prepare allocated devices before container start
(NodePrepareResources) and to unprepare them upon pod termination
(NodeUnprepareResources). For node-local accelerators (such as PCIe GPUs or
local FPGAs), this node-level setup is critical to check device health,
partition memory, and configure mount paths.
However, there is an emerging class of resources whose lifecycles are managed
entirely in the control plane and published centrally by a controller as
ResourceSlice objects. These resources require absolutely zero node-local
setup. Under the current architecture, the kubelet still assumes a node-local
driver exists, forcing administrators to deploy and maintain wasteful “no-op”
node DaemonSets just to answer gRPC calls with empty success responses. If one
of these dummy helper plugins crashes or is missing, the kubelet’s unprepare
hook fails and retries indefinitely, leaving terminating pods permanently “stuck
in Terminating” and blocking cluster upgrades and node drains.
To resolve this architectural mismatch and accommodate modern deployments, we
need a way for resource drivers to declare that node preparation and cleanup
can be skipped. Bypassing these gRPC hooks directly at the ResourceSlice level
allows vendors to deploy central-only controllers with zero worker node
footprints. It also provides the flexibility to support mixed hardware
topologies—where a single driver manages some devices requiring node-level
preparation and others that do not—without splitting the driver or forcing
unnecessary footprints onto worker nodes.
Goals
- Allow resource drivers to declare that node-local operations (preparation and clean-up) are optional for devices.
- Propagate this configuration from the
ResourceSliceto the final allocatedResourceClaim.Status.Allocationresult. - Update the kubelet to skip driver lookup and gRPC preparation/unpreparation steps when node operations are explicitly configured as skipped.
- Maintain backward compatibility: by default, all existing DRA drivers must continue to require node-local preparation and unpreparation.
Non-Goals
- Eliminate node-local preparation entirely.
- Enable users to override this infrastructure requirement at the individual
ResourceClaimSpeclevel.
Proposal
We propose adding a SkipNodeOperations field to
ResourceSliceSpec and DeviceRequestAllocationResult.
- API Definition: The driver/controller publisher sets
skipNodeOperationsinResourceSliceresources if the published devices do not require node-local setup or cleanup. - Control Plane Resolution: The allocator/scheduler resolves the referenced
ResourceSliceduring allocation, and copies this configuration intoResourceClaim.Status.Allocation.Devices.Results[i].SkipNodeOperations. - Node Execution: The kubelet reads this field from the
ResourceClaim’s allocation results. If all allocated devices for a given driver within a claim skip an operation, the kubelet bypasses the corresponding gRPC call (NodePrepareResourcesorNodeUnprepareResources) to the node-local resource driver.
User Stories
Deploying controller-managed resources without node-local drivers
As a cluster administrator or vendor using a central driver controller, I want
to offer resources (e.g., cluster-wide shared resource pools, logically
partitioned network services, or pure control-plane gating drivers like
dra-driver-image-configurator)
where availability is discovered and published as
ResourceSlice resources centrally by the controller. Because the devices
require no node-local plumbing or mount operations on worker nodes, there is no
node driver deployed. The controller publishes these resources with
skipNodeOperations: ["*"]. When users request these
devices, the kubelet launches the pods immediately and cleanly, without
complaining about missing node-local drivers, and without requiring any node
driver DaemonSet to be present in the cluster.
Skipping only cleanup for devices that self-release
As a driver vendor whose devices need node-local setup at pod start but whose
cleanup happens automatically (for example, because the resource is released by
the control plane when the claim is deallocated), I want to publish
skipNodeOperations: ["NodeUnprepareResources"]. The kubelet still calls
NodePrepareResources, so the device is set up correctly, but pod termination
never blocks on an unprepare call.
Risks and Mitigations
- Dynamic ResourceSlice Changes: An administrator or controller could update
SkipNodeOperationsin aResourceSlicewhile claims are already allocated.Mitigation: While freezing the allocation configuration into the
ResourceClaimstatus ensures consistent execution for already running pods, it also means that if a driver’s requirements are updated in-place, existing claims will still use the older configuration. Specifically:- If a driver changes from skipping to requiring node preparation, existing claims will still have node preparation skipped by the kubelet, causing pods to run without the required hardware setup.
- If a driver changes from requiring to skipping node preparation, and the node-local driver is decommissioned, existing claims will still require node preparation, causing the kubelet to fail or hang waiting for the missing driver plugin.
Because this skew is inherent to the decoupled nature of scheduling and runtime, this risk must be managed operationally: cluster administrators must perform driver upgrades and migrations carefully, ensuring no active claims/pods exist for the driver before changing its configuration or decommissioning node-local driver components.
- Backward Compatibility & Out-of-Tree / Custom Allocators: Old scheduler
clients or out-of-tree custom driver controllers/allocators might write
allocation results without setting the new
SkipNodeOperationsfield.- Mitigation: The behavior depends on whether the driver uses optional node operations:
- For drivers that do not use optional node operations (i.e., require node-local setup): The fields default to omitted (not skipped). The kubelet will execute node preparation and clean-up as normal. This guarantees 100% backward compatibility with all existing schedulers, custom controllers, and running workloads.
- For drivers that use optional node operations (and do not deploy a node-local driver):
If an old or out-of-tree allocator fails to copy the field from the
ResourceSliceto theResourceClaimstatus, the kubelet will default to executing preparation and fail because no node-local driver is running. To mitigate this:- Custom allocators/schedulers must be upgraded to support and copy the new field before they can be used with optional-operations drivers.
- Alternatively, during transitions, operators can deploy a minimal, “no-op” node-local daemon for the driver to satisfy the kubelet’s gRPC calls until the allocator is upgraded.
- Mitigation: The behavior depends on whether the driver uses optional node operations:
- Unknown operation names: Future versions may add new values to the
SkipNodeOperationenum.- Mitigation: The kubelet ignores values it does not recognize, so an older kubelet reading a newer slice never skips an operation it does not understand.
Design Details
API Changes
ResourceSliceSpec:type ResourceSliceSpec struct { ... // SkipNodeOperations lists node-local resource operations (gRPC calls) // that will be skipped for the devices in this slice when determining whether // operations are necessary on the node. If all allocated devices for a driver in // a claim skip an operation, that gRPC call will be skipped. Valid values are: // // - "NodePrepareResources": NodePrepareResources gRPC calls are skipped. This // value cannot be specified unless "NodeUnprepareResources" is also listed // (or "*" is specified). // - "NodeUnprepareResources": NodeUnprepareResources gRPC calls are skipped. // - "*": All node-local resource operations are skipped. // // Other values may be added in the future. The kubelet must ignore unknown // values. // // +optional // +listType=set // +featureGate=DRAOptionalNodeOperations SkipNodeOperations []SkipNodeOperation `json:"skipNodeOperations,omitempty" protobuf:"bytes,10,rep,name=skipNodeOperations,casttype=SkipNodeOperation"` } // +enum type SkipNodeOperation string const ( SkipNodeOperationNodePrepareResources SkipNodeOperation = "NodePrepareResources" SkipNodeOperationNodeUnprepareResources SkipNodeOperation = "NodeUnprepareResources" SkipNodeOperationAll SkipNodeOperation = "*" )DeviceRequestAllocationResult:type DeviceRequestAllocationResult struct { ... // SkipNodeOperations lists node-local resource operations (gRPC calls) // that will be skipped for this allocated device when determining whether // operations are necessary on the node. If all allocated devices for a driver in // a claim skip an operation, that gRPC call will be skipped. It is a copy of // the ResourceSlice.spec.skipNodeOperations value at the time when the device was allocated. // // +optional // +listType=set // +featureGate=DRAOptionalNodeOperations SkipNodeOperations []SkipNodeOperation `json:"skipNodeOperations,omitempty" protobuf:"bytes,11,rep,name=skipNodeOperations,casttype=SkipNodeOperation"` }
API Server Handling
Feature gate enforcement uses the standard drop-disabled-fields pattern:
- When the
DRAOptionalNodeOperationsfeature gate is disabled:- New Resources:
spec.skipNodeOperationson aResourceSlice, andstatus.allocation.devices.results[*].skipNodeOperationson aResourceClaim, are silently dropped (set tonil) on write. - Existing Resources: if the old object already has the field populated, it is preserved across updates. This means objects written while the gate was enabled survive a downgrade and continue to work when the gate is re-enabled, and unrelated updates to those objects do not fail.
- New Resources:
- When the feature gate is enabled:
- The field is validated and persisted normally.
Validation that applies regardless of the gate:
- Values must be members of the
SkipNodeOperationenum, and the list is a set (+listType=set), so duplicates are rejected. Both are handled by declarative validation. "NodePrepareResources"may only be listed if"NodeUnprepareResources"or"*"is also listed. Otherwise a pod could be admitted and started on a node with no node-local driver, since preparation is skipped, and then hang inTerminatingbecause unpreparation is still required and no driver can serve it.
Allocator Changes
During scheduling, the structured parameters allocator resolves ResourceSlices
that contain the allocated devices. When a device’s slice has a non-empty
SkipNodeOperations, the allocator treats the device as unallocatable in
either of these cases:
- The
DRAOptionalNodeOperationsfeature gate is disabled in the scheduler/allocator. - The candidate node does not advertise
DRAOptionalNodeOperationsinnode.status.declaredFeatures.
Filtering the device out (rather than failing the whole claim) lets the
allocator fall back to another device or another node, and leaves the pod
Pending with a normal unschedulable status if no candidate remains.
Otherwise the allocator copies the SkipNodeOperations set verbatim from the
ResourceSliceSpec into each DeviceRequestAllocationResult under
ResourceClaim.Status.Allocation.Devices.Results.
Kubelet Changes
When Kubelet prepares resources for an allocated claim, it evaluates the allocated devices’ status:
Aggregation: Because Kubelet invokes preparation and clean-up per-claim and per-driver, it computes, for each driver in the claim, the set of operations that every device allocated from that driver skips. A device listing
"*"counts as skipping every operation.Checkpointing: Kubelet caches this aggregated set inside its checkpointed, claim-specific state (
ClaimInfo) so it is safely preserved across Kubelet restarts. To ensure robust upgrade/downgrade compatibility, the checkpoint serialization must be forward and backward compatible.Bypassing: During
PrepareResources, the DRA manager skips both the driver registry lookup and theNodePrepareResourcesgRPC call for any driver whose cached set containsNodePrepareResourcesor"*". DuringUnprepareResourcesit does the same forNodeUnprepareResourcesor"*". Skipping the registry lookup is what allows a driver with no node-local component to work at all. Each skipped call incrementsdra_node_prepare_skips_totalordra_node_unprepare_skips_totalfor that driver.Disabled Feature Gate Behavior: If the
DRAOptionalNodeOperationsfeature gate is disabled on the kubelet, computing the driver state for a claim whose allocation result asks to skip anything returns an error (DRAOptionalNodeOperations feature gate is disabled on kubelet). This surfaces as aPrepareResourcesfailure, so the pod stays inContainerCreatingwith aFailedPrepareDynamicResourcesevent rather than running with an unprepared device. Because the check lives in the sharedClaimInfoconstruction path, it applies uniformly rather than relying on a separate admission check.Note that pods which were already prepared keep their checkpointed state and are unprepared from that state, so disabling the gate does not strand a running pod in
Terminating.
Node Declared Features Integration
To manage version skew safely during rolling upgrades, this KEP integrates with the Node Declared Features framework. This allows the control plane to dynamically discover if a node’s Kubelet supports optional node operations before scheduling workloads, preventing pods from being scheduled to incompatible nodes.
We register a new declared feature:
- Feature Name:
DRAOptionalNodeOperations - Associated Feature Gate:
DRAOptionalNodeOperations - Discovery Logic (Kubelet): A node declares support for
DRAOptionalNodeOperationsin itsnode.status.declaredFeaturesif and only if theDRAOptionalNodeOperationsfeature gate is enabled on the Kubelet. - Enforcement (Scheduler): The generic NDF
InferForSchedulinghook returnsfalsefor this feature, because a claim’sstatus.allocationis not set until PreBind and therefore cannot be inspected at PreFilter time. Enforcement instead lives in thedynamicresourcesscheduler plugin, in two places:- Allocating a new claim: the allocator will not select a device whose
slice sets
SkipNodeOperationsunless the candidate node declaresDRAOptionalNodeOperations. - Filtering with an already-allocated claim: if any allocated device
in the claim sets
SkipNodeOperationsand the node does not declare the feature, the node is rejected.
- Allocating a new claim: the allocator will not select a device whose
slice sets
- Max Version:
nil. The feature remains a scheduling constraint; it can be given a max version once the feature is GA and the supported kubelet skew guarantees support.
Test Plan
[x] I/we understand the owners of the involved components may require updates to existing tests to make this code solid enough prior to committing the changes necessary to implement this enhancement.
Prerequisite testing updates
None.
Unit tests
- API Server Validation: In
pkg/apis/resource/validation/validation_resourceslice_test.goandpkg/registry/resource/:- Verify valid combinations of
skipNodeOperationsare accepted and invalid values (or"NodePrepareResources"alone) are rejected. - Verify field is dropped when feature gate is disabled, and preserved if already in use.
- Verify valid combinations of
- ResourceSlice Controller Helper Unit Tests: In
staging/src/k8s.io/dynamic-resource-allocation/resourceslice/resourceslicecontroller_test.go:- Verify that
SkipNodeOperationsis synced toResourceSlice.Spec.SkipNodeOperations. - Verify that a
DroppedFieldsErroris returned whenSkipNodeOperationsis dropped by the API server becauseDRAOptionalNodeOperationsis disabled.
- Verify that
- Allocator Unit Tests: In
staging/src/k8s.io/dynamic-resource-allocation/structured/:- Verify that
SkipNodeOperationsinResourceSliceSpecis correctly propagated toAllocationResult. - Verify that devices with
SkipNodeOperationsare not selected when the feature is disabled or the node lacks support.
- Verify that
- Kubelet DRA Manager Unit Tests: In
pkg/kubelet/cm/dra/manager_test.go:- Assert that
prepareResourcesandunprepareResourcesbypass gRPC calls when the driver’s aggregated set covers the operation. - Assert that
prepareResourcesfails when the feature gate is disabled on the node and skipping is requested.
- Assert that
- Shared Library Unit Tests: In
staging/src/k8s.io/component-helpers/nodedeclaredfeatures/features/draoptionalnodeoperations/feature_test.go:- Verify the node declared feature for
DRAOptionalNodeOperationsbehaves correctly.
- Verify the node declared feature for
- Kubelet Checkpoint State Unit Tests: In
pkg/kubelet/cm/dra/claiminfo_test.go:- Verify backward and forward compatibility of the serialized
ClaimInfocheckpoint state:- Forward Compatibility (Downgrade/Rollback): Verify that a checkpoint
file written by a Kubelet running version N (containing the new
SkipNodeOperationsfield inClaimInfo) can be successfully parsed and deserialized by a Kubelet running version N-1 (or with the feature gate disabled) without parsing errors or crashes, with unrecognized fields being safely ignored. - Backward Compatibility (Upgrade): Verify that an older checkpoint file written by a Kubelet running version N-1 (which completely lacks the new field) is successfully parsed and deserialized by Kubelet version N, with the field defaulting to not skipping (ensuring we do not skip preparation/unpreparation for legacy claims).
- Forward Compatibility (Downgrade/Rollback): Verify that a checkpoint
file written by a Kubelet running version N (containing the new
- Verify backward and forward compatibility of the serialized
Integration tests
- Scheduler Filtering Integration Tests:
- Source:
test/integration/dra/optional_node_operations.go - TestGrid: integration master, triage search
- Verify that a pod or pod group requiring
DRAOptionalNodeOperations(having a claim allocated withSkipNodeOperations) is successfully scheduled to a node that advertises the feature. - Verify that the scheduler filters out (rejects) nodes that do not advertise the feature (representing older Kubelets or nodes with the feature gate disabled).
- Verify that if no compatible nodes are available, the pod remains in the
Pendingstate with aFailedSchedulingevent indicating the missingDRAOptionalNodeOperationsfeature on nodes.
- Source:
e2e tests
- Source:
test/e2e/dra/dra.go(optionalNodeOperationsTests) - TestGrid: sig-node-kubelet, triage search
Basic End-to-End test cases (Scenario 1 & 2) were implemented in Alpha inside test/e2e/dra/dra.go to validate
skipNodeOperations configurations using different
driver configurations. Scenario 3 (Upgrade / Downgrade and Feature Gate Rollback)
will be added for Beta.
Scenario 1: Driver without node-local components (Pure Control-Plane)
This scenario validates that we can run workloads using drivers that do not deploy any node-local components.
- Setup: Deploy a DRA test driver without node gRPC components running on
worker nodes (
WithKubelet = false). - Test Case 1.1: Fully skipped node operations (
skipNodeOperations: ["*"])- API Configuration: Publish
ResourceSliceswithskipNodeOperations: ["*"]. - Workload: Deploy a Pod referencing this resource.
- Assertions:
- The Pod reaches the
Runningphase successfully. - The allocated device can be accessed.
- No
FailedPrepareDynamicResourceswarnings are posted to the Pod events. - Pod deletion completes cleanly and immediately (does not hang in
Terminatingwaiting for unprepare).
- The Pod reaches the
- API Configuration: Publish
- Test Case 1.2: Missing node component failure (
skipNodeOperationsomitted)- API Configuration: Publish
ResourceSliceswithskipNodeOperationsomitted. - Workload: Deploy a Pod referencing this resource.
- Assertions:
- The Pod gets stuck in
ContainerCreatingwithFailedPrepareDynamicResourceserrors because the kubelet tries to contact the non-existent node driver.
- The Pod gets stuck in
- API Configuration: Publish
- Test Case 1.3: Missing node component failure when skipping only unprepare
(
skipNodeOperations: ["NodeUnprepareResources"])- API Configuration: Publish
ResourceSliceswithskipNodeOperations: ["NodeUnprepareResources"]. - Workload: Deploy a Pod referencing this resource.
- Assertions:
- The Pod gets stuck in
ContainerCreatingwithFailedPrepareDynamicResourceserrors becauseNodePrepareResourcesis still required and no node-local driver is running.
- The Pod gets stuck in
- API Configuration: Publish
Scenario 2: Driver with node-local components (Standard Driver)
This scenario validates that the kubelet selectively invokes or bypasses
node-local driver gRPC operations according to skipNodeOperations when a
node-local driver is running.
- Setup: Deploy a standard DRA test driver that includes node-local gRPC components.
- Test Case 2.1: Standard Node Execution (
skipNodeOperationsomitted)- API Configuration: Publish
ResourceSliceswithskipNodeOperationsomitted. - Workload: Deploy a Pod.
- Assertions:
- The Pod reaches the
Runningphase. - Assert that the driver’s
NodePrepareResourceswas called. - Delete the Pod.
- Assert that the driver’s
NodeUnprepareResourceswas called.
- The Pod reaches the
- API Configuration: Publish
- Test Case 2.2: Fully bypassed node operations (
skipNodeOperations: ["*"])- API Configuration: Publish
ResourceSliceswithskipNodeOperations: ["*"]. - Workload: Deploy a Pod.
- Assertions:
- The Pod reaches the
Runningphase. - Assert that the driver’s
NodePrepareResourceswas not called. - Delete the Pod.
- Assert that the driver’s
NodeUnprepareResourceswas not called.
- The Pod reaches the
- API Configuration: Publish
- Test Case 2.3: Skipping only unprepare (
skipNodeOperations: ["NodeUnprepareResources"])- API Configuration: Publish
ResourceSliceswithskipNodeOperations: ["NodeUnprepareResources"]. - Workload: Deploy a Pod.
- Assertions:
- The Pod reaches the
Runningphase. - Assert that the driver’s
NodePrepareResourceswas called. - Delete the Pod.
- Assert that the driver’s
NodeUnprepareResourceswas not called.
- The Pod reaches the
- API Configuration: Publish
Scenario 3: Upgrade / Downgrade and Feature Gate Rollback
This scenario validates that the system behaves correctly during a rolling upgrade or downgrade/rollback of the feature gate.
- Test Case 3.1: Rolling Upgrade (N-1 to N):
- Setup: Start with a cluster running version N-1 (feature gate disabled). Deploy a DRA driver.
- Action 1 (Control Plane Upgrade): Upgrade the control plane to version N
(feature gate enabled).
- Assertions:
- If we deploy a new workload using a control-plane-only driver (no
node-local components):
- The Pod remains in the
Pendingstate (unschedulable). The scheduler’sdynamicresourcesplugin must filter out all N-1 worker nodes because they do not advertiseDRAOptionalNodeOperationsinnode.status.declaredFeatures. - The pod must not be scheduled to any N-1 node.
- The Pod remains in the
- If we deploy a new workload using a control-plane-only driver (no
node-local components):
- Assertions:
- Action 2 (Kubelet Upgrade): Upgrade the kubelets to version N.
- Assertions:
- Once a Kubelet is upgraded to N and advertises
DRAOptionalNodeOperations, verify that the pending workload is automatically scheduled to that node, successfully bypasses node preparation, transitions toRunning, and runs successfully. - Verify that deleting the control-plane-only workload completes immediately without trying to contact a node-local driver.
- Once a Kubelet is upgraded to N and advertises
- Assertions:
- Test Case 3.2: Feature Gate Rollback / Downgrade (N to N-1):
- Setup: Start with a cluster running version N (feature gate enabled).
Deploy a standard DRA driver and a workload using
skipNodeOperations: ["*"]. - Action 1 (Control Plane Downgrade): Downgrade the control plane to N-1
(feature gate disabled).
- Assertions:
- The API server allows the existing
ResourceSliceobjects to remain valid and not be rejected on unrelated updates. - The running workload on the N kubelet continues to run without interruption.
- The API server allows the existing
- Assertions:
- Action 2 (Kubelet Downgrade / Feature Gate Rollback): Downgrade the
Kubelet binary to N-1, or disable the
DRAOptionalNodeOperationsfeature gate on Kubelet version N, and restart the Kubelet.- Assertions:
- Checkpoint Recovery: The Kubelet starts up successfully and parses
the checkpoint file without errors or crashes.
- For Kubelet version N (gate disabled): The Kubelet successfully
recovers the full
ClaimInfostate including the savedskipNodeOperationsset, and the already-prepared pod is unprepared from that state. - For Kubelet version N-1: The Kubelet successfully parses the checkpoint by ignoring the unknown field, and recovers the rest of the state with nothing skipped.
- For Kubelet version N (gate disabled): The Kubelet successfully
recovers the full
- Workload Deletion:
- Verify that the kubelet behaves according to the Disabled Feature Gate Behavior section upon workload deletion.
- Checkpoint Recovery: The Kubelet starts up successfully and parses
the checkpoint file without errors or crashes.
- Assertions:
- Setup: Start with a cluster running version N (feature gate enabled).
Deploy a standard DRA driver and a workload using
- Test Case 3.3: Upgrade -> Downgrade -> Upgrade (N-1 -> N -> N-1 -> N):
- Setup: Start with a cluster running version N-1 (feature gate disabled). Deploy a standard DRA driver.
- Action 1 (Upgrade): Upgrade the cluster to version N (feature gate
enabled).
- Deploy a workload using a driver configured with
skipNodeOperations: ["*"]. - Assert that the workload runs successfully.
- Deploy a workload using a driver configured with
- Action 2 (Downgrade): Downgrade the cluster to version N-1 (feature gate
disabled).
- Assertions:
- Assert that the API server allows the existing
ResourceSlice(which hasskipNodeOperations: ["*"]) to remain valid and unmodified. - Delete the workload and verify that the kubelet behaves according to the Disabled Feature Gate Behavior section.
- Assert that the API server allows the existing
- Assertions:
- Action 3 (Upgrade Again): Upgrade the cluster back to version N (feature
gate enabled).
- Deploy a new workload using the same driver.
- Assert that the new field is respected, and the workload runs successfully.
- Assert that any pre-existing resource slices that survived the downgrade cycle continue to function correctly with the re-enabled feature gate.
Graduation Criteria
Alpha
- Feature implemented behind the
DRAOptionalNodeOperationsfeature flag (off by default). - Full unit and basic E2E test suites (Scenario 1 & 2) implemented and green.
- Metrics (
dra_node_prepare_skips_totalanddra_node_unprepare_skips_total) added. - User and driver developer documentation published on kubernetes.io.
Beta
- Enable the feature gate by default.
- E2E upgrade/downgrade and rollback test suites (Scenario 3) implemented and green.
- Gather real-world feedback from developers and driver vendors.
- Update documentation on kubernetes.io to reflect Beta status and default enablement.
GA
- The feature has been enabled by default for at least two releases with no critical bug reports.
- All feedback, gaps, and issues identified during the Beta phase are addressed.
- Feature gate locked to true and deprecated according to standard policy.
Upgrade / Downgrade Strategy
- Upgrade:
- When the cluster control plane and nodes are upgraded, all preexisting claims (where the new field is absent) automatically evaluate to not skipped. This guarantees no change in behavior for running workloads.
- Newer claims can utilize drivers that publish resource slices configured
with
skipNodeOperationsto bypass node-local execution. - During rolling upgrades, the scheduler will
automatically restrict the scheduling of pods using these newer “no-prep” claims
to upgraded nodes that advertise support for
DRAOptionalNodeOperations.
- Downgrade:
- Feature Gate Rollback (on v1.37+): If the
DRAOptionalNodeOperationsfeature gate is disabled on a kubelet that supports the feature:- New pods or restarting pods whose claims specify
skipNodeOperationswill failPrepareResourceswith aDRAOptionalNodeOperations feature gate is disabled on kubeleterror rather than running with unprepared devices. - Already-running pods keep their checkpointed
ClaimInfostate (including the cachedskipNodeOperationsset), soUnprepareResourcescontinues to skip cleanup and pods can be deleted cleanly without hanging inTerminating.
- New pods or restarting pods whose claims specify
- Kubelet Binary Downgrade (to pre-v1.37): If a kubelet binary is
downgraded to an older version that lacks
DRAOptionalNodeOperationssupport altogether, it ignores the unknownskipNodeOperationsfield in the checkpoint and defaults to invoking node-local gRPC calls. If any pods are running using a driver without node-local components, those pods will fail to restart or delete cleanly. Operators must ensure all pods using no-prep claims are terminated before downgrading kubelet binaries to pre-v1.37, or run temporary no-op drivers during the downgrade transition.
- Feature Gate Rollback (on v1.37+): If the
Version Skew Strategy
Older kubelet (N-1 and older) / Upgraded Control Plane (N):
- Automated Version Skew Protection: If the control plane is upgraded and
generates allocations with
skipNodeOperationsset, thedynamicresourcesscheduler plugin requires the target node to declare theDRAOptionalNodeOperationsfeature. - Because older worker nodes running older Kubelets ($N-1$ and older) do not
support the feature gate, they will not advertise
DRAOptionalNodeOperationsin theirnode.status.declaredFeatures. - The scheduler will automatically filter out these older nodes during the scheduling cycle, guaranteeing that the pod will only land on compatible, upgraded nodes.
- Automated Version Skew Protection: If the control plane is upgraded and
generates allocations with
Upgraded kubelet (N) / Older Control Plane (N-1 and older):
If the control plane has not been upgraded yet, any new allocations will not have
skipNodeOperationsset in the status.An upgraded kubelet (N) will read the absent fields and default to not skipping (requiring node preparation/unpreparation).
The behavior depends on whether the driver uses optional node operations:
- For drivers that do not use optional node operations (i.e., require node-local setup): The fallback ensures backward-compatible, safe execution because the node-local driver is running and kubelet will coordinate with it as normal.
- For drivers that use optional node operations (and do not deploy a node-local driver):
The fallback means the upgraded kubelet will attempt to coordinate
with the local driver and fail because no node-local driver is running.
- Mitigation: The control plane must be upgraded before these optional-operations drivers can be deployed, or a temporary, minimal “no-op” node-local daemon must be deployed to satisfy the kubelet’s gRPC calls during the transition window.
Note: This same fallback behavior occurs if the control plane is upgraded (N) but the active custom allocator or scheduler has not been upgraded to support KEP-5945 yet and fails to copy the field.
Kubelet Feature Gate Disabled / SkipNodeOperations configured:
- If the control plane has the gate enabled and writes
skipNodeOperations, but the upgraded kubelet has the gate disabled:- Pods requesting
skipNodeOperationswill failPrepareResourceswith aDRAOptionalNodeOperations feature gate is disabled on kubeleterror. - For already running pods (in case the feature gate was disabled after
successful
PrepareResources), the kubelet will honorskipNodeOperationsand skip the unprepare call duringUnprepareResources, allowing the pod to terminate cleanly.
- Pods requesting
- If the control plane has the gate enabled and writes
Scheduler Feature Gate Disabled / SkipNodeOperations configured:
- If the
DRAOptionalNodeOperationsfeature gate is disabled in the scheduler/allocator, but a driver publishesResourceSliceswithskipNodeOperations(e.g., due to inconsistent feature gates in a rolling upgrade, or lingering slices after downgrade), the allocator treats those devices as unallocatable. - This ensures that we fail allocation early in the scheduling lifecycle (which allows rescheduling/retry after correcting the configuration), rather than scheduling the pod incorrectly (where fields are not copied to the claim status and the kubelet subsequently gets stuck expecting a node-local driver).
- If the
Production Readiness Review Questionnaire
Feature Enablement and Rollback
How can this feature be enabled / disabled in a live cluster?
- Feature gate
- Feature gate name:
DRAOptionalNodeOperations - Components depending on the feature gate:
- kube-apiserver
- kube-scheduler
- kubelet
- Feature gate name:
The gate is off by default in alpha (v1.37) and on by default in beta (v1.38).
It also depends on the DynamicResourceAllocation and NodeDeclaredFeatures
gates.
Does enabling the feature change any default behavior?
No. By default, absent fields evaluate to empty (which defaults to not
skipping in code), meaning all resource claims continue to require node
preparation and cleanup unless explicitly set to skip in the published
ResourceSlice by the driver.
Can the feature be disabled once it has been enabled (i.e. can we roll back the enablement)?
Yes. Setting the feature gate to false and restarting components will disable
it. If disabled, any new allocations for standard drivers will proceed normally.
However, devices in lingering ResourceSlices that still have
skipNodeOperations set (preserved by kube-apiserver across rollback) will be
treated as unallocatable (filtered out) by the allocator. If no other compatible
devices satisfy a claim, the pod remains Pending (unschedulable) rather than
being bound to a node where skipNodeOperations would either be stripped from
the new ResourceClaim allocation by kube-apiserver (causing the kubelet to
call a non-existent node-local driver) or rejected by PrepareResources on a
kubelet with the feature gate disabled.
What happens if we reenable the feature if it was previously rolled back?
Re-enabling the feature gate is safe. Any claims allocated while the feature was
disabled will have an empty skipNodeOperations in their status, so they will
continue to be processed with node-local preparation. Newly allocated claims
after re-enablement can once again utilize no-prep resource pools. No state
corruption or data loss occurs.
Are there any tests for feature enablement/disablement?
Yes:
- Registry strategy unit tests verify the drop-on-disabled and
preserve-if-already-in-use behavior for both
ResourceSliceandResourceClaimstatus. - Allocator unit tests verify that devices with
skipNodeOperationsare not selected when the feature is disabled. - Kubelet unit tests verify that
PrepareResourcesfails when the gate is disabled but the allocation result asks to skip an operation, and that theClaimInfocheckpoint written with the field set can still be read back after the gate is disabled (and by an older kubelet).
Rollout, Upgrade and Rollback Planning
How can a rollout or rollback fail? Can it impact already running workloads?
- Nodes that do not yet advertise
DRAOptionalNodeOperationsare filtered out by the scheduler, so pods wait until a supporting node is available. - A rollback can fail if pods were deployed relying on a driver with no node-local driver, blocking those pods’ restarts.
- Mitigation: Operators should ensure no pods using
skipNodeOperationsare active in the cluster before disabling the feature gate.
What specific metrics should inform a rollback?
An increase in dra_operations_duration_seconds or
FailedPrepareDynamicResources warnings on the kubelet, indicating the kubelet
is attempting node preparation and blocking/failing due to missing node drivers.
dra_node_prepare_skips_total/dra_node_unprepare_skips_totalfailing to increase for drivers configured withskipNodeOperations.
Were upgrade and rollback tested? Was the upgrade->downgrade->upgrade path tested?
This will be tested as part of the Beta graduation criteria using the upgrade/downgrade E2E test plan. See Scenario 3: Upgrade / Downgrade and Feature Gate Rollback in the Test Plan for the detailed test cases.
Is the rollout accompanied by any deprecations and/or removals of features, APIs, fields of API types, flags, etc.?
No.
Monitoring Requirements
How can an operator determine if the feature is in use by workloads?
By exposing and monitoring the kubelet-side counter metrics
dra_node_prepare_skips_total and
dra_node_unprepare_skips_total, or by auditing active ResourceClaim
allocations to check if .status.allocation.devices.results[*].skipNodeOperations is non-empty.
How can someone using this feature know that it is working for their instance?
- API .status
- Other field:
.status.allocation.devices.results[*].skipNodeOperationswill list the skipped operations in theResourceClaim. - Workloads run successfully without node-local drivers deployed.
- Other field:
What are the reasonable SLOs (Service Level Objectives) for the enhancement?
- Bypassing the node driver lookup should reduce pod startup latency
(
prepareResources) for resources not requiring node preparation to near-zero. - 0% error rate in kubelet resource preparation for no-prep claims.
What are the SLIs (Service Level Indicators) an operator can use to determine the health of the service?
- Metrics
- Metric name:
dra_operations_duration_seconds- Components exposing the metric: kubelet
- Metric name:
dra_node_prepare_skips_total,dra_node_unprepare_skips_total- Components exposing the metric: kubelet
- Metric name:
- Other
- Details: rate of
FailedPrepareDynamicResourcespod events.
- Details: rate of
Are there any missing metrics that would be useful to have to improve observability of this feature?
No. The metrics dra_node_prepare_skips_total and
dra_node_unprepare_skips_total were introduced in alpha (v1.37).
Dependencies
Does this feature depend on any specific services running in the cluster?
No. It does not depend on any external services or separate cluster-level services. It is an in-tree feature within kube-apiserver, kube-scheduler, and kubelet (it interacts with the in-tree Node Declared Features framework and Dynamic Resource Allocation).
Scalability
Will enabling / using this feature result in any new API calls?
No. It reuses existing API objects and calls.
Will enabling / using this feature result in introducing new API types?
No.
Will enabling / using this feature result in any new calls to the cloud provider?
No.
Will enabling / using this feature result in increasing size or count of the existing API objects?
Yes, slightly:
- API type(s):
ResourceSlice(spec.skipNodeOperations) andResourceClaim(status.allocation.devices.results[*].skipNodeOperations). - Estimated increase in size: An optional string slice (
[]SkipNodeOperation), typically 0 to ~30 bytes when populated. - Estimated amount of new objects: None.
Will enabling / using this feature result in increasing time taken by any operations covered by existing SLIs/SLOs?
No. It actually reduces time taken by kubelet pod startup since it skips gRPC lookups and network calls.
Will enabling / using this feature result in non-negligible increase of resource usage (CPU, RAM, disk, IO, …) in any components?
No. Bypassing node-local drivers reduces total cluster-wide memory and CPU consumption by eliminating unnecessary helper daemonsets.
Can enabling / using this feature result in resource exhaustion of some node resources (PIDs, sockets, inodes, etc.)?
No. In fact, it prevents resource exhaustion by eliminating the need to run dummy daemonsets on every node for drivers without node-local drivers, which saves PIDs, memory, and sockets.
Troubleshooting
How does this feature react if the API server and/or etcd is unavailable?
The kubelet relies on its locally saved ClaimInfo cache. If etcd is down, new
claims cannot be created/scheduled, but existing pods can be terminated cleanly
without requiring API server calls for no-prep claims.
What are other known failure modes?
Misconfigured driver skip settings: If a driver controller misconfigures
skipNodeOperationsfor a physical device that does require node preparation, the kubelet will skip preparation, causing containers to start without necessary mounts or initialization, leading to container application crashes.- Mitigation: Driver developers and administrators must ensure that
skipNodeOperationsis only applied toResourceSlices representing resources that require absolutely no node-local preparation or device plumbing on the worker nodes.
- Mitigation: Driver developers and administrators must ensure that
Driver requirements change in-place: If a driver’s node preparation requirements are updated in-place (e.g., changing
skipNodeOperationsin new resource slices), existing claims will still use the older configuration. Specifically:- If changing from skipping to requiring preparation, existing claims will still have node preparation skipped by the kubelet (potentially causing pod failures).
- If changing from requiring to skipping preparation and decommissioning the node-local driver, existing claims will still require node preparation, causing the kubelet to fail or hang waiting for the missing driver plugin.
- Mitigation: Administrators must perform such migrations/upgrades carefully (e.g., ensuring no active claims or pods exist for the driver before updating its configuration or decommissioning node-local driver components).
Older or custom allocator fails to copy field: If an older or custom scheduler/allocator does not support copying the skip field from the
ResourceSliceto theResourceClaimstatus, the kubelet will default to executing node preparation, which will fail if the driver has no node-local component deployed on the worker nodes.- Mitigation: Ensure the custom allocator/scheduler is upgraded to support and copy the new field before deploying optional-operations drivers, or temporarily run a minimal “no-op” node-local daemon for the driver.
What steps should be taken if SLOs are not being met to determine the problem?
- Verify if the affected Pod has
FailedPrepareDynamicResourcesevents. - Inspect the associated
ResourceClaimstatus:kubectl get resourceclaim <claim-name> -o yaml. - Check if
.status.allocation.devices.results[*].skipNodeOperationsis set. If it is empty but the driver is configured withskipNodeOperationsin itsResourceSlice, verify if the scheduler or custom allocator has been upgraded to support KEP-5945 and correctly copies this field. - If the pod remains
Pending(unschedulable) when requesting devices from aResourceSlicewithskipNodeOperationsset, verify that:- Target nodes declare
DRAOptionalNodeOperationsinnode.status.declaredFeatures(requiringDRAOptionalNodeOperationsto be enabled on the kubelet). - The
DRAOptionalNodeOperationsfeature gate is enabled inkube-scheduler(when disabled, the allocator treats devices withskipNodeOperationsas unallocatable).
- Target nodes declare
- If
PrepareResourcesfails with aDRAOptionalNodeOperations feature gate is disabled on kubeleterror, verify that theDRAOptionalNodeOperationsfeature gate is enabled on the target kubelet. - If a terminating pod was deleted and skipped cleanup, verify if it had
skipNodeOperationsset in its allocation result, which allows bypassing cleanup even when the feature gate is disabled. - If resource preparation succeeded (skipped) but the container fails to start
or run because of missing hardware access, verify that the
ResourceSlicewas not misconfigured. If the device actually requires node-local prep,NodePrepareResources(or"*") must not be listed inskipNodeOperations.
Implementation History
- 2026-05-21: KEP drafted and proposed as Provisional for Alpha stage.
- v1.37: KEP marked
implementable; alpha implementation merged (DRAOptionalNodeOperationsfeature gate, off by default). - v1.38: KEP updated for beta graduation; feature gate enabled by default.
Drawbacks
- Adds a new configuration field to the API, which increases API surface area. However, this is necessary to support controller-managed or logical resources natively without node-local drivers in a clean way.
Alternatives
Alternative 1: DeviceClass-level configuration
Configure this on the cluster-scoped DeviceClassSpec.
- Reason for Rejection: The cluster administrator shouldn’t have to specify
whether a device needs node preparation. Shifting it to
ResourceSlice(driver-owned) makes it fully automatic and matches the driver’s self-declared capability.
Alternative 2: Claim-level declaration
Allow users to declare skipNodeOperations in their ResourceClaimSpec.
- Reason for Rejection: Users should not be concerned with, or even know about, the underlying node-level physical or logical prep requirements of the hardware. This is an operational and infrastructure concern that belongs entirely to the vendor and scheduler/kubelet.
Alternative 3: Kubelet Auto-Discovery / gRPC probe with timeout
Instead of using an API field, the kubelet could automatically probe for a local driver. If no driver is registered after a short timeout, it assumes preparation is not needed and starts the pod.
- Reason for Rejection: This is extremely risky. The kubelet cannot distinguish between “no driver is supposed to be here” and “the driver is crashed, slow to start, or overloaded”. Using a timeout would result in flaky pod startups, silent failures, and potential security/consistency issues where containers launch before their local devices are fully prepared. Explicit declaration via the API is highly deterministic and secure.
Alternative 4: Centralized catch-all no-op plugin
Deploy a generic, “no-op” DRA driver (such as dra-driver-noop) configured centrally to register under specific DRA driver names and handle the node preparation calls by immediately returning success without doing any actual work.
- Reason for Rejection: While this allows running without modifying the DRA
API, it has several drawbacks:
- Operational Overhead: It requires deploying and managing an additional daemon/driver on nodes just to satisfy the Kubelet’s handshake, increasing operational complexity.
- Mixed-mode coordination: It is difficult to coordinate in environments with “mixed-mode” resources, where some devices of a particular driver name require actual node-local preparation (and thus need a real driver) while others do not. A static “catch-all” driver cannot easily co-exist or coordinate with a real driver registering under the same driver name on the same node to selectively handle or bypass preparation.
- Lack of Explicit Intent: It hides the logical nature of the resource
behind a dummy driver, making debugging and cluster observation more
difficult compared to an explicit
SkipNodeOperationsfield in theResourceSlice.