Skip to content

DRA driver skeleton - #788

Merged
klihub merged 4 commits into
containers:mainfrom
bart0sh:PR003-dra-driver-skeleton
Sep 18, 2026
Merged

klihub merged 4 commits into
containers:mainfrom
bart0sh:PR003-dra-driver-skeleton

Conversation

@bart0sh

@bart0sh bart0sh commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

Add a DRA driver skeleton to the resource manager

This PR adds DRA driver - registration, ResourceSlice publishing and the two claim entry points — and wires it into the resource manager behind a dra.enabled configuration option that defaults to off. No policy publishes devices yet, so with this PR alone an enabled driver registers and publishes an empty ResourceSlice. Policies get to say what they provide in the PRs that follow.

Why the driver belongs to the resource manager

The driver is node-scoped infrastructure: one plugin registration, one socket, one ResourceSlice publisher per node, all of which outlive any particular allocation decision. Device semantics — what a device is, which ones exist,
what allocating one means — belong to the active policy. So pkg/resmgr/dra knows how to be a DRA driver and nothing about CPUs, memory or cache; it never inspects a device's attributes. The package comment states that boundary, and the tests assert it.

What is here

  • pkg/resmgr/dra — the plugin: New, Start, an idempotent Stop, and PrepareResourceClaims/UnprepareResourceClaims. Built on k8s.io/dynamic-resource-allocation/kubeletplugin.
  • dra.enabled in the common resource manager configuration, exposed by all three policy CRDs. "Common" here means the resource manager reads the switch from one place because it owns the driver — each policy CRD still carries its own spec.dra.enabled, so DRA is enabled per policy (and per node group, via the usual config CR layering), not cluster-wide.
  • resource manager wiring: setupDRA/startDRA from start(), Stop() from shutdown.
  • Helm: the resource.k8s.io/resourceslices RBAC and the kubelet plugin and plugin-registry host mounts, in all three charts, gated on config.dra.enabled so a disabled deployment renders exactly as before.

Details worth a reviewer's attention

The driver is named after the active policy — topology-aware.nri.io. The published devices are the policy's, so a node running a different policy publishes devices of a different kind, and a DeviceClass selecting on device.driver stays specific without further qualification. The cost is that switching a node's policy orphans the old driver's ResourceSlices until the node object goes away.

The plugin takes the resource manager's lock directly. dra.Options has a sync.Locker, and the resource manager passes itself: it embeds sync.RWMutex already. Every kubelet request takes that lock, which serializes claim handling against NRI request handling.

Stop() stops the plugin before taking the lock. Helper.Stop() drains the gRPC handlers in flight, and a handler arriving mid-drain blocks on the lock, so stopping the plugin under the lock deadlocks. There is a test for the ordering,
not just a comment: it starts a real plugin against a fake clientset, holds the lock to stand in for a request being served, and waits for the plugin's socket to disappear.

Turning DRA on or off at runtime is refused, with a message asking for a restart. Both directions have to happen with the lock released, and reconfiguration holds it.

Missing cluster access degrades rather than fails. A plugin configured from a local file has no kubernetes client and no node name; enabling DRA there logs a warning and leaves DRA off instead of refusing to start.

Testing

go test ./... passes. Unit tests cover the plugin (registration, double start, idempotent stop, both claim entry points, and the boundary property that device attributes are never read), the configuration option across all three policy types, and the resource manager wiring including the shutdown ordering. helm template and helm lint verified on all three charts with DRA both enabled and disabled.

An end-to-end test arrives with the policy-side implementation, and will skip cleanly on clusters without the required feature gates.

@bart0sh
bart0sh force-pushed the PR003-dra-driver-skeleton branch from 8abfa6f to 70f2a87 Compare September 15, 2026 15:31
@bart0sh
bart0sh marked this pull request as ready for review September 15, 2026 16:00
@bart0sh

bart0sh commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator Author

/cc @klihub @askervin

@klihub
klihub requested review from askervin and klihub September 15, 2026 16:14
Comment thread pkg/apis/config/v1alpha1/dra.go

@klihub klihub left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bart0sh I did a first skim through and I haven't spotted anything off. I'll do one more with more fresh eyes tomorrow.

