FR
live

Kubernetes 1.37 adds scheduler preemption for in-place pod resize

On September 10, 2026, Kubernetes 1.37 introduced, behind the InPlacePodVerticalScalingSchedulerPreemption feature gate, scheduler preemption for in-place pod resizes stuck in the Deferred state. Operators can now bin-pack nodes with low-priority workloads without risking blocked scale-ups for critical services.

A server blade pulled partway out of a fully occupied blade enclosure, its empty slot lit by a single amber indicator.

September 10, 2026. Natasha Sarkar (Google) announced on the Kubernetes blog that scheduler preemption for in-place pod resize is arriving in alpha, behind the InPlacePodVerticalScalingSchedulerPreemption feature gate. It closes the last gap in restart-free vertical scaling: until now, a scale-up request that exceeded a node’s free capacity sat indefinitely in the Deferred state. The scheduler can now evict low-priority workloads to make room. For anyone bin-packing nodes, that is a paradigm shift in density.

The hole left by in-place resize

In-place pod resize graduated to stable in Kubernetes 1.35. It lets operators adjust the CPU and memory allocated to a running container without a restart or downtime. But it opened a precise scheduling gap.

When a user or controller — such as the Vertical Pod Autoscaler — raises the requests of an active container, the Kubelet checks whether the node has enough spare allocatable capacity. If the node is fully utilized and cannot satisfy the new limits, the Kubelet sets the container’s resizeStatus to Deferred. Unlike an Infeasible resize — rejected immediately because it exceeds physical machine boundaries, namespace limit ranges, or admission quotas — Deferred means the request is valid but temporarily unactuatable, waiting for capacity to free up.

Before this feature, that wait could become permanent. If an in-memory database or a real-time web server needed more memory to avert an OOM crash, and the node was full, the resize stayed Deferred. The administrator’s options were limited and painful: manually evict low-priority pods, wait for the cluster autoscaler to provision a larger node (a heavy operation that violates the whole “no restart” promise of in-place scaling), or deploy a custom autoscaling solution.

The root cause is simple: the kube-scheduler was unaware of deferred resizes. It could not apply its priority-based preemption — the eviction of lower-priority workloads to free a resource — to pods that were already placed.

What the alpha preemption changes

The new feature gate reconnects the scheduler to the problem. When a high-priority pod requires an in-place resize that exceeds node capacity, the scheduler automatically evicts lower-priority pods on the same host to clear headroom. You get both density (bin-packing nodes with batch or best-effort jobs) and responsiveness for critical services.

The mechanics rest on four architectural principles.

Centralized scheduler tracking. The kube-scheduler watches for pods carrying a Deferred resizeStatus. Normally, a pod with spec.nodeName populated is considered placed and drops out of the active scheduling queue. Under this feature gate, the scheduler intercepts pods with the Deferred condition and keeps them in active evaluations specifically to trigger preemption, until the Kubelet completes the resize actuation.

Single-node preemption boundary. Unlike placement preemption — which evaluates every node in the cluster to find the best fit — resize preemption is strictly local to the pod’s assigned node. The scheduler identifies eligible low-priority “victim” pods on the same host and initiates graceful eviction. If, even after evicting all eligible low-priority workloads, the node cannot absorb the resize, the pod remains Deferred.

Safe resource reservation. To prevent scheduling races and double allocation, the scheduler treats the resources requested for a resize as already consumed. The Kubelet can then actuate the resize as soon as preemption takes effect, without another pod slipping into the freed headroom.

Separation of concerns with the Kubelet. Under resource pressure, the Kubelet has a local mechanism, the critical Pod admission handler, which can evict low-priority pods to guarantee admission for a critical system pod. Here, the feature gate explicitly removes that logic from the Kubelet for in-place resizing: it delegates the preemption decision to the scheduler, guaranteeing a single orchestrator that respects global priorities, Pod Disruption Budgets (PDBs), and graceful-termination policies.

Competing updates are handled dynamically. If a higher-priority resize arrives on the same node during an active preemption cycle, the Kubelet prioritizes it, and the scheduler observes the change to trigger a new preemption round if needed.

Per-node configuration and opt-out

The feature turns on cluster-wide: Kubernetes 1.37 or later across the control plane and worker nodes, with the InPlacePodVerticalScalingSchedulerPreemption gate enabled on kube-apiserver, kube-scheduler, and kubelet.

