Conversation
v0.37 grew the kubeletplugin.DRAPlugin interface with WatchHealthStatus, which we decline: our devices are the node's own CPUs and memory, and the kubelet already knows whether the node is healthy. Declining is what makes it stop asking. Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
A claim's devices are granted to the containers using it by a CDI spec of its own, named after the claim so that unpreparing it can find the spec again. What a device grants is the policy's business: the container edits it hands us are written out verbatim, and the spec version follows from them, so a policy reaching for a newer kind of edit needs nothing here. Importing the CDI library is the first thing in the tree to pull in runtime-tools, whose stale replace does not compile against the runtime-spec we already have. It has had no importer since it was inherited, so it goes. Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
A claim is allocated by the policy, committed, and only then granted by a CDI spec. That order is what keeps the accounting honest: a crash between the two leaves a spec nothing claims, which can be found and cleaned up, rather than resources granted to a container and accounted to nobody. Releasing follows the same order, so what may be left behind is always a spec and never an allocation. Every claim is answered on its own, because the kubelet records the answers per claim and retries only the ones which failed. A claim the policy allocated but we could not prepare is handed back, unless an earlier prepare of it had already succeeded: its devices may be in use, and the kubelet releases the claim when its last pod goes away. Claims are refused until the runtime synchronization has completed. The driver registers as soon as we start, but Synchronize is the one NRI request which runs without the resource manager's lock and with cache saves blocked, so a claim served beside it would be allocated concurrently with the policy sync and committed to nothing. Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Claim synchronization can race, failed NRI updates are not safely retryable, and required orphan-spec cleanup is missing.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 2
Open (3)
What changed in this PR
Adds DRA claim preparation and release through policies, with CDI-based resource grants and synchronization gating.
Changes:
- Implements per-claim allocation, rollback, commit, and release handling.
- Adds CDI spec storage and comprehensive tests.
- Upgrades Kubernetes dependencies to v0.37.
| File | Description |
|---|---|
pkg/resmgr/resource-manager.go |
Starts NRI before DRA. |
pkg/resmgr/nri.go |
Enables claims after synchronization. |
pkg/resmgr/dra/plugin.go |
Adds CDI storage, gating, and health handling. |
pkg/resmgr/dra/plugin_test.go |
Extends plugin test infrastructure. |
pkg/resmgr/dra/claim.go |
Implements claim preparation and release. |
pkg/resmgr/dra/claim_test.go |
Tests claim lifecycle and failures. |
pkg/resmgr/dra/cdi.go |
Implements per-claim CDI specs. |
pkg/resmgr/dra/cdi_test.go |
Tests CDI storage behavior. |
pkg/resmgr/dra.go |
Commits policy and container updates. |
pkg/resmgr/dra_test.go |
Tests synchronization gating. |
go.mod |
Updates Kubernetes and CDI dependencies. |
go.sum |
Refreshes dependency checksums. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+341
to
343
| m.dra.AllowClaims() | ||
|
|
||
| return p.getPendingUpdates(nil), nil |
Comment on lines
+129
to
+132
| store, err := newCDIStore(driverName, opts.CDIDir) | ||
| if err != nil { | ||
| return nil, err | ||
| } |
bart0sh
marked this pull request as ready for review
September 21, 2026 18:17
bart0sh
marked this pull request as draft
September 21, 2026 18:20
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


DRA claim handling
Prepare and unprepare claims, and grant them with CDI
Third PR of the DRA series, on top of #803. It fills in the two kubelet handlers
the skeleton left as no-ops: a claim is allocated by the active policy through
the interface #803 added, and what it got is granted to the containers using it
by a CDI spec of its own.
Still inert on a cluster — every backend answers
AllocateClaimwithpolicy.ErrNoDRAClaims, so a claim naming this driver fails and the pod stayspending. The next PR brings the first policy that really allocates, and with it
the first look at this path outside its tests.
Three commits, in order: the library bump to Kubernetes v0.37 and the one
source change it forces; the CDI spec store — file mechanics and device
naming, where the device for result i of claim uid is
claim-<uid>-<i>, sothe positional correspondence #803 defined survives into the CDI IDs; then
claim dispatch.
The ordering is the design
Prepare is: allocate through the policy, commit, write the spec. Unprepare
is: release, commit, remove the spec. Committing is a cache save plus the NRI
container updates the policy made, which is what lets an allocation outlive us
and reach the containers that give resources up for it.
Spec last is what keeps the accounting honest across a crash: the worst case is a
spec no claim accounts for, never resources granted to a container and accounted
to nobody. Two things follow from it.
A spec proves a prepare completed, so a failure partway through a
re-prepare must not roll back:
AllocateClaimis idempotent andReleaseClaimreleases the whole claim, so releasing here would take resources from a pod
already using them.
prepareClaimrolls back only while the claim has no spec.Claims are refused until the runtime synchronization has completed
stub.Start()returns once the runtime has answeredConfigure; the containersalready running only reach the policy with the
Synchronizethat follows — theone NRI handler that runs without the resource manager's lock and with cache
saves blocked. A claim served in that window would be allocated beside
policy.Syncand would report a commit that never happened. Taking the lock inSynchronizeis not the fix, since committing a claim calls out to the runtimewith that lock held. Instead the plugin refuses claims until
SynchronizecallsAllowClaims(), and the kubelet retries. The flag is never cleared: losing theruntime connection exits the process.
Those refusals are per request, not per claim — nothing is wrong with the
individual claims, and a request with no answer is what the kubelet retries.
Everything else is answered per claim, because the kubelet records the answers
per claim and retries only the ones that failed.
The library bump
v0.37 is what
Device.ShareIDandDeviceRequestAllocationResult.ConsumedCapacityneed, the two fields a claimagainst a device with consumable capacity is answered with. The plugin interface
grew
WatchHealthStatus, which we decline: our devices are the node's own CPUsand memory. Importing CDI is also the first thing in the tree to pull in
runtime-tools, whosereplacepin — inherited, with no importer ever since —does not compile against the
runtime-specalready here, so it goes.Testing
go test ./...andgo test -race ./pkg/resmgr/...pass, and each commit buildsand tests green on its own with
go.modtidy. The spec store and both handlersare covered: the devices a claim is answered with, other drivers' results left
alone, per-claim isolation, rollback at each failure point, a re-prepare and a
failed re-prepare, both commit-failure paths, and the gate in both directions
including the
Synchronizeline that opens it. Every assertion written for theordering and the gates was checked against the mutation it exists to catch.