Comment thread pkg/resmgr/resource-manager.go
@bart0sh
bart0sh force-pushed the PR003-dra-driver-skeleton branch 2 times, most recently from b0d6ae8 to 5cea989 Compare September 17, 2026 08:56
Add the kubelet-facing side of a DRA driver: registration, the gRPC
lifecycle, and publishing a single empty ResourceSlice so the driver is
visible in the cluster. Claims are answered with empty results for now,
under a lock provided by the owner, so kubelet requests serialize
against NRI ones.

The helper reports two very different things through HandleError:
ResourceSlice publications it will retry, and its gRPC servers giving
up. Tell the two apart with kubeletplugin.ErrRecoverable, log the
recoverable ones, and ask the owner to shut down on the rest. Otherwise
the driver stays registered with kubelet without being able to serve it,
and nothing we could do here would bring it back.

Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
Add a DRA section to the common resource manager configuration, with a
single option for turning the DRA driver on. It defaults to off, so
existing deployments register no driver and publish no ResourceSlices.

Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
Create and start the kubelet plugin from the resource manager as its
owner: the plugin takes the resource manager's lock, so kubelet requests
serialize against NRI ones, and asks it to shut down when it runs into
an error it cannot recover from. Enabling or disabling DRA needs a
restart. Add the RBAC and host mounts the driver needs to the helm
charts.

Shutting down on request stops the config agent, which unwinds Start()
the same way a SIGTERM does. Route the signal handler through the same
call, so both paths shut down identically.

Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
@bart0sh
bart0sh force-pushed the PR003-dra-driver-skeleton branch from 5cea989 to 9e17251 Compare September 17, 2026 16:00
@bart0sh

bart0sh commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator Author

@klihub Rebased on top of fresh main. Updated HandleError to properly process unrecoverable driver errors. PTAL.

@klihub klihub left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bart0sh Still looking good to me. Let me read this once more tomorrow morning, and I'd like to give @askervin also the opportunity to do so, if he has some spare cycles. We can then chat about it if we spot anything in our sync call.

@klihub
klihub self-requested a review September 18, 2026 10:22

@klihub klihub left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@askervin askervin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread pkg/apis/config/v1alpha1/dra.go Outdated
// the active policy provides. A policy which provides no devices leaves a
// registered driver with no devices, which claims cannot be made against.
// +optional
Enabled bool `json:"enabled,omitempty"`

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bart0sh, @klihub, what do you think, would it enable being more user-friendly in the next DRA steps, if DRAConfig.Enabled would be *bool instead of bool?

I'm considering if we could avoid a small piece of user-facing configuration complexity (as dependencies between configuration options), and pay the price in the complexity of policies. That is, if a user has given a policy configuration that clearly states "I want to publish _____ as a DRA resource", then the policy could enable DRA, unless DRAConfig.Enabled has been explicitly set to false. With *bool, DRAConfig.Enabled == nil could be interpreted as "false unless needed by some other option". I don't know yet about the topology-aware policy, but I'm absolutely sure that at least the balloons policy will have per-balloonType DRA parameters...

On one hand, this may sound and be a little thing in the configuration, but on the other hand, I see that they are piling up. For instance, if a balloons user configures "preferCloseToDevices: podresourceapi: vendor.com/gpu", it is obvious that the user wants her container near a GPU. However, balloons requires that user configures the main switch for kubelet pod resources API (agent.podResourceAPI: true), too, otherwise her preferCloseToDevices will be just wishful thinking.

That said, I'm fine merging this PR as is, or with simple bool -> *bool change with no other changes, because building a way for a policy to either modify common configuration, or express wishes/new defaults on it, is far from the purpose of this and follow-up PRs. But I'm hoping we'd be able to keep user configuration complexity minimal, as (especially with balloons) it's already pretty complex.

@bart0sh bart0sh Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@askervin Good point, thanks! Enabled is now a *bool (see the latest commit in this PR).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bart0sh, @klihub, what do you think, would it enable being more user-friendly in the next DRA steps, if DRAConfig.Enabled would be *bool instead of bool?

Yes. I think unless there is a pressing reason, it is better to idiomatically always go for a pointer instead of a direct value/scalar in these cases. That allows us to change default behavior later, without using kubebuilder tags.

Unset means off, but stays distinguishable from an explicit false, so that
a policy whose own configuration asks for DRA devices can later turn the
driver on without overriding a user who has turned it off.

Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
@bart0sh
bart0sh force-pushed the PR003-dra-driver-skeleton branch from 220da24 to fbdc752 Compare September 18, 2026 13:21
@klihub
klihub merged commit f31747a into containers:main Sep 18, 2026
15 checks passed
This was referenced Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants