Skip to main content

Kubernetes' Partitionable GPU Devices (KEP-4815): The Real Cost Math Behind Slicing One GPU Into 7 Schedulable Sandboxes

8 min readDora NodaDora Noda
Share
On this page

Average GPU utilization across production Kubernetes clusters sits around 5%. If you're running a self-hosted fleet of AI-agent sandboxes on GPU hardware you own or lease by the month — not metered by the second on a hyperscaler — that number is not an abstraction. It's the difference between a GPU that pays for itself and one that sits mostly idle behind a single tenant's ResourceClaim, because today's Dynamic Resource Allocation (DRA) in Kubernetes hands out GPUs whole.

KEP-4815, Partitionable Devices, changes that baseline. It lets a DRA driver expose one physical GPU as several independently schedulable slices, and it's been beta and enabled by default since Kubernetes v1.36, with continued work through the v1.37 release (targeting GA on August 26, 2026 — not yet shipped as this is written). For anyone pricing AI-agent sandbox seats by fractional GPU-second instead of by the whole card, this is the mechanism that makes that pricing model real. Below is the actual math on what that's worth, and the concrete scheduler/quota changes a Cluster API-provisioned GPU node needs to expose slices instead of whole devices.

What KEP-4815 Actually Changes

Before this KEP, a DRA driver could describe a GPU as a single Device in a ResourceSlice, and the scheduler allocated it whole to one ResourceClaim — the "consumable capacity" work in v1.34 let you split quantities like memory off a device, but the device itself still went to one claim at a time. Partitionable Devices adds a second axis: a driver can now describe overlapping partitions of the same physical hardware and let the scheduler figure out, per-claim, which combination of partitions is still free.

Mechanically, that's two new ResourceSlice fields:

  • SharedCounters — a driver declares named counter pools representing a limited physical resource (say, 80GB of GPU memory or 7 MIG compute slots).
  • ConsumesCounters — each individual Device entry declares how much of which counter it draws down when allocated.

A PerDeviceNodeSelection field additionally lets each device in a slice carry its own NodeName/NodeSelector, so a single ResourceSlice can describe partitions spread across multiple hosts. When the scheduler allocates a partition, it decrements the shared counters; any other partition that would overdraw those counters becomes unallocatable until the first claim is released. That's the whole trick: the GPU stays a single piece of hardware, but the scheduling treats each partition as its own device with its own lifecycle.

One operational gotcha worth knowing before you deploy this: allocation is first-match, not best-fit. The scheduler doesn't search for the optimal partition combination — it walks the device list in order and takes the first one that satisfies the claim. The KEP's own guidance to driver authors is to list devices smallest-to-largest in the ResourceSlice, or a claim asking for a small slice can end up burning a large one simply because it was listed first.

Timeline, since sources disagree: the KEP was accepted as implementable in Kubernetes 1.32, shipped alpha in 1.33, and graduated to beta (feature-gated DRAPartitionableDevices, enabled by default) in 1.36. The 1.37 cycle — GA'ing August 26, 2026 — continues hardening it toward GA rather than introducing it fresh. If you've read that this "started in 1.36," that's the beta graduation date, not the feature's origin.

The Cost Math: Whole GPU vs. 7-Way Partition

Here's where it gets concrete. Take two real GPU price points a self-hosted operator would actually rack or lease today:

HardwareSourceMonthly costHourly (÷730)
Hetzner GEX130 (RTX 6000 Ada, 48GB)Hetzner dedicated server pricing€838 (~$905)~$1.24
Bare-metal A100 80GBGPU Mart dedicated pricing$1,559~$2.14

The RTX 6000 Ada is what a lot of self-hosted operators are actually running today, and it's worth being direct about a limitation: workstation-class Ada cards don't support hardware MIG. MIG's hardware-isolated partitioning is an Ampere/Hopper datacenter-silicon feature — A100, A30, H100, H200. On an RTX 6000 Ada, a DRA driver can still expose partitions through KEP-4815's SharedCounters mechanism (time-sliced or MPS-based profiles instead of hardware-isolated ones), but the isolation guarantee is weaker than true MIG. If sandbox tenants need hard memory-fault isolation from each other — a reasonable requirement when the "tenant" is an autonomous AI agent running arbitrary code — you want the A100/H100 class card.

So the real worked example uses the A100: MIG splits it into up to 7 slices of 10GB each. At $1,559/month, that's:

  • Whole-GPU model: 1 sandbox tenant per card, $1,559/month per seat.
  • 7-way MIG model: $1,559 ÷ 7 = $222.71/month per slice (~$0.305/hour), assuming every slice is sold.

