Skip to content

Add GPUCluster CRD and controller for DRA-based stack#2571

Merged
karthikvetrivel merged 7 commits into
mainfrom
kv-gpuclusterconfig-crd
Jul 23, 2026
Merged

Add GPUCluster CRD and controller for DRA-based stack#2571
karthikvetrivel merged 7 commits into
mainfrom
kv-gpuclusterconfig-crd

Conversation

@karthikvetrivel

@karthikvetrivel karthikvetrivel commented Jun 23, 2026

Copy link
Copy Markdown
Member

1. Overview

We introduce a new CRD named GPUCluster and a new controller for reconciling it. Like ClusterPolicy today, it is a singleton, cluster-scoped CRD that configures the operands needed to enable GPUs in Kubernetes. GPUCluster represents the new DRA-based software-enablement stack; it is an evolution of ClusterPolicy. Unlike ClusterPolicy, it does not manage the driver or a device plugin: the driver is either preinstalled on the host or managed by NVIDIADriver CRs, and GPUs are surfaced to workloads through DRA.

A GPUCluster may coexist with a ClusterPolicy in the same cluster, with every GPU node served by exactly one of the two stacks.

2. Testing

Unit tests cover the new API, operand rendering, controller status handling, and the node-labeling logic. I also tested this end-to-end on a 2-node heterogeneous cluster (A100 + T4, Kubernetes v1.34):

  • GPUCluster-only install via Helm: all operands reconcile to ready. DRA allocation was validated for full GPUs, MIG, and adminAccess. The dra-driver-validator was verified against both host-installed and NVIDIADriver-managed drivers.
  • Coexistence: ClusterPolicy and GPUCluster run in one cluster, with one node per plane. Each node runs only its plane's operands, with extended resources on the device-plugin node and ResourceSlices on the DRA node.
  • Mode switching: flipping nvidia.com/gpu-operator.mode in either direction swaps the operand set. A shared NVIDIADriver-managed driver survives the switch without a reload.
  • Label lifecycle: driver-manager pause values survive reconciles. A node's previous-plane labels are cleaned up, and unrecognized gpu.deploy.* labels are left untouched.

For compute domains, I created a ComputeDomain CR with numNodes: 2 and a channel ResourceClaimTemplate, then ran a 2-pod indexed Job with pod anti-affinity so one pod landed on each GB200 node. I gave each pod a resource claim against the channel template, and inside each container I listed /dev/nvidia-caps-imex-channels/ to confirm containerd injected channel0 via CDI. Note that compute domains functionality requires containerd 2.x+.

3. Misc Design Notes

The driver daemonset deployed by the NVIDIADriver CR is not gated on the deploy mode so that it is not evicted and re-scheduled when the user switches modes.

The DRA kubelet-plugin daemonset is gated on nvidia.com/gpu.deploy.dra-driver rather than the mode label. The kubelet plugin must outlive every pod holding a gpu.nvidia.com ResourceClaim. Unpreparing a claim requires the plugin, so if it unregisters before the claim holders are gone, those pods get stuck in a Terminating state. Gating the daemonset on the mode label would evict the plugin at the instant of a mode switch, before the workloads drained by that switch have terminated. Instead, the node-labeling controller defers removal of the gpu.deploy.dra-driver label until no pod on the node still holds a GPU claim (terminating pods and admin-access claims count, since unpreparing them also requires the plugin), so the kubelet plugin is always the last DRA component to leave the node.

4. Next Steps

PRs to land:

After we have a new validator daemonset, this PR can be marked as ready:


Moved from #2513 (re-created with the head branch on NVIDIA/gpu-operator instead of a fork, to enable stacked PRs). The earlier review discussion — including the GPUClusterConfigGPUCluster naming suggestion, since adopted — lives in #2513.

Comment thread deployments/gpu-operator/values.yaml Outdated
Comment thread deployments/gpu-operator/templates/cleanup_crd.yaml
Comment thread deployments/gpu-operator/values.yaml Outdated
Comment thread api/nvidia/v1alpha1/gpuclusterconfig_types.go Outdated
Comment thread api/nvidia/v1alpha1/gpuclusterconfig_types.go Outdated
Comment thread api/nvidia/v1alpha1/gpuclusterconfig_types.go Outdated
Comment thread internal/state/dra_driver.go Outdated
Comment thread manifests/state-dra-driver/0500_daemonset.yaml Outdated
Comment thread manifests/state-dra-driver/0500_daemonset.yaml
Comment thread manifests/state-dra-driver/0500_daemonset.yaml Outdated
Comment thread manifests/state-gfd/0400_resourceclaimtemplate.yaml
@karthikvetrivel
karthikvetrivel force-pushed the kv-gpuclusterconfig-crd branch from 5691bbc to e5dcecd Compare July 1, 2026 15:24
@coveralls

coveralls commented Jul 1, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 33.236% (+1.3%) from 31.955% — kv-gpuclusterconfig-crd into main

@karthikvetrivel
karthikvetrivel force-pushed the kv-gpuclusterconfig-crd branch 4 times, most recently from a4c09b7 to 6b5ac48 Compare July 2, 2026 19:50
@karthikvetrivel karthikvetrivel changed the title Add GPUClusterConfig CRD and controller for DRA-based stack Add GPUCluster CRD and controller for DRA-based stack Jul 2, 2026
@karthikvetrivel
karthikvetrivel marked this pull request as draft July 2, 2026 20:19
@karthikvetrivel
karthikvetrivel marked this pull request as ready for review July 6, 2026 16:48
Comment thread controllers/nodelabeling_controller.go
Comment thread controllers/nodelabeling_controller.go Outdated
Comment thread controllers/nodelabeling_controller.go Outdated
Comment thread controllers/nodelabeling_controller.go Outdated
Comment thread manifests/state-dra-validation/0500_daemonset.yaml
Comment thread bundle/manifests/gpu-operator-certified.clusterserviceversion.yaml
Comment thread assets/state-vfio-manager/0500_daemonset.yaml Outdated
Comment thread cmd/dra-driver-validator/find.go Outdated
@karthikvetrivel
karthikvetrivel force-pushed the kv-gpuclusterconfig-crd branch 2 times, most recently from 3b7cc55 to 4ad2c9d Compare July 8, 2026 18:48
Comment thread cmd/manage-crds/main.go Outdated
Comment thread deployments/gpu-operator/templates/cleanup_gpucluster.yaml
Signed-off-by: Karthik Vetrivel <kvetrivel@nvidia.com>
@karthikvetrivel
karthikvetrivel force-pushed the kv-gpuclusterconfig-crd branch 2 times, most recently from 48e44d8 to 86cd1a1 Compare July 22, 2026 21:51
Comment thread controllers/state_manager.go Outdated
Comment thread controllers/nodelabeling_controller.go
Comment thread controllers/nodelabeling_controller.go Outdated
Comment thread controllers/nodelabeling_controller.go Outdated
// its own driver rather than delegating to NVIDIADriver CRs), device-plugin nodes get no owner:
// their driver comes from the ClusterPolicy DaemonSet, and assigning an owner would land a second
// driver DaemonSet on them. On success, it returns true when any node owner label was changed.
func AssignOwners(ctx context.Context, c client.Client, classicClusterPolicyDriver bool) (bool, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not a blocker, but I am having trouble grokking this. My intuition is telling me we should only call AssignOwners() when drivers are managed by the NVIDIADriver controller. But here we are calling it even when ClusterPolicy is managing the driver daemonsets. What's the rationale here?

From the comment:

// When classicClusterPolicyDriver is true (a ClusterPolicy manages
// its own driver rather than delegating to NVIDIADriver CRs), device-plugin nodes get no owner:
// their driver comes from the ClusterPolicy DaemonSet, and assigning an owner would land a second
// driver DaemonSet on them.

If ClusterPolicy is managing the driver daemonsets, doesn't our NVIDIADriver controller's Reconcile() return early and not render any daemonsets in that case?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The classicClusterPolicyDriver=true path only exists for the mixed cluster where ClusterPolicy coexists with GPUCluster. Here, the NVIDIADriver controller is active because DRA-mode nodes get their driver from NVIDIADriver CRs, so AssignOwners() must still run to label those nodes, and the flag just makes it skip (and clear) the owner label on device-plugin-mode nodes so the ClusterPolicy's own driver DaemonSet isn't joined by a second, NVIDIADriver-rendered one.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Here, the NVIDIADriver controller is active because DRA-mode nodes get their driver from NVIDIADriver CRs

This is the source of my confusion -- A) I was under the impression that the NVIDIADriver controller is never active whenever a ClusterPolicy-backed driver is active (since the ClusterPolicy-backed driver would target ALL gpu nodes), and B) I was under the impression that the DRA-mode did not strictly require that the NVIDIADriver controller was used for driver management (it is agnostic to how drivers are installed).

Comment thread internal/state/configurable_state.go Outdated
Comment thread internal/state/configurable_state.go Outdated
Comment thread internal/state/dra_driver.go Outdated
Comment thread internal/state/dra_driver.go Outdated
Comment thread internal/state/dra_driver.go Outdated
@karthikvetrivel
karthikvetrivel force-pushed the kv-gpuclusterconfig-crd branch 2 times, most recently from 3b99f8c to 22ef265 Compare July 23, 2026 00:33
Comment thread cmd/gpu-operator/main.go Outdated
Comment thread cmd/gpu-operator/main.go Outdated
Comment thread cmd/gpu-operator/main.go Outdated
Comment thread cmd/gpu-operator/main.go Outdated
Comment thread cmd/nvidia-validator/driver.go Outdated
Comment thread cmd/nvidia-validator/driver.go Outdated
Comment thread deployments/gpu-operator/templates/gpucluster.yaml Outdated
Signed-off-by: Karthik Vetrivel <kvetrivel@nvidia.com>
Signed-off-by: Karthik Vetrivel <kvetrivel@nvidia.com>
@karthikvetrivel
karthikvetrivel force-pushed the kv-gpuclusterconfig-crd branch 3 times, most recently from 6f3a74f to db850c5 Compare July 23, 2026 17:17
Signed-off-by: Karthik Vetrivel <kvetrivel@nvidia.com>
Signed-off-by: Karthik Vetrivel <kvetrivel@nvidia.com>
@karthikvetrivel
karthikvetrivel force-pushed the kv-gpuclusterconfig-crd branch 2 times, most recently from 3fbf7cd to d5ef70f Compare July 23, 2026 18:46
Comment thread cmd/cleanup-gpuclusters/main.go
Signed-off-by: Karthik Vetrivel <kvetrivel@nvidia.com>
Signed-off-by: Karthik Vetrivel <kvetrivel@nvidia.com>
@karthikvetrivel
karthikvetrivel force-pushed the kv-gpuclusterconfig-crd branch from d5ef70f to a063aa9 Compare July 23, 2026 20:00
@tariq1890

Copy link
Copy Markdown
Contributor

To add to what others have said here already - EXCELLENT work!

This looks to be in a good shape to merge. We can address the other outstanding comments in follow-ups

@karthikvetrivel
karthikvetrivel merged commit 2a07dc4 into main Jul 23, 2026
51 of 54 checks passed
@tariq1890
tariq1890 deleted the kv-gpuclusterconfig-crd branch July 23, 2026 23:05
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.

7 participants