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
check-nvidia-smi gained a deployment-phase constraint, Deployment.gpu-driver.version, in #1995 (closed 2026-08-21). It is evaluated against the nvidia-smi banner on every verified GPU node and fails closed when declared but unmeasurable.
No recipe declares it. Not one overlay, not one mixin. The enforcement hook is built and idle.
The consequence is sharpest on the families where AICR does not control the driver at all — driver.enabled: false, so the GPU Operator installs nothing and the host driver is whatever the provider's node image ships:
driver.enabled: false only means the GPU Operator installs no driver; it does not imply the provider owns it. After #2360, gpuStack=bundle-installer enables gcp-driver-installer, so AICR owns and pins the driver on that value.
bundle-installer still needs a floor: the installer's lsmod fast path exits 0 when any nvidia module is already loaded, so a pinned bump does not upgrade live nodes — an older driver persists until node replacement or reboot. A floor is what catches that.
On these, a cluster with an arbitrarily old host driver validates green: the check confirms nvidia-smi runs and reports a version, and compares it to nothing.
The example from #1995's own text is still unenforced — GKE A4X Max (GB300) requires host driver R580.95.05+, documented by Google.
This is the same missing-requirement-expression pattern as #2402 (Kubernetes floors below the DRA chart's kubeVersion): AICR installs components carrying real minimum requirements and does not express those requirements as constraints.
It is not the same failure mechanism, and this issue should not be read as claiming one. Deployment.gpu-driver.version is a post-deployment validation constraint: its absence means aicr validate cannot fail on an out-of-spec driver. It does not reject the recipe or stop Helm from deploying, whereas #2402's chart kubeVersion causes Helm to refuse installation outright.
Why now
The GPU Operator v26.7.0 bump (#2383) raises operand versions on exactly the platforms where the driver does not move:
DCGM 4.6.0-1, DCGM Exporter 4.6.0
device plugin 0.20.0, GFD 0.20.0
NVIDIA DRA driver 0.5.0 kubelet plugin
container toolkit 1.20.0 — note AKS runs toolkit.enabled: false, so the node image's toolkit must also be compatible
Each runs against a host driver AICR does not control and does not gate.
What already exists
From #1995, in validators/deployment/nvidia_smi.go:
Constraint name Deployment.gpu-driver.version; the value must carry a comparison operator (typically >=) to behave as a floor — a bare version is an exact string match.
Banner parsing handles both Driver Version: and the renamed KMD Version:, case-insensitively, including the pipe-delimited table-row layout (check-nvidia-smi fails on drivers renaming nvidia-smi banner fields #1667). Four-component versions such as 580.95.05.1 are rejected rather than silently truncated.
failClosedIfUnmeasurableGPUDriverFloor converts the ordinarily non-blocking Skip paths (no GPU nodes, all cordoned, nodes busy) into a blocking error when the constraint is declared: "a declared gate must not PASS unenforced."
With no constraint declared, the check keeps its original banner-presence behaviour and does not invent a floor.
So this issue requires no new validator code. The work is choosing floors and writing constraint lines.
Options
A. Per-family floors on the driver.enabled: false overlays (recommended)
Declare a floor on each provider-installed family, set from what that provider ships and what the accelerator requires.
Pros: floors are meaningful per platform; GB300-on-GKE can carry a genuinely high floor without holding a generic L40S cluster to it. Targets exactly the families with no other guarantee.
Cons: one decision per family; floors need revisiting as providers move their node images.
B. A single global floor in base.yaml
Pros: one line, uniform coverage including the operator-managed families.
Cons: must be the lowest common denominator across every supported accelerator and provider, so it is weakest precisely where it matters most. A floor that GB300 needs would break older L40S/A100 clusters; a floor they tolerate is meaningless for GB300.
C. Global baseline plus per-family overrides
Low floor in base.yaml, raised on families that need more.
Pros: guarantees no family is entirely ungated while allowing precision.
Cons: two places to reason about; a leaf overlay silently inheriting a weak baseline can read as "gated" when it is not.
D. Extend to the operator-managed families as well
Orthogonal to A–C. On EKS the pinned driver.version expresses intent, but the constraint detects something the pin cannot: the pinned driver not actually being what runs — a failed driver upgrade, a node that did not roll, or a pre-existing host driver shadowing the operator's.
Recommendation
Option A only. Option D is deferred — see "Option D cannot be expressed per profile value today" below.
Define floors on concrete service x accelerator leaves where a documented compatibility minimum exists, applying a floor across all profile values of an overlay only when the same minimum is valid for every value.
Note the earlier framing of "the driver.enabled: false families" was wrong and is withdrawn: on AKS and GKE COS, driver ownership is profile-selected (gpuStack), but deployment constraints are not profile-selectable today. A constraint placed on the shared overlay applies to every profile value, so it cannot selectively target the provider-managed one. The correct unit is the affected resolved family with a documented minimum.
Key floors to documented requirements, not shipped or validated versions. A provider's currently shipped version proves a floor is satisfiable; it is not the minimum, and a floor keyed to it would move whenever a node image moves. Likewise a passing 26.7.0 run with 595.91.07 proves that version works — it does not establish the lowest compatible version. NVIDIA lists R580 and R535 as supported for v26.7 alongside 595.91.07 as the recommended default, so the chart default is not the compatibility floor.
The effective floor should be the maximum documented minimum imposed by the accelerator, the active component stack, and any provider-specific configuration.
Resolve the last-wins placement question first and land matrix tests covering every combination affected by each floor (see the blocker section below). Do not gate documented floors on an exhaustive compatibility matrix for all supported recipes — that is ongoing work, not a prerequisite.
Record the source of each floor in a comment next to it (provider documentation, operand requirement, or accelerator requirement) so a later reader can tell whether it is still current.
Blocker: constraints merge last-wins, not max
This must be resolved before any floor lands. Constraints merge by name with the later overlay winning — pkg/recipe/validation.go:140-172: "Non-empty overlay unions by Name; overlay value wins on same-name." There is no version comparison and no max.
So if an accelerator leaf and a platform overlay both declare Deployment.gpu-driver.version, whichever applies later wins regardless of which floor is higher. A lower platform floor can silently downgrade a higher accelerator floor. Since GB300 requires more than its platform baseline, at least some floors are accelerator-driven, and a leaf floor must be able to raise a platform floor — which last-wins does not guarantee by construction.
Any implementation needs table-driven resolved-recipe tests asserting the final effective floor for every combination affected by that floor, including alternate profile values — not merely that a constraint exists somewhere in the chain.
Option D cannot be expressed per profile value today
Option D is a different contract — rollout convergence against the configured pin, not minimum compatibility — and is split out of this issue's scope.
It also cannot be routed through profiles as things stand, for two independent reasons:
ProfileValue.constraints are snapshot (generation-time) measurement constraints. Catalog load validates them via measurement.ValidatePath (pkg/recipe/constraint_paths.go:97), and Deployment is not a measurement Type (pkg/measurement/types.go defines K8s, GPU, OS, SystemD, NodeTopology). So Deployment.gpu-driver.version in a profile value is rejected at load.
Even bypassing that, it would land in the wrong place. Profile constraints append to top-level mergedSpec.Constraints (pkg/recipe/profile_resolution.go), while check-nvidia-smi reads only validation.deployment.constraints via findDeploymentConstraint (validators/deployment/gpu_operator_version.go:67-77). Two distinct fields.
Consequence: adding a KeyGPUDriver producer would not unblock profile-specific deployment floors. It would enable a generation-time snapshot constraint for an already-installed driver — and that would additionally require adding KeyGPUDriver to TypeGPU's closed key set in pkg/measurement/catalog.go:153-160, which today lists only KeyGPUPresent, KeyGPUCount, KeyGPUDriverLoaded, KeyGPUDetectionSource, KeyGPUModel.
A snapshot-side floor is a weaker and different guarantee than a deployment-phase one (it checks the snapshotted cluster at generation, not the running cluster after install), and profile constraints fail closed when unmeasurable, so older snapshots lacking the field would break generation.
Profile-specific deployment floors therefore need explicit profile-to-deployment-phase routing or selected-profile-aware validator logic. Option D also interacts with the documented --set gpuoperator:driver.version=... override: a floor pinned to the configured version would reject a downward override, which may be desirable but is a documented behaviour change.
Related
#1995 (validator hook, closed — this is the consuming half), #2402 (same defect class, Kubernetes floors), #2383 (v26.7.0 bump and driver 595.91.07, whose validation should inform the floors), #1716 (driver installation on GKE COS), #1873 (driver ownership coherence).
Problem
check-nvidia-smigained a deployment-phase constraint,Deployment.gpu-driver.version, in #1995 (closed 2026-08-21). It is evaluated against thenvidia-smibanner on every verified GPU node and fails closed when declared but unmeasurable.No recipe declares it. Not one overlay, not one mixin. The enforcement hook is built and idle.
The consequence is sharpest on the families where AICR does not control the driver at all —
driver.enabled: false, so the GPU Operator installs nothing and the host driver is whatever the provider's node image ships:gpuStack=azure-managedgpuStack=gke-defaultgpuStack=bundle-installergcp-driver-installer, pinned580.173.02(COS-qualified)driver.enabled: falseonly means the GPU Operator installs no driver; it does not imply the provider owns it. After #2360,gpuStack=bundle-installerenablesgcp-driver-installer, so AICR owns and pins the driver on that value.bundle-installerstill needs a floor: the installer'slsmodfast path exits 0 when any nvidia module is already loaded, so a pinned bump does not upgrade live nodes — an older driver persists until node replacement or reboot. A floor is what catches that.On these, a cluster with an arbitrarily old host driver validates green: the check confirms
nvidia-smiruns and reports a version, and compares it to nothing.The example from #1995's own text is still unenforced — GKE A4X Max (GB300) requires host driver R580.95.05+, documented by Google.
This is the same missing-requirement-expression pattern as #2402 (Kubernetes floors below the DRA chart's
kubeVersion): AICR installs components carrying real minimum requirements and does not express those requirements as constraints.It is not the same failure mechanism, and this issue should not be read as claiming one.
Deployment.gpu-driver.versionis a post-deployment validation constraint: its absence meansaicr validatecannot fail on an out-of-spec driver. It does not reject the recipe or stop Helm from deploying, whereas #2402's chartkubeVersioncauses Helm to refuse installation outright.Why now
The GPU Operator v26.7.0 bump (#2383) raises operand versions on exactly the platforms where the driver does not move:
4.6.0-1, DCGM Exporter4.6.00.20.0, GFD0.20.00.5.0kubelet plugin1.20.0— note AKS runstoolkit.enabled: false, so the node image's toolkit must also be compatibleEach runs against a host driver AICR does not control and does not gate.
What already exists
From #1995, in
validators/deployment/nvidia_smi.go:Deployment.gpu-driver.version; the value must carry a comparison operator (typically>=) to behave as a floor — a bare version is an exact string match.Driver Version:and the renamedKMD Version:, case-insensitively, including the pipe-delimited table-row layout (check-nvidia-smi fails on drivers renaming nvidia-smi banner fields #1667). Four-component versions such as580.95.05.1are rejected rather than silently truncated.failClosedIfUnmeasurableGPUDriverFloorconverts the ordinarily non-blocking Skip paths (no GPU nodes, all cordoned, nodes busy) into a blocking error when the constraint is declared: "a declared gate must not PASS unenforced."So this issue requires no new validator code. The work is choosing floors and writing constraint lines.
Options
A. Per-family floors on the
driver.enabled: falseoverlays (recommended)Declare a floor on each provider-installed family, set from what that provider ships and what the accelerator requires.
B. A single global floor in
base.yamlC. Global baseline plus per-family overrides
Low floor in
base.yaml, raised on families that need more.D. Extend to the operator-managed families as well
Orthogonal to A–C. On EKS the pinned
driver.versionexpresses intent, but the constraint detects something the pin cannot: the pinned driver not actually being what runs — a failed driver upgrade, a node that did not roll, or a pre-existing host driver shadowing the operator's.Recommendation
Option A only. Option D is deferred — see "Option D cannot be expressed per profile value today" below.
Define floors on concrete service x accelerator leaves where a documented compatibility minimum exists, applying a floor across all profile values of an overlay only when the same minimum is valid for every value.
Note the earlier framing of "the
driver.enabled: falsefamilies" was wrong and is withdrawn: on AKS and GKE COS, driver ownership is profile-selected (gpuStack), but deployment constraints are not profile-selectable today. A constraint placed on the shared overlay applies to every profile value, so it cannot selectively target the provider-managed one. The correct unit is the affected resolved family with a documented minimum.Key floors to documented requirements, not shipped or validated versions. A provider's currently shipped version proves a floor is satisfiable; it is not the minimum, and a floor keyed to it would move whenever a node image moves. Likewise a passing 26.7.0 run with
595.91.07proves that version works — it does not establish the lowest compatible version. NVIDIA lists R580 and R535 as supported for v26.7 alongside595.91.07as the recommended default, so the chart default is not the compatibility floor.The effective floor should be the maximum documented minimum imposed by the accelerator, the active component stack, and any provider-specific configuration.
Resolve the last-wins placement question first and land matrix tests covering every combination affected by each floor (see the blocker section below). Do not gate documented floors on an exhaustive compatibility matrix for all supported recipes — that is ongoing work, not a prerequisite.
Record the source of each floor in a comment next to it (provider documentation, operand requirement, or accelerator requirement) so a later reader can tell whether it is still current.
Blocker: constraints merge last-wins, not max
This must be resolved before any floor lands. Constraints merge by name with the later overlay winning —
pkg/recipe/validation.go:140-172: "Non-empty overlay unions by Name; overlay value wins on same-name." There is no version comparison and no max.So if an accelerator leaf and a platform overlay both declare
Deployment.gpu-driver.version, whichever applies later wins regardless of which floor is higher. A lower platform floor can silently downgrade a higher accelerator floor. Since GB300 requires more than its platform baseline, at least some floors are accelerator-driven, and a leaf floor must be able to raise a platform floor — which last-wins does not guarantee by construction.Any implementation needs table-driven resolved-recipe tests asserting the final effective floor for every combination affected by that floor, including alternate profile values — not merely that a constraint exists somewhere in the chain.
Option D cannot be expressed per profile value today
Option D is a different contract — rollout convergence against the configured pin, not minimum compatibility — and is split out of this issue's scope.
It also cannot be routed through profiles as things stand, for two independent reasons:
ProfileValue.constraintsare snapshot (generation-time) measurement constraints. Catalog load validates them viameasurement.ValidatePath(pkg/recipe/constraint_paths.go:97), andDeploymentis not a measurementType(pkg/measurement/types.godefinesK8s,GPU,OS,SystemD,NodeTopology). SoDeployment.gpu-driver.versionin a profile value is rejected at load.mergedSpec.Constraints(pkg/recipe/profile_resolution.go), whilecheck-nvidia-smireads onlyvalidation.deployment.constraintsviafindDeploymentConstraint(validators/deployment/gpu_operator_version.go:67-77). Two distinct fields.Consequence: adding a
KeyGPUDriverproducer would not unblock profile-specific deployment floors. It would enable a generation-time snapshot constraint for an already-installed driver — and that would additionally require addingKeyGPUDrivertoTypeGPU's closed key set inpkg/measurement/catalog.go:153-160, which today lists onlyKeyGPUPresent,KeyGPUCount,KeyGPUDriverLoaded,KeyGPUDetectionSource,KeyGPUModel.A snapshot-side floor is a weaker and different guarantee than a deployment-phase one (it checks the snapshotted cluster at generation, not the running cluster after install), and profile constraints fail closed when unmeasurable, so older snapshots lacking the field would break generation.
Profile-specific deployment floors therefore need explicit profile-to-deployment-phase routing or selected-profile-aware validator logic. Option D also interacts with the documented
--set gpuoperator:driver.version=...override: a floor pinned to the configured version would reject a downward override, which may be desirable but is a documented behaviour change.Related
#1995 (validator hook, closed — this is the consuming half), #2402 (same defect class, Kubernetes floors), #2383 (v26.7.0 bump and driver
595.91.07, whose validation should inform the floors), #1716 (driver installation on GKE COS), #1873 (driver ownership coherence).