To put the leverage in perspective: serving 7 concurrent sandbox tenants under the whole-GPU model costs 7 × $1,559 = $10,913/month across 7 cards. The same 7 tenants under the partitioned model cost $1,559/month on one card — or, held at the same $10,913 budget, that buys 7 cards × 7 slices = 49 sandbox seats instead of 7. That's the entire economic case for this KEP in one comparison: a 7x increase in sellable seats per dollar of GPU capex, if you can keep the slices full.

That "if" is the part a cherry-picked example would skip. Occupancy won't be 100%. If a PaaS prices sandbox seats at $0.50/hour (a plausible fractional rate — well under typical serverless-GPU per-hour pricing, since the tenant isn't getting a full card), one fully-sold slice earns $0.50 × 730 = $365/month, against a per-slice cost of $222.71 — a healthy margin at full occupancy. But break-even isn't 100% occupancy: it's the point where slice revenue covers the whole card's $1,559, which is $1,559 ÷ $365 ≈ 4.3 of the 7 slices sold, or about 62% average occupancy. Below that — say only 3 slices sold on a given card — you're running at $1,095/month revenue against $1,559/month cost, underwater by $464. Partitioning doesn't eliminate the utilization problem the 5% stat opened with; it lowers the occupancy bar you need to clear before a card turns a profit, from "one tenant, fully booked" to "roughly 4 of 7 slices, fully booked" — a materially easier bar, not a free one.

What a Cluster API-Provisioned GPU Node Actually Needs

None of the above works without deliberately wiring three things into your GPU node pool. This is the part that's easy to under-scope as "just enable a feature gate."

1. Feature gate on both the API server and schedulerDRAPartitionableDevices must be on in both places, since the scheduler is what enforces the shared-counter bookkeeping:

yaml
# kube-apiserver and kube-scheduler flags
--feature-gates=DynamicResourceAllocation=true,DRAPartitionableDevices=true

2. A DeviceClass plus a ResourceSlice that actually declares the partitions, not just the whole card. For an A100 running 7-way MIG, the DRA driver (NVIDIA's k8s-dra-driver-gpu) publishes something shaped like this — illustrative, since the beta API is still settling before GA:

yaml
apiVersion: resource.k8s.io/v1beta1
kind: ResourceSlice
metadata:
  name: gpu-node-1-a100
spec:
  nodeName: gpu-node-1
  driver: gpu.nvidia.com
  pool:
    name: a100-0
    sharedCounters:
      - name: mig-slots
        counters:
          compute: { value: "7" }
          memory:  { value: "80Gi" }
  devices:
    - name: mig-1g.10gb-0   # smallest first — first-match allocation
      consumesCounters:
        - counterSet: mig-slots
          counters:
            compute: { value: "1" }
            memory:  { value: "10Gi" }
    # ... repeated for each of the 7 slices

A ResourceClaim from a sandbox pod then requests a slice by size (1g.10gb), not by GPU identity — the scheduler resolves which physical card and which slice, decrementing mig-slots accordingly.

3. Per-slice metering wired to billing, not just to scheduling. The ResourceClaimStatus field exposes which specific device (and therefore which counter draw) got allocated to a claim — that's the hook a self-hosted PaaS needs to poll or watch in order to bill fractional GPU-seconds per sandbox rather than per node. This doesn't come for free with the feature gate; it's a controller you write that watches ResourceClaim allocations and reconciles them against your billing/quota system. Skipping this step is the single most common way teams end up with correctly-partitioned GPUs and a billing system that still charges by the whole card.

Get the ordering wrong in step 2 — biggest slice listed first — and step 3's billing math quietly breaks too: a claim for a small sandbox seat can consume a large partition's worth of mig-slots, and your per-seat cost model no longer matches what actually got allocated.

Where This Is Heading

The trajectory across 1.33 → 1.36 → 1.37 is a steady move from "DRA can describe a device" to "DRA can describe a device that's actually many devices, safely." For a self-hosted AI-agent sandbox fleet — the exact workload where tenants are short-lived, bursty, and individually cheap to run but expensive to over-provision for — that's the feature that makes fractional GPU billing something you can build a Cluster API node pool around instead of approximating with cron jobs and hope.

If you're evaluating this now, ahead of 1.37's GA: turn the feature gate on in a dev cluster, confirm your DRA driver's ResourceSlice output orders devices smallest-to-largest, and build the billing reconciler before you need it — not after a sandbox tenant discovers they can request a small slice and get a whole card by accident.

bex is an open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, provisioned through Cluster API. If GPU-backed AI-agent sandboxes are part of what you're operating, this is the layer bex's node pools are built to sit on top of. Star the repo on GitHub.


Sources:

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex