Home DevOps GPU Support and Specialized Hardware in Kubernetes
Advanced 3 min · July 12, 2026

GPU Support and Specialized Hardware in Kubernetes

Learn GPU Support and Specialized Hardware in Kubernetes with plain-English explanations and real examples..

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.

Follow
Verified
production tested
July 12, 2026
last updated
2,073
articles · all by Naren
Before you start⏱ 30 min
  • Kubernetes cluster (v1.24+), kubectl, Helm (v3+), NVIDIA GPU nodes with driver >= 525.60.13, containerd runtime with nvidia-container-toolkit, basic understanding of Kubernetes scheduling and resource management.
✦ Definition~90s read
What is GPU Support and Specialized Hardware in Kubernetes?

GPU support in Kubernetes enables pods to access NVIDIA GPUs for compute-intensive workloads like ML training and inference. It matters because it turns Kubernetes into a viable platform for AI/ML, allowing dynamic scheduling of GPU resources alongside regular containers.

Think of GPU Support and Specialized Hardware in Kubernetes like a tool in your DevOps toolkit — once you understand what it does and when to reach for it, managing Kubernetes clusters becomes second nature.

Use it when you need to run CUDA-based applications on a cluster with NVIDIA GPUs, ensuring efficient utilization and isolation.

Plain-English First

Think of GPU Support and Specialized Hardware in Kubernetes like a tool in your DevOps toolkit — once you understand what it does and when to reach for it, managing Kubernetes clusters becomes second nature.

Welcome to GPU Support and Specialized Hardware in Kubernetes. We'll break this down from first principles.

Why GPU Support Matters in Kubernetes

Kubernetes was designed for stateless microservices, but AI/ML workloads demand specialized hardware. Without GPU support, you'd have to manually assign nodes and manage device contention. The Kubernetes ecosystem now provides device plugins and scheduler extensions to treat GPUs as first-class resources. This matters because it allows you to run training jobs, inference servers, and data processing pipelines on the same cluster, with the same orchestration benefits. When to use it: any time your workload requires CUDA, ROCm, or other GPU-accelerated libraries. Avoid it for CPU-only tasks—overhead isn't worth it.

gpu-pod.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  containers:
  - name: cuda-vector-add
    image: nvidia/cuda:12.2.0-base-ubuntu22.04
    command: ["nvidia-smi"]
    resources:
      limits:
        nvidia.com/gpu: 1
Output
Thu Jan 1 00:00:00 2026
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 545.23.08 Driver Version: 545.23.08 CUDA Version: 12.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Tesla T4 Off | 00000000:00:1E.0 Off | 0 |
| N/A 34C P8 9W / 70W | 0MiB / 15109MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
🔥GPU Resource Naming
The resource name nvidia.com/gpu is defined by the NVIDIA device plugin. Other vendors (AMD, Intel) use different names like amd.com/gpu.
📊 Production Insight
In production, always set resource limits, not requests, for GPUs to avoid overcommit. We once had a job that requested 0 GPUs but got scheduled on a GPU node, causing contention.
🎯 Key Takeaway
GPU support turns Kubernetes into a viable platform for AI/ML workloads.

Prerequisites: NVIDIA Drivers and Container Runtime

Before Kubernetes can schedule GPUs, each node must have the NVIDIA driver installed and a container runtime that supports GPU passthrough. The driver version must match the CUDA version your workloads expect. Use nvidia-smi to verify. For the runtime, install nvidia-container-toolkit and configure containerd or Docker to use it. This is a common failure point: mismatched driver/runtime versions cause pods to fail with 'cannot find CUDA driver'. Always pin driver versions in your node image.

install-nvidia-runtime.shBASH
1
2
3
4
5
6
7
# Install NVIDIA container toolkit on Ubuntu
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=containerd
sudo systemctl restart containerd
Output
INFO[0000] Configuring containerd for NVIDIA runtime
INFO[0000] Successfully configured containerd
⚠ Driver Compatibility
CUDA 12.x requires driver version >= 525.60.13. Check NVIDIA's compatibility matrix before upgrading.
📊 Production Insight
We once rolled out a new node image with a newer driver that broke existing CUDA 11 jobs. Now we pin driver version in the AMI and test with a canary pod.
🎯 Key Takeaway
Driver and runtime must match; verify with nvidia-smi before deploying workloads.
kubernetes-gpu-support THECODEFORGE.IO GPU Workload Scheduling in Kubernetes Step-by-step flow from driver install to pod scheduling Install NVIDIA Drivers Ensure nvidia-driver and nvidia-docker2 are present Configure Container Runtime Set nvidia as default runtime in containerd/docker Deploy NVIDIA Device Plugin Apply DaemonSet to register GPU resources Define Resource Requests Specify nvidia.com/gpu: 1 in pod spec Schedule Pod on GPU Node Kube-scheduler matches resource availability Monitor GPU Utilization Use DCGM exporter and Prometheus metrics ⚠ Missing nvidia-docker2 runtime causes GPU not found Always verify runtime with 'docker info | grep nvidia' THECODEFORGE.IO
thecodeforge.io
Kubernetes Gpu Support

