The module lifecycle stage: General Availability
The module has requirements for installation
The module operates in two mutually exclusive modes, selected by the dra.enabled parameter:
- DRA mode (
dra.enabled: true) — the recommended mode, in Preview; enabled explicitly. GPUs are requested through the Kubernetes API using ResourceClaim resources. - Device Plugin mode — the default mode, it works without extra configuration. GPUs are requested through the
nvidia.com/gpuextended resource, and sharing is configured per NodeGroup.
Both modes deploy into namespace d8-nvidia-gpu.
DRA mode
DRA mode is in Preview. It is available for use, but its parameters and behaviour may still change in future releases.
Components
The module separates a vendor-agnostic core from per-vendor adapters. The core knows nothing about any specific GPU brand; everything that touches vendor hardware lives behind a contract implemented by a vendor adapter.
In DRA mode the module creates the following components:
| Component | Kind | Vendor-specific | What it does |
|---|---|---|---|
gpu-controller |
Deployment (up to 3 replicas, leader-elected) | no | Cluster-level controller. Reconciles PhysicalGPU and GPUClass, generates DeviceClass objects, and serves the module’s admission webhooks. Communicates with adapters only through the PhysicalGPU CRD. Runs on master nodes. |
gpu-node-agent |
DaemonSet | no | GPU discovery. Reads host /sys and the PCI ID database, matches devices against the gpu-supported-vendors ConfigMap, creates one PhysicalGPU per card, and labels the node gpu.deckhouse.io/vendor=<vendor>. Runs on all non-control-plane nodes, resync every 5 minutes. |
dra-plugin |
container in every vendor adapter Pod | no | The kubelet DRA plugin. One image shared by all vendors. |
| vendor adapter | DaemonSet | yes | The node-side hardware layer for one vendor. Ships as nvidia-adapter and metax-adapter. See Vendor adapters. |
gpu-dcgm, gpu-dcgm-exporter |
DaemonSet | yes (NVIDIA) | DCGM telemetry and its Prometheus exporter. DCGM is NVIDIA’s tool; other vendors would ship their own exporter alongside their adapter. |
The module works through discovery: gpu-node-agent runs everywhere and labels each node with the vendor it found, and every vendor adapter is scheduled by a nodeSelector on that label. A node with no supported GPU gets no adapter at all.
Vendor adapters
A vendor adapter is a DaemonSet with two working containers plus a metrics guard:
| Container | Vendor-specific | What it does |
|---|---|---|
dra-plugin |
no | Registers with kubelet under /var/lib/kubelet/plugins/gpu.deckhouse.io, implements NodePrepareResources / NodeUnprepareResources, and publishes ResourceSlice objects built from PhysicalGPU. Delegates every hardware operation to the vendor adapter container over a Unix socket inside the Pod. |
vendor adapter (nvidia-adapter, metax-adapter) |
yes | Talks to the hardware. Reads capabilities, generates CDI specs, performs partitioning and passthrough, and enriches PhysicalGPU status. For NVIDIA this is the nvidia-adapter container, which uses NVML. |
kube-rbac-proxy |
no | Guards the metrics endpoint. |
The adapter implements a Backend contract with three mandatory methods: the vendor name, a capabilities reader, and a CDI writer. Everything beyond that is an optional capability interface, so a vendor implements only what its hardware can actually do:
| Capability | What it covers | NVIDIA |
|---|---|---|
PowerManager |
Reading and setting power limits | NVML |
HealthMonitor |
Hardware health events | XID events |
Partitioner |
Splitting a card into isolated partitions | MIG |
PassthroughManager |
Handing the raw device to a VM | vfio-pci |
SharingManager |
Concurrent and time-shared access | MPS, time-slicing |
ProcessInspector |
Which processes hold the GPU | NVML |
UUIDResolver |
Device UUID | NVML |
CDIBaseSpecProvider, CDIHookResolver |
Base CDI spec and hook path | yes |
What a vendor implements is visible in the opaque device configs its adapter registers. NVIDIA registers GpuConfig, MigDeviceConfig and VfioDeviceConfig; MetaX registers GpuConfig and VfioDeviceConfig, so whole cards and passthrough work there but partitioning does not. A claim carrying a config kind no adapter registered is rejected by the admission webhook. For module capabilities by vendor, see Module capabilities by GPU vendor.
To add a vendor, write a container against that contract, add its PCI vendor ID to the gpu-supported-vendors ConfigMap, and ship an adapter DaemonSet. The CRD does not change, and neither does any core component.
Adapters ship for NVIDIA (10de) and MetaX (9999). Discovery also recognises AMD (1002) and Intel (8086), so cards from those vendors appear as PhysicalGPU objects, stay in phase Pending, and are never published for allocation (because their capabilities are not read).
DRA workloads receive their GPUs through CDI injection under the default container runtime. The nvidia RuntimeClass that the module ships is used only by the DCGM DaemonSets — normal DRA workloads must not set runtimeClassName: nvidia.
Conditions for enabling the mode
Three conditions decide what gets deployed. They do not gate one and the same set of templates:
| Condition | Set by | Meaning |
|---|---|---|
dra.enabled |
your ModuleConfig | DRA mode requested. |
internal.migrationReady |
the check_migration hook |
The d8-nvidia-gpu namespace is labeled gpu.deckhouse.io/managed-by=gpu, so the module owns it. |
internal.draFeatureGatesReady |
the dra_preflight hook |
All required DRA feature gates are actually enabled in the cluster. |
To find out which condition is blocking deployment, check the module conditions and the alerts:
d8 k get module gpu -o jsonpath='{.status.conditions}' | jqDRA feature gates readiness
The DRA feature gates are enabled by the Deckhouse platform, not by this module. Before deploying the DRA stack, the module verifies that the gates are genuinely enabled: it reads their real state from the kube-apiserver metrics rather than inferring it from version numbers.
Required feature gates:
| Feature gate | Available since | What it carries |
|---|---|---|
DynamicResourceAllocation |
1.26 | The DRA core. |
DRAResourceClaimDeviceStatus |
1.32 | Per-device state in ResourceClaim. |
DRAPartitionableDevices |
1.33 | MIG partitions as devices over shared counters. |
DRADeviceBindingConditions |
1.34 | The pre-bind handshake that resolves placement conflicts. |
DRAConsumableCapacity |
1.34 | Shares of a card: MPS and time-slicing through a claim. |
DRAExtendedResource |
1.34 | Requesting a GPU by class name. |
Three of them arrive only in Kubernetes 1.34, which is why DRA mode needs that version even though the DRA core itself works on 1.33.
When dra.enabled: true, the module deploys the DRA workload stack — the controller, the node agent, the vendor adapters and everything that serves a ResourceClaim — only if all required DRA feature gates are enabled. Otherwise that part is not deployed, and the module reports the reason through the module condition FeatureGatesReady=False and the alert D8GpuDraFirstEnablementBlocked (or D8GpuDraFeatureGatesCheckError, when the gate state could not be read at all). Device Plugin mode is not affected by this check.
Node preparation is gated separately, and this distinction matters on a cluster where the gates are missing. The NodeGroupConfiguration scripts apply as soon as dra.enabled: true and the migration is complete, without waiting for the gates — a node still gets its containerd drop-in, its sysctl and its readiness labels, because those are reversed when the module is disabled. The two steps whose effect is not reversed — the IOMMU kernel-command-line rewrite with its reboot request, and the vfio-pci binding — are withheld while the gates are confirmed absent and the workload stack has never been deployed. So “the gates are missing” means the workload stack stays away and the irreversible half of node preparation stays away, not that nothing is rendered at all.
DRA mode requires these feature gates to be enabled by the platform. They are enabled automatically on a supported Deckhouse version; if they are not enabled, dra.enabled: true does not deploy the DRA workload stack, withholds the irreversible node-preparation steps, and raises an alert. Upgrade Deckhouse to activate DRA mode. The module does not modify control-plane or kubelet arguments.
If a required gate is switched off later while DRA mode is already active — for example by a manual change or an incomplete upgrade — the alert D8GpuDraFeatureGateDisabledOnComponent appears. This alert also covers per-kubelet drift that an apiserver-only check cannot detect.
How the module works when starting a Pod
Starting a Pod that requests a GPU includes the following stages:
gpu-node-agentdiscovers PCI devices on the node and creates a PhysicalGPU for each card, adding the labelsgpu.deckhouse.io/vendor,gpu.deckhouse.io/device,gpu.deckhouse.io/node, and the supported sharing strategies (gpu.deckhouse.io/sharing.mps,gpu.deckhouse.io/sharing.ts).- The vendor adapter for that card reads its capabilities through the vendor library — NVML on NVIDIA — fills in
.status.capabilitiesof the PhysicalGPU object (architecture, compute API, driver version, supported partition profiles), and moves the object toReady. - Once the PhysicalGPU becomes
Ready,dra-pluginpublishes ResourceSlice objects — one set of devices per node — describing the whole card, every possible partition, and their sharing variants. - An administrator optionally creates a GPUClass;
gpu-controllerturns it into a set of DeviceClass objects that users request by name or through an extended resource. - The user creates a ResourceClaim (usually via a
ResourceClaimTemplate) and references it from a Pod. The scheduler matches the claim against published devices. - On the chosen node,
dra-plugincallsNodePrepareResourcesand passes the request to the vendor adapter, which performs any reconfiguration required — on NVIDIA that means creating a MIG partition, starting an MPS control daemon, or binding the card tovfio-pci— then returns a CDI device name. - The container starts with the provided GPU. On Pod deletion the reverse path runs, and any partition created for the claim is destroyed.
Published device attributes
Devices in a ResourceSlice carry attributes in the gpu.deckhouse.io domain, and their names encode whether the device is a whole card, a MIG partition, or a sharing variant. See Device attributes and Getting information about the allocated GPU.
Every device declares bindsToNode: true with bindingConditions: ["Ready"] and bindingFailureConditions: ["BindingFailed"], so a failed preparation surfaces as a BindingFailed condition on the claim rather than a silently pending Pod.
Causes of MIG layout conflicts
MIG partitions are modelled as partitionable devices. Each node publishes a shared counter set per card (slices, slice-0…slice-7, multiprocessors, copy-engines, decoders, jpeg-engines, ofa-engines), and every device — the whole card and each possible partition — declares which counters it consumes.
Consequences:
- The scheduler enforces mutual exclusion itself. Allocating a
7gpartition consumes all slice counters, so no other partition on that card can be allocated at the same time. - MIG partitions are ephemeral. A partition exists only between
NodePrepareResourcesandNodeUnprepareResources. There is no persistent MIG layout to manage: the layout is a consequence of what is currently claimed.
PhysicalGPU lifecycle
PhysicalGPU lifecycle phases appear in .status.phase:
| Phase | Meaning |
|---|---|
Pending |
Discovered, not yet inspected by the adapter. |
Initializing |
The adapter is reading capabilities. |
Ready |
Usable; devices are published to ResourceSlice. |
Reconfiguring |
A MIG or driver-binding change is in progress. |
Passthrough |
The card is bound to vfio-pci for VFIO passthrough and is not available as a CUDA device. |
Failed |
Capabilities could not be read, or an operation failed. |
Lost |
The card disappeared from the node. |
The phase is derived, never set directly. Five conditions carry the detail:
| Condition | Meaning | Reasons |
|---|---|---|
AdapterReady |
The vendor adapter initialised and read capabilities. | NotScheduled, DriverNotReady, DriverInitFailed, ToolkitNotReady, VFIORequiresBareMetal, Ready, Lost |
HardwareHealthy |
The hardware reports no faults. | Healthy, Unhealthy, Unknown |
Reconfiguring |
A partition or driver-binding change is running. | None, Requested, Draining, InProgress, Completing, DisruptionRequired, DisruptionPending, RebootRequested |
Reclaim |
Progress of an administrator-triggered reset. | InProgress, Done, Refused, Failed |
Managed |
Why the device is, or is not, managed by the module. | See Device management state. |
Devices are published only while the phase is Ready, so an AdapterReady=False card never appears in any ResourceSlice.
Phase derivation reads the driver binding first: a card whose .status.driverBinding.mode is Passthrough becomes Passthrough regardless of its conditions, because a vfio-pci-bound card legitimately has no adapter readiness and would otherwise be misread as Initializing. For every other mode the condition table applies, so returning the card to a compute driver leaves the phase naturally.
| Conditions | Phase |
|---|---|
driverBinding.mode == Passthrough |
Passthrough (takes priority) |
AdapterReady=False/NotScheduled |
Pending |
AdapterReady=False/DriverNotReady or /ToolkitNotReady |
Initializing |
AdapterReady=False/DriverInitFailed or /VFIORequiresBareMetal |
Failed |
AdapterReady=False/Lost |
Lost |
AdapterReady=True, HardwareHealthy=False |
Failed |
AdapterReady=True, HardwareHealthy=True, Reconfiguring=True |
Reconfiguring |
AdapterReady=True, HardwareHealthy=True, Reconfiguring=False |
Ready |
Note that a passthrough request on a virtualised node fails rather than reaching Passthrough: it lands on AdapterReady=False/VFIORequiresBareMetal, which derives to Failed.
Reconfiguration progresses through Requested → Draining → InProgress → Completing → None. When a hardware transition needs the node itself disrupted, the vendor adapter raises DisruptionRequired and the controller carries it through DisruptionPending to RebootRequested.
Driver binding
.status.driverBinding records what the kernel actually has bound, and who owns the device. Its fields have split ownership through Server-Side Apply:
| Field | Owner | Meaning |
|---|---|---|
driver |
gpu-node-agent |
The raw kernel driver from sysfs — nvidia, vfio-pci, or empty when nothing is bound. Treated as ground truth. |
mode |
gpu-node-agent |
The classified serving mode: Compute, Passthrough, Unbound, or Unknown. Transport-agnostic — do not infer the transport from it. |
managementState |
gpu-controller |
Who manages the device: Managed, Excluded, Orphaned, or Unknown. |
In kubectl get physicalgpus output, the last two fields appear as the Mode and Management columns.
Device management state
managementState answers whether the module owns a device, and it is the only value that gates reclaim. The Managed condition carries the extensible reason behind it:
| Reason | Condition | managementState |
Meaning |
|---|---|---|---|
BackingAllocation |
True |
Managed |
The binding is backed by an active, owning ResourceClaim. |
ExcludedReleasePending |
False |
Managed |
An opt-out was declared but the binding is still alive, so the device is not yet reclaim-eligible. |
DeliberatelyExcluded |
False |
Excluded |
The operator opted the device out and the binding has been released. |
OrphanPending |
Unknown |
Unknown |
A stray passthrough binding was seen, but the grace period has not elapsed. Neither reclaim- nor alert-eligible. |
Orphaned |
False |
Orphaned |
A stray binding that persisted for the whole grace period. Actionable. |
Indeterminate |
Unknown |
Unknown |
Identity or occupancy could not be resolved, for example no Node or PCI address. Starts no grace clock. |
Opt a device out with the gpu.deckhouse.io/unmanaged annotation. A stray binding must hold continuously for a two-minute grace period before it is classified Orphaned, which keeps a brief race from raising a false orphan.
Request a reset with the gpu.deckhouse.io/reclaim annotation. The controller reflects progress on the Reclaim condition and refuses the request — with a reason on the condition rather than silently — when an active ResourceClaim still references the device, when the device is not Orphaned, or when its state cannot be determined.
A reclaim that starts but does not finish ends at Failed: if the card is still on a passthrough driver two minutes after the reset began, the condition reports that driverBinding.mode is still Passthrough and that a node reboot may be required. That is the outcome to watch for — the module cannot resolve it on its own.
Admission webhooks
Served by gpu-controller:
| Webhook | Objects | Failure policy | What it does |
|---|---|---|---|
gpuclass |
GPUClass CREATE/UPDATE |
Fail | Validates the class definition. While gpu-controller is unavailable, GPUClass writes are rejected. |
podgpuresourceclaim |
Pod CREATE | Fail | The extended-resource path: when a container requests a gpu.deckhouse.io/* resource, generates the matching ResourceClaim. Skipped in kube-system and d8-* namespaces. |
resourceclaimparameters |
ResourceClaim, ResourceClaimTemplate, DeviceClass |
Ignore | Validates the module’s opaque device configs (GpuConfig, MigDeviceConfig, VfioDeviceConfig). |
podresourceclaim |
Pod with resourceClaims |
Ignore | Consistency checks on claim references. |
Additionally, a ValidatingAdmissionPolicy named gpu-vfio-switch-guard constrains the privileged Jobs that nvidia-adapter creates for VFIO driver switching (see below). Any Job in d8-nvidia-gpu that is privileged or uses hostPID — either one is enough to trigger the check — must match the sanctioned profile in full:
- the
vfio-switchServiceAccount, with no token automount - exactly one container, running the exact adapter image
hostNetworkandhostIPCboth falserestartPolicy: Never- host paths limited to
/sys,/dev,/proc, and/var/lib/nvidia-adapter/checkpoint - a command of the form
/app/nvidia-adapter switch <pci-address>, with a canonical PCI address
VFIO passthrough
For passthrough, the card must be detached from the NVIDIA driver and bound to vfio-pci. nvidia-adapter does not do this in its own process: it launches a short-lived privileged Job (/app/nvidia-adapter switch <pci>) running under a ServiceAccount with no Kubernetes permissions, whose only purpose is to be an admission identity. The gpu-vfio-switch-guard policy above is the guard on that capability.
Node preparation is handled by NodeGroupConfiguration (see below). A card in passthrough reports .status.phase: Passthrough and is not published as a CUDA device.
Passthrough requires IOMMU enabled both in BIOS and on the kernel command line. The module can add the kernel parameter itself, but this requires a node reboot.
When a driver switch fails
Rebinding a card between drivers is the one operation that can leave hardware in a state Kubernetes cannot repair on its own, so it has an explicit recovery path.
A failed bind to vfio-pci is normally rolled back to the NVIDIA driver and the claim simply fails. Rollback is impossible in the following cases:
- after a failed or wedged unbind the card is left with no driver at all;
- on release, the card cannot be restored to the NVIDIA driver and stays on
vfio-pcior driverless.
In both cases the adapter publishes Reconfiguring=DisruptionRequired on the PhysicalGPU with a message naming the PCI address and stating that a node reboot is required. gpu-controller then carries the handoff through DisruptionPending to RebootRequested. Once recovery observes the card back on its baseline driver — ground truth that the reboot actually happened — it finalises the condition through Completing.
Failures also surface as events: VFIOPrepareFailed and VFIOUnprepareFailed, alongside VFIOPrepareSucceeded on the happy path.
Node preparation
NodeGroupConfiguration scripts run on every node, in weight order. They are what makes a node eligible for the GPU stack.
| Script | Weight | What it does |
|---|---|---|
gpu-check.sh |
6 | Verifies that the NVIDIA driver is present and usable. Clears node.deckhouse.io/gpu-setup-complete on failure. Skips NVIDIA runtime checks on VFIO-only nodes. |
gpu-runtime.sh |
31 | Writes a containerd drop-in registering nvidia as an explicit runtime handler — not the default runtime. This is deliberate: it is what keeps a Pod without a claim from seeing GPUs. |
gpu-vfio-iommu.sh |
39 | Bare-metal only. Detects the CPU vendor, adds intel_iommu=on or amd_iommu=on to the kernel command line, and requests a reboot through the Deckhouse node-update annotations. |
gpu-vfio.sh |
40 | Loads the vfio and vfio_iommu_type1 kernel modules, reconciles GPU PCI function binding, and sets node.deckhouse.io/gpu-vfio-ready to true or false. |
gpu-sysctl.sh |
41 | Sets net.core.bpf_jit_harden=1, required by the NVIDIA Container Toolkit. Restores the previous value on cleanup. |
gpu-setup.sh |
42 | The final gate: sets or clears node.deckhouse.io/gpu-setup-complete. |
Node labels that gate scheduling
If DRA pods are missing from a node, one of these labels is usually the reason:
| Label | Set by | Effect |
|---|---|---|
node.deckhouse.io/gpu-setup-complete |
gpu-setup.sh |
Must exist. Until it does, no GPU stack component is scheduled onto the node. |
gpu.deckhouse.io/vendor |
gpu-node-agent |
Names the GPU vendor found on the node. Each vendor adapter is scheduled by a nodeSelector on this label; on NVIDIA nodes it also gates the DCGM DaemonSets. |
gpu.deckhouse.io/enabled |
administrator | Opt-out switch. Setting it to false excludes the node from GPU management. |
gpu.deckhouse.io/maintenance=true |
administrator | Excludes the node while you work on it. |
node.deckhouse.io/gpu-vfio-ready |
gpu-vfio.sh |
true only when VFIO modules are loaded and IOMMU groups are present. Use it as a nodeSelector for passthrough workloads: VFIO readiness is not published as a device attribute, so it cannot be expressed in a DeviceClass selector. |
gpu.deploy.dcgm, gpu.deploy.dcgm-exporter |
nvidia-adapter |
Temporarily set to paused-for-mig-change to stop DCGM from holding the GPU during reconfiguration. Pods disappearing during a MIG change is expected. |
Uninstall
When the module is disabled or removed while dra.enabled: true, a Helm pre-delete hook Job deletes every PhysicalGPU in the cluster and waits up to 600 seconds for them to go away. This lets gpu-controller resolve its finalizers before the CRD is removed.
If the Job times out, look for objects with stuck finalizers:
d8 k get physicalgpus -ADevice Plugin mode
In this mode dra.enabled is false, which is the default. GPU sharing is configured per NodeGroup through spec.gpu rather than per workload.
Device Plugin mode configures GPUs at the node level: a node group serves one sharing mode, and workloads request nvidia.com/gpu. Choose DRA mode when workloads need to state their own requirements — MIG partitions, a share of a GPU, or passthrough. You can switch later without manual cleanup (see How do I migrate from Device Plugin mode to DRA?).
Components
In Device Plugin mode the module creates the following components:
| Component | Kind | What it does |
|---|---|---|
node-feature-discovery-master |
Deployment | Collects hardware feature labels from workers and publishes them as node labels (feature.node.kubernetes.io/*, nvidia.com/*). |
node-feature-discovery-gc |
Deployment | Removes stale NFD labels for deleted nodes. |
node-feature-discovery-worker |
DaemonSet | Detects PCI/USB devices on each GPU node and writes feature files for the NFD master. |
gpu-feature-discovery-<ng> |
DaemonSet, per NodeGroup | Queries the driver via NVML and writes detailed GPU feature files (nvidia.com/gpu.count, nvidia.com/mig.capable, …). |
nvidia-device-plugin-<ng> |
DaemonSet, per NodeGroup | Exposes nvidia.com/gpu (Exclusive, TimeSlicing) or nvidia.com/mig-<profile> (MIG) to the scheduler. |
nvidia-mig-manager |
DaemonSet | Applies MIG profiles on A100/H100 nodes: drains the node, reconfigures, reboots if required, and returns the node to service. |
nvidia-dcgm |
DaemonSet | DCGM daemon. |
nvidia-dcgm-exporter |
DaemonSet | Prometheus exporter for DCGM metrics. |
Key labels
node.deckhouse.io/gpu=""— set by the module hook on nodes of GPU Node Groups.node.deckhouse.io/device-gpu.config=<Exclusive|TimeSlicing|MIG>— set by the hook; selects the device plugin and GFD configuration.node.deckhouse.io/gpu-setup-complete=""— set bygpu-sysctl.shafter local checks; until it appears, the stack is not scheduled onto the node.feature.node.kubernetes.io/pci-*.present=true— published by NFD.nvidia.com/*(for examplenvidia.com/gpu.count,nvidia.com/mig.capable) — published by NFD from GFD feature files.nvidia.com/mig.config=<profile|all-disabled>— set by the hook: the desired MIG profile, orall-disabledto roll MIG back.nvidia.com/mig.config.state=<pending|rebooting|success|failed>— set bynvidia-mig-manager.- taint
mig-reconfigure=true:NoSchedule— held bynvidia-mig-managerfor the duration of a reconfiguration. - annotations
update.node.deckhouse.io/disruption-approved,.../draining,.../drained— controlled drain during MIG changes.
How the module works in Device Plugin mode
How the module works in Device Plugin mode:
- The cluster administrator sets or changes
spec.gpuin the NodeGroup. - Helm deploys or removes components in namespace
d8-nvidia-gpu: GFD and device plugin as per-NodeGroup DaemonSets, NFD master/gc on the control plane, NFD worker and DCGM on GPU nodes. - The module hook updates node labels — adding
node.deckhouse.io/gpuanddevice-gpu.config, and for MIG alsonvidia.com/mig.config; on GPU disable it removes them and setsnvidia.com/mig.config=all-disabledto trigger rollback. - NodeGroupConfiguration scripts run in weight order:
gpu-check.sh→gpu-runtime.sh→gpu-sysctl.sh. On success the node getsnode.deckhouse.io/gpu-setup-complete. - The stack converges: NFD publishes labels, GFD writes GPU feature files, the device plugin exposes resources, DCGM starts exporting metrics.
Configuring GPU allocation with the Exclusive strategy
To allocate GPUs without sharing (each GPU is allocated entirely to one Pod), do the following:
- Set
spec.gpu.sharing: Exclusive. - The module sets the label
node.deckhouse.io/device-gpu.config=Exclusiveand brings up GFD and the device plugin. - The node exposes
nvidia.com/gpu; each Pod gets a full GPU.
To disable, remove spec.gpu from the NodeGroup. The module removes its labels, NodeGroupConfiguration rolls back the runtime and sysctl changes, and NFD GC eventually cleans up the nvidia.com/* labels.
Configuring GPU allocation with the TimeSlicing strategy
To allocate GPUs with time-slicing (several Pods can use one GPU concurrently, taking turns on its compute resources), do the following:
- Set
spec.gpu.sharing: TimeSlicingand optionallyspec.gpu.timeSlicing.partitionCount(default 4). - The device plugin applies the time-slicing configuration.
- The node still exposes
nvidia.com/gpu, but with more virtual slots.
Switching to Exclusive or removing spec.gpu reverts it.
Configuring GPU allocation with the MIG strategy
To allocate GPUs by splitting them into multiple instances (NVIDIA MIG, when supported), do the following:
- Set
spec.gpu.sharing: MIGandspec.gpu.mig.partedConfig: <profile>(for exampleall-1g.5gb). - The module sets the labels
node.deckhouse.io/device-gpu.config=MIGandnvidia.com/mig.config=<profile>. - Once NFD publishes
nvidia.com/mig.capable=true,nvidia-mig-manageris scheduled onto the node and reacts to changes of thenvidia.com/mig.configlabel. - To reconfigure, it sets
nvidia.com/mig.config.state=pending, pauses GPU clients vianvidia.com/gpu.deploy.*=paused-for-mig-change, applies the taintmig-reconfigure=true:NoSchedule, waits for drain approval, deletes GPU client pods on the node, applies the profile (rebooting if required), then setssuccessorfailed, removes the taint, uncordons the node, and restores thegpu.deploy.*labels. - The cluster then exposes resources such as
nvidia.com/mig-1g.5gb.
If the nvidia-mig-manager Pod is restarted mid-operation, its preStop hook waits for the active operation to finish, then uncordons and removes the taint and drain annotations on a best-effort basis.
Rolling MIG back. Switching away from MIG or removing spec.gpu sets the label nvidia.com/mig.config=all-disabled, which the manager applies the same way. Once rollback succeeds, the labels nvidia.com/mig.config and nvidia.com/mig.config.state are removed so the manager does not keep waiting on the node. The manager never runs on GPUs without MIG support (nvidia.com/mig.capable=false) — use Exclusive or TimeSlicing for those.
Module shared infrastructure
Regardless of operating mode, the module uses the following infrastructure:
| Item | What it is |
|---|---|
Namespace d8-nvidia-gpu |
Holds the stack in both modes. Labeled so Prometheus picks up the module’s rules. |
gpu-module-registry Secret |
Image pull secret referenced by every module ServiceAccount. |
gpu-supported-vendors ConfigMap |
PCI vendor table used by gpu-node-agent for discovery. |
gpu-baseline OperationPolicy, gpu-restricted SecurityPolicy |
Optional guardrails, applied to namespaces labeled operation-policy.deckhouse.io/gpu=true or security.deckhouse.io/gpu=restricted. |
| TLS material | A module-local root CA (gpu-ca) issues the webhook and metrics-proxy certificates. Managed by hooks; no operator action required. |
Monitoring
The module exports its own metrics alongside the DCGM metrics:
| Source | Metrics |
|---|---|
gpu-controller, nvidia-adapter |
gpu_inventory_devices_total, gpu_inventory_devices_state, gpu_inventory_handler_errors_total, gpu_bootstrap_node_phase, gpu_bootstrap_condition, gpu_bootstrap_handler_errors_total, gpu_resourceclaim_info, gpu_resourceclaim_requested_devices |
| module hooks | gpu_dra_mode, gpu_dra_feature_gate_missing, gpu_dra_feature_gates_check_error |
gpu-dcgm-exporter |
DCGM_FI_* |
Scrape configuration is created automatically: ServiceMonitors for gpu-controller and nvidia-adapter, and a PodMonitor for the DCGM exporter. It can be turned off with monitoring.serviceMonitor.
Grafana dashboards are shipped for both modes — cluster overview, per-node and per-namespace views, GPU inventory, and DRA workloads.
Alerts:
| Alert | Meaning |
|---|---|
D8GpuDraFirstEnablementBlocked |
Required DRA feature gates are missing; the DRA stack is not deployed. |
D8GpuDraFeatureGateDisabledOnComponent |
A gate was disabled on the apiserver, scheduler, or a kubelet while DRA mode is active. |
D8GpuDraFeatureGatesCheckError |
The feature-gate state could not be verified — the readiness check itself is failing. |
D8GPUControlPlaneControllerTargetDown |
Prometheus cannot scrape gpu-controller. |
D8GPUControlPlaneControllerTargetAbsent |
The gpu-controller target has disappeared. |
D8GPUControlPlaneControllerPodIsNotReady |
The gpu-controller Pod is not ready. |