BXUP Track progress & test yourself — free
DevOps / SRE / Platform · Playbook · Advanced · ~5 min read
DEVOPS / SRE / PLATFORM · PLAYBOOK · ADVANCED

Schedule GPUs Like an SRE: Kueue, MIG, and Spot for AI Workloads

GPUs are the most expensive, most contended, and worst-utilized resource on an AI platform — idle 60–80% in most un-managed clusters while teams complain they can't get one.

Tier: Advanced · Workflow area: Platform-for-AI: observability & cost

This playbook applies scheduler discipline: Kueue for queueing and preemption between teams, MIG and time-slicing for fractional GPUs, Karpenter for spot-backed batch capacity, and DCGM metrics to run utilization as an SLO rather than a rumor.

When to use

  • Multiple teams share GPU nodes and allocation happens by Slack negotiation.
  • Inference (latency-sensitive, steady) and batch (training, evals, embedding jobs) fight over the same cards.
  • Finance is asking why the GPU bill is huge while nvidia-smi shows single-digit utilization.

Skip the full machinery for a single team with one workload class — right-size the node group and revisit at the second tenant.

Prerequisites

  • K8s cluster with the NVIDIA GPU Operator installed (device plugin, driver, DCGM exporter).
  • Workloads runnable as Jobs/Deployments with explicit nvidia.com/gpu requests.
  • Cluster-autoscaling via Karpenter (or your cloud's equivalent) for the spot section.
  • Honest workload inventory: which jobs are preemptible, which are latency-critical, who owns each.

The workflow

  1. Measure before you manage. From DCGM exporter, chart per-GPU utilization (DCGM_FI_DEV_GPU_UTIL) and memory use, grouped by namespace/team. A week of this data tells you whether your problem is fragmentation (many small underusing pods), contention (queue of pending pods), or waste (allocated-but-idle) — each has a different fix below.

  2. Split inference from batch at the node level. Label and taint GPU node groups: workload=inference (on-demand, stable) vs workload=batch (spot-eligible). Inference Deployments tolerate only their pool. This single move ends the worst incidents — a training job evicting the chatbot.

  3. Put batch behind Kueue. Kueue makes GPU demand visible and preemption governed instead of accidental:

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ClusterQueue
    metadata: {name: gpu-batch}
    spec:
      namespaceSelector: {}
      resourceGroups:
      - coveredResources: ["nvidia.com/gpu", "cpu", "memory"]
        flavors:
        - name: spot-l4
          resources:
          - {name: "nvidia.com/gpu", nominalQuota: 8}
      preemption:
        withinClusterQueue: LowerPriority
    

    Give each team a LocalQueue pointing at the ClusterQueue; jobs carry kueue.x-k8s.io/queue-name and get admitted (or wait, visibly) instead of pending mysteriously. Use WorkloadPriorityClasses so eval jobs yield to time-critical retrains. Verify current API fields with kubectl explain — Kueue's API is still v1beta1 and moves.

  4. Slice big cards for small workloads. If utilization data shows many pods using a fraction of an A100/H100-class card: enable MIG via the GPU Operator (mig.strategy=single or mixed) and request slices as resources, e.g. nvidia.com/mig-1g.10gb: 1 — hardware-isolated, right-sized shares for small models, notebooks, and embedding services. For dev/notebook workloads where isolation matters less, time-slicing is the cruder, driver-level alternative. Don't slice inference nodes running models that need the whole card.

  5. Buy batch capacity on spot. Karpenter NodePool for the batch pool: spot capacity type, several GPU instance families for diversity, sensible disruption budgets. Spot + Kueue is the pairing that works — interruptions become requeues, not failures — provided jobs checkpoint. Keep inference on on-demand/reserved; spot inference is how you turn a capacity event into a customer incident.

  6. Publish utilization SLOs and review monthly. Two numbers per pool: allocation rate (requested ÷ capacity) and true utilization (DCGM busy ÷ allocated). Targets like >70% true utilization on batch pools change behavior when they're on a dashboard next to the team names. Feed the $ view from pb-46's FinOps dashboards; use an AI assistant to draft the monthly narrative from the metrics export — and verify its numbers against the dashboard before it goes to leadership.

Key Takeaway:

Queueing, slicing, and spot are the same playbook you already know from CPU capacity management — the only new part is that the unit costs 30x more, which makes the discipline mandatory instead of nice.

Tool variants

  • Kueue (this playbook): K8s-native job queueing — the CNCF default.
  • Volcano / YuniKorn: alternatives with gang-scheduling strength for multi-pod distributed training; consider when large multi-GPU jobs dominate.
  • Run:ai-class commercial schedulers: add fairness, quotas, and dashboards out of the box — evaluate when the OSS assembly cost exceeds license cost.
  • Cloud-managed pools (GKE/EKS auto-provisioning): cover the Karpenter role on their platforms.

Verification

  • A batch job submitted without quota headroom waits visibly in Kueue (kubectl get workloads) rather than pending silently; it runs when quota frees.
  • Priority preemption drill: high-priority job preempts a lower-priority one, which requeues and completes.
  • Spot interruption drill (or simulated node drain): batch job requeues and resumes from checkpoint; inference pool unaffected.
  • MIG slices appear as schedulable resources and small workloads land on them, with DCGM confirming improved per-card utilization.

Pitfalls

  • Fractional sharing without isolation expectations. Time-slicing gives no memory isolation — one notebook OOMs the card for everyone. Use MIG where tenants are untrusted or workloads matter.
  • Spot for stateful/unresumable jobs. A 20-hour training run with no checkpointing on spot is a donation to the cloud provider. Checkpointing is the admission ticket to the spot pool.
  • Quota sized to peak fantasy. Teams request quota like they request headcount. Size nominalQuota from measured usage; let Kueue borrowing absorb bursts.
  • Utilization theater.DCGM_FI_DEV_GPU_UTIL at 90% can still mean inefficient kernels. It's a capacity signal, not a performance guarantee — pair with throughput metrics from pb-46.

Restricted-environment variant

  • All components (GPU Operator, Kueue, Karpenter, DCGM) are OSS and run in-cluster — suitable for client VPCs and air-gapped estates with mirrored images.
  • In client-dedicated clusters, per-client ClusterQueues make GPU spend attribution contractual-grade; export DCGM by client namespace.
  • India cost note: spot GPU pricing and MIG slicing are the difference between a viable and non-viable self-hosted stack at services-company margins — model the ₹/1M-token cost of pb-43 serving on sliced/spot capacity before defaulting to hosted APIs.
Note

GPU quotas are org politics rendered as YAML — get the priority ladder (whose jobs preempt whose) agreed in writing before you encode it in a PriorityClass.

Success criteria

  • True utilization on batch pools up measurably (target >70%) with waste visible per team.
  • Zero incidents of batch work degrading inference latency since node-pool separation.
  • Spot interruptions are routine non-events in the batch queue log, not pages.
  • The monthly GPU review runs from dashboards and a verified AI-drafted narrative, ending in concrete quota changes.
This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in