It also offers fine-grained, per-node control. Administrators and controllers (such as a cluster autoscaler) can disable resize preemption on specific nodes via the new spec.podPreemptionPolicy field:

yaml
apiVersion: v1
kind: Node
metadata:
  name: batch-workload-node
spec:
  podPreemptionPolicy:
    disableResizePreemption:
      - "cluster-autoscaler.kubernetes.io/disable-preemption"
      - "operator.example.com/policy-override"

The typical use case is a controller that prefers to scale down other pods or dynamically adjust node capacity itself, enabling scheduler preemption only as a last resort. The granularity of disableResizePreemption lets you reserve that policy for batch-dedicated nodes while leaving preemption active on the nodes hosting critical services.

Test preemption locally with kind

The documentation ships a reproducible scenario on a single-node kind cluster with deliberately constrained CPU headroom. The goal: watch preemption happen without deploying a full cluster.

Step one — a 1.37 cluster with the feature gate. Create a kind-config.yaml that enables InPlacePodVerticalScalingSchedulerPreemption:

yaml
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
  InPlacePodVerticalScalingSchedulerPreemption: true

Then create the cluster while pinning a Kubernetes 1.37 or newer image, otherwise the gate will not be recognized:

bash
kind create cluster --config kind-config.yaml --image kindest/node:v1.37.0

Step two — saturate the node. Deploy two PriorityClasses — a high-priority (value 1000000) and a low-priority (value 1000) — plus two pods: a low-priority pod requesting 3 CPU and a high-priority pod requesting 4 CPU. Together they consume 7 of the 8 allocatable CPUs on a standard kind node, leaving 1 CPU of free headroom.

Step three — trigger a Deferred resize. Patch the high-priority pod to raise its CPU request from 4 to 6 (a +2 CPU delta). With only one free CPU, the request exceeds remaining allocatable capacity. The resize subresource is the entry point for in-place scaling:

bash
kubectl patch pod high-priority-pod --subresource resize --patch \
  '{"spec":{"containers":[{"name":"app","resources":{"requests":{"cpu":"6"},"limits":{"cpu":"6"}}}]}}'

Step four — observe the eviction. With the gate active, the kube-scheduler intercepts the Deferred condition on the high-priority pod and targets the low-priority pod for preemption. Inspect the low-priority pod’s events to confirm the scheduler triggered the eviction, then verify the high-priority pod leaves the Deferred state once headroom is freed.

The scenario demonstrates exactly the behavior the architecture promises: preemption that is local to the node, triggered only when free capacity falls short, and respectful of declared priorities.

Verdict

Kubernetes 1.37 forces nobody: resize preemption is alpha, feature-gated, and reversible per node. But its value is immediate for operators who bin-pack.

If you already bin-pack your nodes with low-priority workloads, enable InPlacePodVerticalScalingSchedulerPreemption in staging, validate PDB behavior (preemption respects them, but an eviction is still an eviction), then roll it out to the nodes running critical services. The payoff is twofold: density preserved, and an end to Deferred resizes that drag on.

If you don’t bin-pack, the feature is not urgent: it only matters when the node is saturated at the moment of a scale-up. Focus instead on moving to 1.37 and adopting the Vertical Pod Autoscaler, which remains the natural trigger for in-place resizes. Preemption will come in to consolidate a vertical-scaling strategy you will have already put in motion.

Either way, treat this as an alpha to validate, not to depend on: the feature gate is reversible, but the eviction behavior it introduces can surprise dashboards that assume lower-priority pods are never touched. Watch its graduation path before building critical scheduling policies on top of it.

References

The cyber brief, every Tuesday

The flaws that matter and the patches to apply, in a ten-minute read.

No spam. One-click unsubscribe.
read next

On the same topic

GitLab 19.3.2 closes an unauthenticated arbitrary file read and seventeen more flaws

GitLab shipped versions 19.3.2, 19.2.6 and 19.1.8 on September 10, 2026 to fix eighteen flaws, including an unauthenticated arbitrary file read through the commits API and an insecure deserialization scored CVSS 9.9. Every exposed self-managed instance must be updated without delay, and protected CI/CD variable secrets need a review.

← Back to the feed

Type at least two characters.

navigate open esc dismiss