Technical · Multi-Scheduler

One estate, two schedulers: optimizing Kubernetes and Slurm together.

Organisations rarely choose between Slurm and Kubernetes — they end up with both, and nobody can answer a simple question about total cost across the two. Why the waste patterns differ, why gang scheduling matters, and how to build one view across the estate.

By Ashutosh Dubey, Co-founder & CTO·August 11, 2026·9 min read
The short version
  • Most organisations run both Slurm and Kubernetes — usually without deciding to — and nobody can answer a simple question about total cost across the two.
  • The waste patterns differ. Kubernetes waste is continuous and quiet; Slurm waste is episodic and better documented. The fixes do not transfer.
  • Make them comparable: GPU hours as the unit, device telemetry as the truth, workload class — batch against service — as the grouping. Then fix the largest absolute waste first, wherever it lives.

Organisations rarely choose between Slurm and Kubernetes. They end up with both, usually without deciding to.

The pattern repeats often enough to be predictable. A research or data science group has run Slurm for years on hardware predating the current platform team. The platform team standardised on Kubernetes for everything else. Then AI workloads arrived, which sit cleanly in neither camp, and now training runs on Slurm while inference serves from Kubernetes, and nobody can answer a simple question about total cost across the two.

That question is worth answering, because the waste patterns are different in each and the fixes do not transfer.

Why both exist, and why neither is wrong

Slurm and Kubernetes were built for different workload shapes, and the differences are structural rather than a matter of maturity.

Slurm is a batch scheduler. Work arrives as jobs with defined resource requirements and finite duration, waits in a queue, runs to completion and releases its resources. It assumes a fixed pool of hardware and its job is to allocate that pool fairly and efficiently over time.

Kubernetes is a service orchestrator. Work is long-running, expected to stay up, and scaled horizontally in response to demand. It assumes elastic capacity and its job is to keep declared state true.

The clearest difference is how each handles a distributed job that needs several nodes at once.

Slurm allocates the whole set together. Kubernetes, by default, does not. The Kubernetes project’s own enhancement proposal for gang scheduling states the position directly: since version 1.0, the scheduler has treated the pod as the unit of scheduling, and each pod is an independent decision.

The practical consequence is the one that costs money. Submit a four-node distributed training job to Kubernetes and you can end up with three pods running and a fourth pending because no node has free GPUs. The three that started sit blocked at a synchronisation barrier, holding accelerators and doing nothing, until either the fourth arrives or somebody notices.

That single difference explains much of why serious distributed training still runs on Slurm.

Two clarifications worth having, because the terminology causes genuine confusion.

First, add-on schedulers do provide all-or-nothing semantics on Kubernetes. Volcano, Kueue, the upstream scheduler-plugins coscheduling plugin and NVIDIA’s KAI Scheduler all address this. A native in-tree API is also arriving, introduced in Kubernetes v1.36, so this is an actively moving area rather than a settled limitation.

Second, the phrase “gang scheduling” means different things in the two communities. In Kubernetes it means all-or-nothing scheduling of a set of pods. Slurm uses the same phrase for a separate feature involving time-slicing between suspended jobs. The contrast drawn here is between Slurm’s all-or-nothing allocation and Kubernetes default per-pod scheduling, which is a real difference regardless of what either feature is called.

Two schedulers, two different waste patterns

How Kubernetes wastes GPUs

Waste in Kubernetes is continuous and quiet. A pod declares resource requests, gets scheduled, and holds those resources for as long as it runs, which for a service is indefinitely. Nothing triggers a review. There is no completion event, no job record, no natural moment at which anyone compares requested against used.

Inference services are the common offender. A model server sized for peak traffic holds a full accelerator through the overnight trough. Development namespaces are worse, since notebook pods hold GPUs for the length of a working day while executing code for a few minutes of it.

How Slurm wastes GPUs

Waste in Slurm is episodic and, in one important respect, easier to find. Every job produces an accounting record with a requested allocation and an actual runtime. The evidence is there, whether or not anyone looks.

The pattern is over-requesting driven by asymmetric failure. Under-request and the job dies losing days of work. Over-request and nothing visible happens. Add time-limit padding, which degrades backfill efficiency across the whole queue, and idle periods inside long allocations during checkpoint writes and barrier waits.

Slurm’s documentation is explicit that backfill scheduling depends on reasonably accurate time limits, because the expected start time of pending jobs is calculated from when running jobs are expected to complete. Inflated limits therefore cost throughput for everyone, not just the padded job.

The consequence for tooling

Kubernetes cost tooling assumes continuous telemetry against long-lived objects and an elastic underlying pool. Slurm analysis is job-oriented and assumes fixed capacity where the meaningful currency is queue time rather than money.

A tool built for one produces confused output on the other. Which is why organisations running both typically run two sets of tools and reconcile nothing.

Making cost comparable across both

The unifying question is the same in both environments even though the mechanics differ. What was allocated, what was consumed, and what is the gap?

Four things to establish.

A single unit of account. GPU hours and node hours work across both. Currency does not, because in a mixed estate the Kubernetes side is often cloud-billed while the Slurm side runs on capitalised hardware. Comparing a monthly invoice against depreciated capital expenditure produces a meaningless number. Compare capacity first, then apply cost models separately if you need currency.

Consistent utilisation semantics. This is where most attempts fail. Kubernetes reports requests against usage per container. Slurm reports allocation against runtime per job. Neither says what the accelerator actually did. Device telemetry is the common denominator that makes them comparable, because it measures hardware behaviour independent of which scheduler asked for it.

Workload classification, not scheduler classification. The useful split is batch against service, not Slurm against Kubernetes. A batch training job has the same economics whether it runs under Slurm or as a Kubernetes Job. A long-running inference service has the same economics either way. Grouping by workload shape makes the numbers mean something.

Honest boundary accounting. Data movement between the two environments has real cost, especially where the Kubernetes side is in cloud and the Slurm side is on premise. Egress is easy to overlook and occasionally exceeds the compute savings from any placement decision.

Where workloads should actually run

Once you can see both, placement becomes a question you can answer rather than an accident of history.

Runs better on Slurm: multi-node distributed training needing all-or-nothing allocation, long-running simulation, anything requiring tightly coupled interconnect performance, and workloads with an established queue and fair-share policy that users understand.

Runs better on Kubernetes: inference serving with variable demand, anything needing autoscaling, workloads that must integrate with service meshes or standard CI and CD, and mixed workloads where GPU work is one component of a larger application.

Genuinely ambiguous: batch inference, model evaluation pipelines, and hyperparameter sweeps. These run acceptably on either, and the deciding factors are usually where the data already sits and which team owns the pipeline rather than anything technical.

"The problem is not having two schedulers. The problem is having no view across them."

One caution worth stating plainly. Consolidating onto a single scheduler is a large migration with an uncertain payoff, and it is frequently proposed for reasons of tidiness rather than economics. Running both is a legitimate steady state.

What to do with a mixed estate

Instrument the hardware, not the scheduler. Device-level telemetry gives you one truth about what accelerators did. Scheduler records tell you who asked for what. Join them on both sides and you have comparable numbers for the first time.

Report in capacity terms. GPU hours allocated, GPU hours consumed, and the gap between them, split by workload class. This single view usually reveals that one side of the estate is materially worse than the other, and it is not always the side people expect.

Fix the largest absolute waste first, wherever it lives. Not the worst percentage. A training job at 60% efficiency on sixty-four GPUs for three days wastes far more than a notebook at 5% on one card. Percentages consistently point at the wrong target.

Keep the safety model consistent. Whatever changes get made, apply them the same way in both environments. Recommendations reviewed by a human, changes scoped and reversible, and an audit trail in systems you already run. A cost programme that causes one incident does not get corrected. It gets cancelled.

The underlying point

Slurm and Kubernetes look like different worlds and are usually owned by different teams with different vocabularies. Underneath, the economics are identical.

Someone declares what a workload needs before it runs. The declaration is padded because under-requesting fails loudly and over-requesting fails silently. Nobody revisits the declaration because nothing prompts them to. The gap between declared and consumed is where the money and the capacity go.

That is one problem wearing two sets of clothes. Recognising it as one problem is what makes it possible to measure the whole estate with a single question, rather than running two programmes that never reconcile.

About OptOps. OptOps is the optimization layer for enterprise infrastructure, built to work across substrates rather than within one. The same engine reads real workload behaviour on Kubernetes in the cloud and on HPC and GPU compute on premise, producing sized recommendations with cost and confidence attached. Read-only by default, so it deploys where write-access tools cannot.

References

One view across the whole estate

OptOps reads device telemetry and scheduler records on both sides — Slurm and Kubernetes — and reports allocated against consumed in the same units, split by workload class. Read-only by default. See which side of your estate is actually worse.

Book a demo Get a free Cluster Efficiency Assessment

Frequently asked questions

Should we use Slurm or Kubernetes for AI workloads?

It depends on workload shape rather than on which is better. Slurm suits multi-node distributed training because it allocates the full set of nodes together. Kubernetes suits inference serving and anything needing autoscaling or integration with standard service tooling. Many organisations run both, which is a reasonable steady state.

Can you run Slurm and Kubernetes on the same cluster?

Both can operate within one organisation and there are integration approaches that let them share hardware pools, though most estates keep them on separate hardware with different teams. The practical difficulty is rarely coexistence itself. It is that neither system reports in terms the other can be compared against, so nobody has a view of total cost or utilisation across both.

What is gang scheduling and why does Kubernetes lack it by default?

Gang scheduling, in Kubernetes terminology, guarantees that all components of a distributed job start together or none start. The Kubernetes scheduler has treated the pod as the unit of scheduling since version 1.0, so a multi-pod training job can partially start, leaving running pods blocked at a synchronisation barrier while holding GPUs. Add-on schedulers including Volcano, Kueue and the coscheduling plugin provide the capability, and a native API was introduced in Kubernetes v1.36.

How do you compare infrastructure cost across Slurm and Kubernetes?

Use GPU hours and node hours as the common unit rather than currency, since one side is often cloud-billed while the other runs on capitalised hardware. Use device telemetry as the shared source of truth for what hardware actually did, because scheduler-native metrics are not comparable. Group by workload class, batch against service, rather than by scheduler.

Which scheduler wastes more GPU capacity?

Neither inherently, but the waste behaves differently. Kubernetes waste is continuous and largely invisible, since long-running services hold resources indefinitely with no event prompting review. Slurm waste is episodic and better documented, because every job produces an accounting record showing requested against actual usage. The Slurm variety is easier to find if anyone looks.

Is it worth consolidating onto a single scheduler?

Usually not for cost reasons alone. Consolidation is a substantial migration with uncertain payoff, and it is often proposed for architectural tidiness rather than economics. Running both is a legitimate steady state. The real problem in most mixed estates is the absence of a unified view of utilisation, which can be solved without migrating anything.

Calculate ROI