Kubernetes & platform12 min read

Kubernetes for AI workloads: GPUs, DRA and job scheduling in practice

What is genuinely stable for GPUs in Kubernetes as of October 2026, what is still beta, and how that should shape your decisions on AKS and EKS.

Summary

The core of Dynamic Resource Allocation (DRA) has been stable in Kubernetes since version 1.34, and version 1.37 from August 2026 also took to GA the handling of classic nvidia.com/gpu-style requests through a DRA driver. Native gang scheduling (the Workload and PodGroup APIs) is beta in 1.37. On managed services, however, DRA still runs into practical limits: on EKS it cannot be used with EKS Auto Mode or with dynamic provisioning in Karpenter, and GPU sharing through the DRA driver is listed there as alpha. A sensible approach for most companies: the device plugin wherever you need autoscaling from zero, DRA on statically provisioned pools, and queues and quotas through Kueue.

Why GPUs in Kubernetes are a hot topic right now

According to the CNCF annual survey for 2025, 82% of container users run Kubernetes in production, and 66% of organizations hosting generative models use it to run some or all of their inference. The same survey also shows the other side: 44% of respondents do not yet run AI/ML workloads on Kubernetes, and only 7% of organizations deploy models daily.

In other words, almost anyone can stand up a cluster with a GPU node pool today, but few know how to run AI workloads on it efficiently and repeatably. The reason is largely technical. Kubernetes was designed for CPU and memory, resources that can be divided and rescheduled. A GPU is expensive, indivisible (unless you explicitly make it otherwise), and the workloads running on it have different scheduling needs than a web service.

Over the past year, upstream has moved further in this area than in several years before. What follows summarizes what is genuinely stable as of October 2026, what is beta, and what that means for AKS and EKS.

DRA: what is stable and what is not

The classic device plugin advertises GPUs as an integer: a node has four units of nvidia.com/gpu, a pod asks for one. The scheduler has no idea which card model it is, how much memory it has or how it is interconnected. Everything else is patched in through node labels, node selectors and separate node pools.

DRA replaces this model. The driver publishes devices along with their attributes into ResourceSlice objects, the administrator defines a DeviceClass, and the workload requests a device through a ResourceClaim or ResourceClaimTemplate, selecting it with CEL expressions. The core of this API has been GA since version 1.34 (August 2025); according to the project, further DRA extensions are to land without backward-incompatible changes.

The current version 1.37, according to the official summary of DRA updates, took support for “DRA Extended Resource” to GA. This is crucial for migration: a DRA driver can also serve a pod that requests nvidia.com/gpu the old way, without a device plugin having to run alongside it. Existing manifests and Helm charts therefore do not have to be rewritten all at once.

CapabilityStatus as of October 2026Source
DRA core (resource.k8s.io/v1)GA since 1.34Kubernetes blog
Extended resource via DRA driverGA in 1.37Kubernetes blog
Workload and PodGroup API (gang scheduling)Beta in 1.37Kubernetes blog
Shared ResourceClaims for PodGroupsBeta in 1.37Kubernetes blog
GPU sharing via the NVIDIA DRA driver on EKS (MIG, MPS, time-slicing)AlphaAmazon EKS documentation

Here is what a request for a GPU with at least 20 GiB of memory looks like (attribute names are defined by the specific driver; the example matches the NVIDIA driver):

apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
  name: gpu-20g
spec:
  spec:
    devices:
      requests:
      - name: gpu
        exactly:
          deviceClassName: gpu.nvidia.com
          selectors:
          - cel:
              expression: device.capacity["gpu.nvidia.com"].memory.isGreaterThan(quantity("20Gi"))
---
apiVersion: v1
kind: Pod
metadata:
  name: inference
spec:
  resourceClaims:
  - name: gpu
    resourceClaimTemplateName: gpu-20g
  containers:
  - name: server
    image: registry.example.com/llm-server:1.0
    resources:
      claims:
      - name: gpu

A stable API does not mean a stable stack

GA applies to the API in Kubernetes. What you can actually do with it depends on the card vendor's DRA driver and on support in your cloud's autoscaler. Each has its own maturity level, and you need to verify both separately.

GPU sharing: time-slicing, MPS, MIG and what DRA does not solve

A whole card for every pod is the simplest and most expensive option. For smaller models, notebooks and development environments, GPUs get shared. The EKS best practices guide for AI/ML describes three mechanisms:

  • Time-slicing – workloads take turns on the GPU over time. It requires no physical partitioning, but according to the documentation it “may lack memory isolation”.
  • MPS (Multi-Process Service) – multiple CUDA processes run concurrently on one card, with better isolation than time-slicing.
  • MIG (Multi-Instance GPU) – physical partitioning of a card into isolated instances with dedicated compute and memory. Only some card generations support it (the documentation names Ampere, Hopper and Blackwell, e.g. the A100 and H100).

DRA can describe and allocate part of a card. What it cannot do is force a container to stay within its allocation. An August post on the CNCF blog sums this up by calling DRA a “promise tracker”: it guarantees that the scheduler does not promise more than the device has, but it does nothing about a container that breaks that promise at runtime. Enforcing a memory limit has to come from another layer – MIG at the hardware level, or a software solution such as HAMi that intercepts CUDA calls.

Time-slicing is not a security boundary

Without memory isolation, one workload can exhaust the VRAM of its neighbor. For multiple teams or customers on a single card, choose MIG, or whole cards. Time-slicing suits development and the workloads of a single team that polices its own rules. General container isolation rules are covered in our article on container security.

Job scheduling: Kueue, gang scheduling and the native Workload API

Distributed training needs all its workers at once. When the scheduler places six of eight pods and the remaining two wait for GPUs, six cards sit idle and you pay for them. Gang scheduling prevents this – either the whole group is scheduled, or nothing is.

The second problem is organizational: who may consume how many GPUs, and who waits in the queue. The default scheduler has no answer to that. Kueue solves it as an add-on layer: it decides when a job waits, when it is admitted and when it is preempted. It offers quotas, cohorts that let teams borrow unused capacity from each other, fair sharing and topology-aware scheduling. It integrates with batch Jobs, JobSet, LeaderWorkerSet, RayJob and Kubeflow training jobs, so a single queue works uniformly for both training and multi-node inference.

What is new in 2026 is that part of this logic is moving directly into kube-scheduler. According to the 1.37 summary, the Workload and PodGroup APIs reached beta, as did workload-aware preemption and shared DRA ResourceClaims for PodGroups. A new CompositePodGroup API for hierarchical groups has been added, intended to provide native support for structures such as JobSet and LeaderWorkerSet.

What this means in practice

  • Native gang scheduling replaces only part of what Kueue does. Quotas, queues and capacity borrowing between teams remain the job of Kueue or another batch system.
  • A beta API may still change before GA. For production training it is safer today to bet on Kueue and try the native APIs in a non-production cluster.
  • If you have one team and a handful of cards, a queue may be unnecessary overhead. It starts to make sense once multiple teams or multiple workload types compete for GPUs.

EKS and AKS: where upstream meets reality

Amazon EKS

The EKS documentation recommends the NVIDIA DRA driver for new deployments on Kubernetes 1.34 and later, but with important exceptions. The DRA driver is not supported in EKS Auto Mode, and in Karpenter only with statically provisioned capacity; for dynamic provisioning in Karpenter, the device plugin remains the option. GPU sharing (dynamic MIG, MPS, time-slicing) is marked alpha for the DRA driver and GA for the device plugin.

The documentation also warns that the DRA driver and the device plugin must not run on the same node – the same device may silently be allocated to multiple pods. On the Bottlerocket AMI, the built-in device plugin therefore has to be disabled.

Azure AKS

The AKS engineering blog describes MIG with DRA on a cluster running Kubernetes 1.34 or later. The procedure: create the node pool with the --gpu-driver none option so that the driver stack is managed by the NVIDIA GPU Operator, disable the device plugin in the operator, and install the NVIDIA DRA driver separately. It is a working path, but you manage the whole stack yourself – including version compatibility during cluster upgrades.

A decision rule for 2026

  • Inference with variable load and node scaling from zero (Karpenter, Auto Mode): device plugin.
  • Training and batch jobs on reserved or statically provisioned capacity: DRA, if you will make use of selection by card attributes.
  • Sharing one card between teams: MIG; via the device plugin where the DRA variant is still alpha.
  • Mixed cluster: separate node pools for DRA and the device plugin, never both on one node.

Node pools, autoscaling and costs

The biggest item on the bill is usually not a poorly chosen instance type, but GPUs running idle. A few rules that apply regardless of cloud:

  • Separate, tainted GPU pools. Regular workloads must not stray onto them; system DaemonSets need tolerations.
  • Gentle consolidation. For interruption-sensitive workloads, AWS recommends the WhenEmpty policy in Karpenter with a longer consolidateAfter; the WhenEmptyOrUnderutilized policy may terminate nodes prematurely and prolong job run times.
  • Spot only where interruption does not matter. AWS cites discounts of up to 90% versus On-Demand, but explicitly warns that spot is not suitable for stateful workloads that cannot tolerate interruption. Training on spot therefore requires checkpointing.
  • Capacity reservations. For P-family instances (and Trainium), AWS offers Capacity Blocks for ML; for the G family, On-Demand Capacity Reservations. For scarce instance types, a reservation is often the only way to get capacity at all.
  • Multiple instance types. A pool restricted to a single type will hit regional capacity shortages sooner.
  • Scaling to zero. Version 1.37 has HPA scale-to-zero in beta and enabled by default (it requires an Object or External metric); it is worth trying for occasionally used inference endpoints. Expect cold starts, though – pulling the image and loading a large model can take minutes.

Measure utilization, not the number of allocated cards. GPU metrics (utilization, memory in use) belong in the same monitoring as the rest of the platform; without them you cannot tell whether sharing pays off.

AI Conformance as a checklist

The CNCF runs the Kubernetes AI Conformance program, whose requirements are versioned together with Kubernetes. The list for version 1.37 is useful even for companies that do not plan any certification: it describes what an AI platform should be able to do.

The mandatory (MUST) requirements include Gateway API support for managing traffic to inference services, the ability to run at least one gang scheduling solution, cluster autoscaling of accelerator node pools, working HPA for pods with accelerators, accelerator and workload metrics, isolated access to cards, and reliable operation of at least one complex AI operator. The recommended (SHOULD) requirements include GPU sharing, the Gateway API Inference Extension for routing requests to models, and workload sandboxing.

What to verify on your own cluster

The Kubernetes version is at least 1.34 (DRA core in GA) and there is a plan to upgrade to 1.37.
It has been decided which node pools use the DRA driver and which use the device plugin; no node runs both.
The autoscaler can scale the GPU pool both up and down, and it has been verified that this works with the chosen GPU allocation method.
For shared cards, a mechanism (MIG, MPS, time-slicing) has been chosen and the isolation it provides is documented.
Batch and training jobs go through a queue with quotas (Kueue), not directly to the scheduler.
GPU utilization and memory metrics are in monitoring, and someone reads them regularly.
GPU driver, operator and DRA driver versions are part of the cluster upgrade procedure.

The last point is the one most often underestimated. The GPU stack adds another compatibility matrix to every Kubernetes upgrade; whoever postpones upgrades misses out on the features described above. An overview of supported versions is on the Kubernetes EOL page, and the upgrade process is described in Kubernetes upgrade.

When none of this makes sense

Your own GPU layer in Kubernetes is not mandatory equipment. If a company calls models through a provider's API and hosts nothing itself, it does not need a GPU node pool. The same goes for a handful of experimental jobs a month – a managed cloud ML service will cost less than running operators, drivers and queues.

The opposite extreme is large training clusters, where traditional HPC schedulers still offer more mature tooling for batch work. Kubernetes makes the most sense in the middle: inference of your own or open models, fine-tuning and batch processing in an organization that already runs Kubernetes and wants AI workloads under the same governance, security policies and deployment pipeline as the rest of its applications.

And do not rush into DRA just because it is GA. The device plugin remains supported, and combined with dynamic autoscaling it is often the only supported option today. Migration makes sense once you need something the integer model cannot do: selection by card attributes, finer-grained sharing or device topology.

Key takeaways

  • DRA is a stable API, not a finished solution. The core is GA since 1.34, extended resources via DRA since 1.37; driver maturity and autoscaler support vary by cloud.
  • DRA allocates, it does not enforce. Memory isolation between workloads on one card comes from MIG or another layer, not from the scheduler.
  • On EKS, the provisioning method decides. Auto Mode and dynamic Karpenter mean the device plugin; DRA belongs on static capacity.
  • Queues and quotas are Kueue's job. The native Workload and PodGroup APIs are beta in 1.37 and cover only gang scheduling and preemption.
  • Idle cards drive costs. Gentle consolidation, spot with checkpointing, capacity reservations and measuring actual utilization have a bigger effect than tuning the instance type.
  • The AI Conformance list works as an audit. Even without certification, it shows what a platform for AI workloads should be able to do.

Sources

  1. Kubernetes Blog: Kubernetes v1.34: DRA has graduated to GA (September 2025)
  2. Kubernetes Blog: Kubernetes v1.37: DRA Updates (September 2026)
  3. Kubernetes Blog: Kubernetes v1.37: Advancing Workload-Aware Scheduling (September 2026)
  4. CNCF: 2025 Annual Cloud Native Survey – results announcement (January 2026)
  5. CNCF Blog: Does Kubernetes DRA Replace HAMi? (August 2026)
  6. CNCF: Kubernetes AI Conformance – requirements for v1.37 (2026)
  7. AWS: Use the NVIDIA DRA driver or device plugin on Amazon EKS (accessed October 2026)
  8. AWS: EKS Best Practices – AI/ML Compute and Autoscaling (accessed October 2026)
  9. AKS Engineering Blog: Multi-instance GPU (MIG) with Dynamic Resource Allocation (DRA) on AKS (March 2026)
  10. Kubernetes SIGs: Kueue – Overview (accessed October 2026)

Planning GPU workloads on AKS or EKS?

DevSecOps.cz helps design node pools, job scheduling and cluster upgrades so that AI workloads run under the same governance as the rest of your platform.

Or write to info@devsecops.cz. We process your data under our privacy policy.