Installing the NVIDIA Device Plugin

The NVIDIA device plugin is a DaemonSet that advertises GPU resources to the kubelet. It watches for GPU devices and updates the node's capacity. Install it via Helm or raw YAML. The plugin also supports MIG (Multi-Instance GPU) partitioning for A100/H100 GPUs. Without it, nvidia.com/gpu won't appear as a schedulable resource. Common mistake: forgetting to set the nvidia.com/gpu resource in the pod spec, or requesting more GPUs than available.

nvidia-device-plugin-ds.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin-daemonset
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: nvidia-device-plugin-ds
  template:
    metadata:
      labels:
        name: nvidia-device-plugin-ds
    spec:
      tolerations:
      - operator: Exists
        effect: NoSchedule
      containers:
      - image: nvidia/k8s-device-plugin:v0.14.0
        name: nvidia-device-plugin-ctr
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        volumeMounts:
        - name: device-plugin
          mountPath: /var/lib/kubelet/device-plugins
      volumes:
      - name: device-plugin
        hostPath:
          path: /var/lib/kubelet/device-plugins
Output
daemonset.apps/nvidia-device-plugin-daemonset created
💡Verify Plugin Installation
Run kubectl get nodes -o json | jq '.items[].status.capacity' to see if nvidia.com/gpu appears.
📊 Production Insight
We had a node where the plugin crashed due to a race condition with kubelet restart. Add liveness probes and monitor plugin logs.
🎯 Key Takeaway
The device plugin is mandatory; without it, GPUs are invisible to the scheduler.

Scheduling GPU Workloads: Resource Requests and Limits

GPU resources are advertised as nvidia.com/gpu and must be specified as limits (requests are ignored by the scheduler). You can request fractional GPUs only if using MIG or time-slicing. The scheduler uses a bin-packing algorithm by default, but you can configure node selectors or taints to isolate GPU nodes. Important: GPU memory is not directly managed by Kubernetes—if your pod exceeds GPU memory, it will OOM and crash. Use CUDA's cudaSetDevice and memory monitoring tools.

gpu-job.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: batch/v1
kind: Job
metadata:
  name: gpu-job
spec:
  template:
    spec:
      containers:
      - name: cuda-work
        image: nvidia/cuda:12.2.0-runtime-ubuntu22.04
        command: ["python3", "-c", "import torch; print(torch.cuda.is_available())"]
        resources:
          limits:
            nvidia.com/gpu: 1
      restartPolicy: Never
Output
True
⚠ Limits vs Requests
Only set limits for GPUs. Requests are ignored; setting both can cause confusion. The scheduler only looks at limits.
📊 Production Insight
We once set requests=1 and limits=2, expecting burst. Instead, the pod got 2 GPUs guaranteed, wasting resources. Stick to limits only.
🎯 Key Takeaway
Always specify GPU resources as limits; requests are ignored.

Multi-Instance GPU (MIG) Partitioning

MIG allows partitioning a single A100/H100 into up to 7 smaller GPU instances, each with isolated memory and compute. This improves utilization for smaller workloads. To use MIG, enable it on the GPU (via nvidia-smi mig -cgi), then configure the device plugin with the mig-strategy flag. The plugin exposes each MIG slice as a separate nvidia.com/gpu resource. Without MIG, a single GPU can only be used by one pod at a time.

enable-mig.shBASH
1
2
3
4
5
6
# Enable MIG on GPU 0
sudo nvidia-smi mig -cgi 19,19,19 -i 0
# Verify
nvidia-smi mig -lgi
# Output:
# GPU 0 Profile ID 19 Placements: {0,1,2}:1
Output
Successfully created MIG instances for GPU 0.
🔥MIG Strategies
The device plugin supports 'single' (one MIG per GPU), 'mixed' (multiple profiles), and 'none' (whole GPU). Choose based on workload mix.
📊 Production Insight
We run inference on MIG slices (1g.10gb) and training on whole GPUs. Monitor memory pressure—MIG doesn't prevent OOM within a slice.
🎯 Key Takeaway
MIG improves GPU utilization by partitioning into isolated slices.

