You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #2401 (closing #1253) wired the DRA kubelet-plugin eviction contract by writing one node label into two places:
nvidia-dra-driver-gpu kubelet-plugin nodeSelector — the plugin only runs on labeled nodes
gpu-operatordriver.manager.env.NODE_LABEL_FOR_GPU_POD_EVICTION — the driver-manager knows which pods to evict before a driver upgrade
The design is sound. The driver-manager deschedules the plugin by blanking the label and reschedules by restoring it, so the label must gate placement for the mechanism to work at all. nvidia.com/dra-kubelet-plugin=true in the nodeSelector is load-bearing, not incidental.
The problem is the failure mode, not the design. Deploying a bundle onto GPU nodes that do not carry the label produces:
nvidia-dra-driver-gpu-kubelet-plugin DaemonSet at DESIRED=0
no DRA kubelet plugins on any node
no ResourceSlices — so no ComputeDomain/IMEX capability
no error anywhere.helm upgrade/install reports success and deploy.sh exits 0.
Nothing the operator runs mentions the requirement. Verified on a generated bundle:
README.md — no mention
deploy.sh — no mention
the only occurrence is 015-nvidia-dra-driver-gpu/values.yaml:18, as a nodeSelector entry
The prerequisite is documented (docs/user/cli-reference.md:1643, docs/user/bundling.md:197) but only in pages an operator would have to already know to consult.
Observed
EKS GB300 cluster (aws-us-east-2-nhensley-gb300), 2026-08-28. An AICR stack deployed 2026-08-26 — before #2401 merged — had a working kubelet-plugin DaemonSet selecting on nodeGroup=gpu-worker alone, 2/2 ready.
Regenerating the bundle from current main and running helm upgrade on gpu-operator and nvidia-dra-driver-gpu added the second selector. Both upgrades reported Upgrade complete. Both kubelet plugins silently disappeared; the DaemonSet went to DESIRED=0.
The driver-manager was not at fault — its logs show correct save/restore behaviour:
21:45:57 Current value of "nvidia.com/dra-kubelet-plugin"= <- already empty
21:50:34 Rescheduling all GPU clients on the current node by enabling their component-specific nodeSelector labels
It captured the pre-existing (empty) value and faithfully restored it. There was simply nothing to restore.
Applying the label resolved it completely — DESIRED 0 → 2, both plugins Running, ResourceSlices published within ~40s:
Pure timing. The cluster's stack was deployed 2026-08-26; #2401 merged 2026-08-27 16:27 PDT. Revision 2 of the deployed DRA release carried kubeletPlugin.nodeSelector: {"nodeGroup": "gpu-worker"} with no eviction label, so the original bundle predates the change. The upgrade described above was the first deployment anywhere on this cluster to carry the new selector.
Expected to affect fresh installs too — inferred, not yet observed
A fresh ./deploy.sh onto unlabelled nodes should fail identically: the plugin never schedules, DESIRED=0, no error. Upgrade is worse only in that working functionality disappears rather than never appearing.
Stated precisely: this has not been demonstrated. No fresh install with a post-#2401 bundle has been run. The inference rests on three verified facts — the selector is present in the rendered values, the bundle's README.md and deploy.sh never mention the label, and nothing in recipes/ writes that label (no component, no nodewright-customizations, no manifest), so no automation would rescue a fresh install.
Worth confirming on a clean cluster before deciding scope: if fresh installs are somehow unaffected, this narrows to the upgrade path and the fix is smaller.
The durable risk is node lifecycle
A one-off kubectl label is a repair, not a configuration. It does not survive:
node replacement or recycling
cluster autoscaling adding GPU nodes
a nodegroup scaled from zero
Any GPU node added afterwards arrives unlabeled and silently runs without the DRA kubelet plugin, leaving the cluster in a partially-DRA-enabled state — worse than uniform failure, because it is intermittent and node-dependent.
The label therefore belongs in the node pool definition (EKS managed nodegroup labels, Karpenter nodeClass, etc.), alongside nodeGroup=gpu-worker which is already provisioned that way.
Proposed
Any one of these would close the silent-failure gap; the first is closest to existing precedent.
Emit a bundle-time warning, matching what aicr bundle already does for StorageClass: when the DRA and GPU Operator components are both enabled and the eviction label is applied, warn that every GPU node must carry it and that the plugin will not schedule otherwise. aicr bundle already warns when a PVC would depend on unverifiable cluster state (docs/user/cli-reference.md:1684) — this is the same class of dependency and currently gets nothing.
Surface it in the bundle artifact — a line in the generated README.md, and/or a pre-flight check in deploy.sh that fails loudly when a rendered nodeSelector matches zero nodes.
Documentation updates, which are needed regardless of which mechanism above is chosen:
docs/user/bundling.md (around L197) and docs/user/cli-reference.md (around L1643) currently present the labelling as a one-off kubectl label node step. Both should state that the label must be applied at node-pool provisioning time — EKS managed nodegroup labels, Karpenter nodeClass, or equivalent — because an ad hoc label does not survive node replacement, recycling, autoscaling, or a nodegroup scaled from zero.
Both should call out the existing-cluster upgrade case explicitly. The current text reads as a fresh-install prerequisite, so an operator regenerating a bundle and running helm upgrade has no reason to revisit it — which is exactly how this was hit.
Both should state the failure mode: an unlabelled node yields DESIRED=0, no ResourceSlices, and no error from Helm or deploy.sh, so the absence is not self-announcing.
docs/integrator/ deployment guides that walk through node-pool creation should include the label alongside the existing nodeGroup=gpu-worker guidance, so it is set where the other required node labels are set.
Whichever warning is added in (1) or (2) should be documented next to the existing StorageClass warning in docs/user/cli-reference.md:1684, so the two cluster-state dependencies are described in one place.
Problem
PR #2401 (closing #1253) wired the DRA kubelet-plugin eviction contract by writing one node label into two places:
nvidia-dra-driver-gpukubelet-pluginnodeSelector— the plugin only runs on labeled nodesgpu-operatordriver.manager.env.NODE_LABEL_FOR_GPU_POD_EVICTION— the driver-manager knows which pods to evict before a driver upgradeThe design is sound. The driver-manager deschedules the plugin by blanking the label and reschedules by restoring it, so the label must gate placement for the mechanism to work at all.
nvidia.com/dra-kubelet-plugin=truein thenodeSelectoris load-bearing, not incidental.The problem is the failure mode, not the design. Deploying a bundle onto GPU nodes that do not carry the label produces:
nvidia-dra-driver-gpu-kubelet-pluginDaemonSet atDESIRED=0ResourceSlices— so no ComputeDomain/IMEX capabilityhelm upgrade/installreports success anddeploy.shexits 0.Nothing the operator runs mentions the requirement. Verified on a generated bundle:
README.md— no mentiondeploy.sh— no mention015-nvidia-dra-driver-gpu/values.yaml:18, as anodeSelectorentryThe prerequisite is documented (
docs/user/cli-reference.md:1643,docs/user/bundling.md:197) but only in pages an operator would have to already know to consult.Observed
EKS GB300 cluster (
aws-us-east-2-nhensley-gb300), 2026-08-28. An AICR stack deployed 2026-08-26 — before #2401 merged — had a working kubelet-plugin DaemonSet selecting onnodeGroup=gpu-workeralone, 2/2 ready.Regenerating the bundle from current
mainand runninghelm upgradeongpu-operatorandnvidia-dra-driver-gpuadded the second selector. Both upgrades reportedUpgrade complete. Both kubelet plugins silently disappeared; the DaemonSet went toDESIRED=0.The driver-manager was not at fault — its logs show correct save/restore behaviour:
It captured the pre-existing (empty) value and faithfully restored it. There was simply nothing to restore.
Applying the label resolved it completely —
DESIRED0 → 2, both pluginsRunning, ResourceSlices published within ~40s:Why this had not been seen before
Pure timing. The cluster's stack was deployed 2026-08-26; #2401 merged 2026-08-27 16:27 PDT. Revision 2 of the deployed DRA release carried
kubeletPlugin.nodeSelector: {"nodeGroup": "gpu-worker"}with no eviction label, so the original bundle predates the change. The upgrade described above was the first deployment anywhere on this cluster to carry the new selector.Expected to affect fresh installs too — inferred, not yet observed
A fresh
./deploy.shonto unlabelled nodes should fail identically: the plugin never schedules,DESIRED=0, no error. Upgrade is worse only in that working functionality disappears rather than never appearing.Stated precisely: this has not been demonstrated. No fresh install with a post-#2401 bundle has been run. The inference rests on three verified facts — the selector is present in the rendered values, the bundle's
README.mdanddeploy.shnever mention the label, and nothing inrecipes/writes that label (no component, nonodewright-customizations, no manifest), so no automation would rescue a fresh install.Worth confirming on a clean cluster before deciding scope: if fresh installs are somehow unaffected, this narrows to the upgrade path and the fix is smaller.
The durable risk is node lifecycle
A one-off
kubectl labelis a repair, not a configuration. It does not survive:Any GPU node added afterwards arrives unlabeled and silently runs without the DRA kubelet plugin, leaving the cluster in a partially-DRA-enabled state — worse than uniform failure, because it is intermittent and node-dependent.
The label therefore belongs in the node pool definition (EKS managed nodegroup
labels, KarpenternodeClass, etc.), alongsidenodeGroup=gpu-workerwhich is already provisioned that way.Proposed
Any one of these would close the silent-failure gap; the first is closest to existing precedent.
aicr bundlealready does for StorageClass: when the DRA and GPU Operator components are both enabled and the eviction label is applied, warn that every GPU node must carry it and that the plugin will not schedule otherwise.aicr bundlealready warns when a PVC would depend on unverifiable cluster state (docs/user/cli-reference.md:1684) — this is the same class of dependency and currently gets nothing.README.md, and/or a pre-flight check indeploy.shthat fails loudly when a renderednodeSelectormatches zero nodes.docs/user/bundling.md(around L197) anddocs/user/cli-reference.md(around L1643) currently present the labelling as a one-offkubectl label nodestep. Both should state that the label must be applied at node-pool provisioning time — EKS managed nodegrouplabels, KarpenternodeClass, or equivalent — because an ad hoc label does not survive node replacement, recycling, autoscaling, or a nodegroup scaled from zero.helm upgradehas no reason to revisit it — which is exactly how this was hit.DESIRED=0, no ResourceSlices, and no error from Helm ordeploy.sh, so the absence is not self-announcing.docs/integrator/deployment guides that walk through node-pool creation should include the label alongside the existingnodeGroup=gpu-workerguidance, so it is set where the other required node labels are set.docs/user/cli-reference.md:1684, so the two cluster-state dependencies are described in one place.Out of scope
nodeSelectoris required for blank/restore to work; Auto-wire DRA kubelet-plugin eviction with GPU Operator driver upgrades #1253's contract is correct and its implementation behaved exactly as designed here.Related: #1253 (closed by #2401), #2439 (surfaced during its cluster validation; not caused by it)