GPU Time-Slicing for Oversubscription

Time-slicing allows multiple pods to share a single GPU by time-multiplexing compute. Unlike MIG, memory is not isolated—pods can interfere. Enable it via the device plugin's gpu-sharing-strategy flag. Useful for development or low-priority batch jobs, but risky for production because a memory-hungry pod can OOM others. Always set resource limits for CPU/memory to mitigate.

time-slicing-config.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: ConfigMap
metadata:
  name: nvidia-device-plugin-config
  namespace: kube-system
data:
  config.yaml: |
    version: v1
    flags:
      migStrategy: none
    sharing:
      timeSlicing:
        resources:
        - name: nvidia.com/gpu
          replicas: 4
Output
configmap/nvidia-device-plugin-config created
⚠ No Memory Isolation
Time-slicing does not isolate GPU memory. A single pod can consume all VRAM and crash others. Use only for non-critical workloads.
📊 Production Insight
We tried time-slicing for CI jobs. One test leaked memory, taking down all other tests. Switched to MIG for isolation.
🎯 Key Takeaway
Time-slicing shares GPU compute but not memory; use cautiously.

Monitoring GPU Utilization and Health

Kubernetes doesn't natively expose GPU metrics. Use the NVIDIA DCGM exporter (part of the GPU Operator) to collect metrics like GPU utilization, memory usage, temperature, and power. Integrate with Prometheus and Grafana. Also, set up liveness probes for GPU pods to detect driver hangs. Common failure: GPU stuck in 'P2' state (high power) due to a stuck kernel—requires node reboot.

dcgm-exporter.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-dcgm-exporter
  namespace: gpu-operator
spec:
  selector:
    matchLabels:
      app: nvidia-dcgm-exporter
  template:
    metadata:
      labels:
        app: nvidia-dcgm-exporter
    spec:
      containers:
      - name: dcgm-exporter
        image: nvidia/dcgm-exporter:3.1.7-1.0.0-ubuntu20.04
        ports:
        - containerPort: 9400
          name: metrics
Output
daemonset.apps/nvidia-dcgm-exporter created
💡Alert on XID Errors
XID errors indicate GPU hardware issues. Set up alerts on DCGM_FI_DEV_XID_ERRORS to catch failing GPUs early.
📊 Production Insight
We had a GPU with intermittent XID 48 (double-bit ECC error). DCGM caught it, we drained the node before jobs failed.
🎯 Key Takeaway
Monitor GPU health with DCGM exporter; alert on XID errors.
kubernetes-gpu-support THECODEFORGE.IO Kubernetes GPU Stack Architecture Layered components from hardware to orchestration Hardware Layer NVIDIA GPU (A100, V100, T4) | PCIe/NVLink Interconnect Host OS Layer NVIDIA Driver | nvidia-fabricmanager (for NVSw Container Runtime Layer nvidia-container-runtime | nvidia-docker2 | CDI (Container Device Interfac Kubernetes Device Plugin Layer NVIDIA Device Plugin | GPU Operator | MIG Manager Scheduling & Policy Layer Resource Requests/Limits | Node Affinity | GPU Time-Slicing Monitoring & Observability Layer DCGM Exporter | Prometheus | Grafana Dashboards THECODEFORGE.IO
thecodeforge.io
Kubernetes Gpu Support

GPU Operator: The All-in-One Solution

The NVIDIA GPU Operator automates the deployment of all GPU-related components: drivers, device plugin, runtime, monitoring, and MIG configuration. It uses a DaemonSet to manage driver upgrades without node reboots. Recommended for production clusters to reduce manual steps. However, it adds complexity—debugging issues requires understanding the operator's reconciliation logic. Weigh against manual setup for small clusters.

install-gpu-operator.shBASH
1
2
3
4
5
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
helm install gpu-operator nvidia/gpu-operator --namespace gpu-operator --create-namespace
# Wait for all pods to be Running
kubectl wait --for=condition=ready pod -l app.kubernetes.io/component=nvidia-driver -n gpu-operator --timeout=300s
Output
NAME: gpu-operator
LAST DEPLOYED: ...
NAMESPACE: gpu-operator
STATUS: deployed
🔥Operator vs Manual
Use the operator for >10 GPU nodes. For smaller clusters, manual setup gives more control and simpler debugging.
📊 Production Insight
We used the operator and hit a bug where driver upgrade stuck due to a pod with hostPID. Now we cordon nodes before operator-triggered upgrades.
🎯 Key Takeaway
GPU Operator automates driver, plugin, and monitoring deployment.

Node Affinity and Taints for GPU Workloads

To ensure GPU workloads land on GPU-equipped nodes, use node affinity or taints. Common pattern: taint GPU nodes with nvidia.com/gpu=present:NoSchedule and add toleration to GPU pods. Also, use node affinity to prefer nodes with specific GPU models (e.g., A100 vs T4). Without these, CPU-only pods might occupy GPU nodes, wasting resources.

gpu-pod-with-toleration.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  tolerations:
  - key: "nvidia.com/gpu"
    operator: "Exists"
    effect: "NoSchedule"
  containers:
  - name: cuda
    image: nvidia/cuda:12.2.0-base-ubuntu22.04
    command: ["nvidia-smi"]
    resources:
      limits:
        nvidia.com/gpu: 1
Output
pod/gpu-pod created
💡Taint GPU Nodes
Run kubectl taint nodes <node> nvidia.com/gpu=present:NoSchedule to reserve them for GPU workloads.
📊 Production Insight
We forgot to taint a node and a log collector pod consumed 2GB of GPU memory, causing OOM for a training job. Now we enforce taints.
🎯 Key Takeaway
Use taints and tolerations to isolate GPU nodes from CPU workloads.

Handling GPU Memory and OOM

Kubernetes does not track GPU memory usage. A pod can request 1 GPU but use all its VRAM, starving other pods on the same GPU (if time-slicing) or causing OOM. Mitigate by using CUDA_VISIBLE_DEVICES to limit which GPUs a pod sees, and by setting memory limits on the container (CPU memory, not GPU). For MIG, each slice has fixed memory, so OOM is contained. Monitor with DCGM and set resource quotas.

gpu_memory_check.pyPYTHON
1
2
3
4
5
6
7
import pynvml
pynvml.nvmlInit()
handle = pynvml.nvmlDeviceGetHandleByIndex(0)
info = pynvml.nvmlDeviceGetMemoryInfo(handle)
print(f'Total: {info.total / 1024**2} MB')
print(f'Used: {info.used / 1024**2} MB')
print(f'Free: {info.free / 1024**2} MB')
Output
Total: 15109 MB
Used: 0 MB
Free: 15109 MB
⚠ GPU OOM is Silent
A GPU OOM kills the CUDA process, but Kubernetes may not restart the pod. Use liveness probes that check GPU memory.
📊 Production Insight
We had a training job that gradually leaked GPU memory over hours. DCGM alert saved us before it OOM'd other jobs.
🎯 Key Takeaway
GPU memory is not managed by Kubernetes; monitor and limit via MIG or CUDA_VISIBLE_DEVICES.

Advanced: GPU Sharing with MPS and CUDA MPS

CUDA Multi-Process Service (MPS) allows multiple processes to share a single GPU context, improving utilization for small kernels. Unlike time-slicing, MPS provides better performance isolation. Enable it via the device plugin's mps sharing strategy. However, MPS has limitations: it requires a control daemon and can be unstable with certain CUDA versions. Use for inference serving with many small requests.

mps-config.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: ConfigMap
metadata:
  name: nvidia-device-plugin-config
  namespace: kube-system
data:
  config.yaml: |
    version: v1
    sharing:
      mps:
        resources:
        - name: nvidia.com/gpu
          replicas: 4
Output
configmap/nvidia-device-plugin-config created
🔥MPS vs Time-Slicing
MPS provides better performance isolation but requires a daemon. Time-slicing is simpler but no memory isolation.
📊 Production Insight
We use MPS for Triton inference server with multiple model instances. It doubled throughput compared to time-slicing.
🎯 Key Takeaway
MPS improves GPU utilization for multi-process workloads with better isolation.
MIG Partitioning vs GPU Time-Slicing Trade-offs between isolation and oversubscription Multi-Instance GPU (MIG) GPU Time-Slicing Hardware Support A100, H100, A30 only All NVIDIA GPUs with CUDA Isolation Level Full memory & cache isolation No memory isolation; time-shared Resource Granularity Fixed slices (e.g., 1g.5gb, 2g.10gb) Configurable time quotas (e.g., 50ms per Performance Guarantee Dedicated compute units Best-effort; potential contention Use Case Multi-tenant, SLA-critical workloads Dev/test, burstable, low-priority jobs Configuration Complexity Requires MIG mode and partition setup Simple via device plugin env vars THECODEFORGE.IO
thecodeforge.io
Kubernetes Gpu Support

Troubleshooting Common GPU Issues

Common issues: (1) Pod stuck in Pending: no GPU node available or resource name wrong. Check node capacity and taints. (2) Pod starts but nvidia-smi fails: driver not installed or runtime not configured. Check pod logs for 'cannot find CUDA driver'. (3) GPU OOM: monitor with DCGM. (4) XID errors: hardware failure, drain node. (5) Device plugin not registering: check kubelet logs. Always start with kubectl describe pod and node conditions.

troubleshoot.shBASH
1
2
3
4
5
6
# Check node GPU capacity
kubectl get node gpu-node -o json | jq '.status.capacity'
# Check device plugin logs
kubectl logs -n kube-system -l name=nvidia-device-plugin-ds
# Check pod events
kubectl describe pod gpu-pod | grep -A5 Events
Output
{
"cpu": "8",
"memory": "32768Ki",
"nvidia.com/gpu": "1"
}
...
Normal Scheduled <unknown> Successfully assigned...
Normal Pulled ... Container image already present
Normal Created ... Created container
Normal Started ... Started container
⚠ Driver Version Mismatch
If pod logs show 'CUDA driver version is insufficient', the node driver is older than the CUDA toolkit in the container. Match versions.
📊 Production Insight
We had a node where the device plugin crashed silently. Added a Prometheus alert on kube_daemonset_status_number_ready to catch it.
🎯 Key Takeaway
Systematic troubleshooting: check node capacity, plugin logs, and pod events.
⚙ Quick Reference
12 commands from this guide
FileCommand / CodePurpose
gpu-pod.yamlapiVersion: v1Why GPU Support Matters in Kubernetes
install-nvidia-runtime.shdistribution=$(. /etc/os-release;echo $ID$VERSION_ID)Prerequisites
nvidia-device-plugin-ds.yamlapiVersion: apps/v1Installing the NVIDIA Device Plugin
gpu-job.yamlapiVersion: batch/v1Scheduling GPU Workloads
enable-mig.shsudo nvidia-smi mig -cgi 19,19,19 -i 0Multi-Instance GPU (MIG) Partitioning
time-slicing-config.yamlapiVersion: v1GPU Time-Slicing for Oversubscription
dcgm-exporter.yamlapiVersion: apps/v1Monitoring GPU Utilization and Health
install-gpu-operator.shhelm repo add nvidia https://helm.ngc.nvidia.com/nvidiaGPU Operator
gpu-pod-with-toleration.yamlapiVersion: v1Node Affinity and Taints for GPU Workloads
gpu_memory_check.pypynvml.nvmlInit()Handling GPU Memory and OOM
mps-config.yamlapiVersion: v1Advanced
troubleshoot.shkubectl get node gpu-node -o json | jq '.status.capacity'Troubleshooting Common GPU Issues

Key takeaways

1
GPU as a Resource
Kubernetes treats GPUs as extendable resources via device plugins; always specify nvidia.com/gpu as limits.
2
Isolation Matters
Use MIG for memory isolation, time-slicing for compute sharing, and taints to reserve GPU nodes.
3
Monitor Everything
GPU memory and health are not managed by Kubernetes; use DCGM exporter and alert on XID errors.
4
Operator Reduces Toil
The GPU Operator automates driver, plugin, and monitoring, but adds complexity; choose based on cluster size.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
Can I request a fraction of a GPU?
Q02JUNIOR
What happens if a pod requests more GPU memory than available?
Q03JUNIOR
How do I ensure GPU pods only run on nodes with specific GPU models?
Q01 of 03JUNIOR

Can I request a fraction of a GPU?

ANSWER
Yes, using MIG (Multi-Instance GPU) or time-slicing. MIG provides isolated memory slices (e.g., 1g.10gb), while time-slicing shares compute without memory isolation. Without these, you can only reques
FAQ · 6 QUESTIONS

Frequently Asked Questions

01
Can I request a fraction of a GPU?
02
What happens if a pod requests more GPU memory than available?
03
How do I ensure GPU pods only run on nodes with specific GPU models?
04
Why is my GPU pod stuck in Pending?
05
Can I use AMD or Intel GPUs with Kubernetes?
06
How do I upgrade NVIDIA drivers without downtime?
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.

Follow
Verified
production tested
July 12, 2026
last updated
2,073
articles · all by Naren
🔥

That's Kubernetes. Mark it forged?

3 min read · try the examples if you haven't

Previous
Windows Containers in Kubernetes
18 / 38 · Kubernetes
Next
Kubernetes Multi-Cluster and Federation