Kubernetes RuntimeClass Placement
Kubernetes RuntimeClass Placement determines how workloads are scheduled based on node-specific runtime classes for efficient resource use and compliance.
Kubernetes RuntimeClass Placement is the interaction between the RuntimeClass resource — which lets a Pod specify a non-default container runtime configuration (gVisor, Kata Containers, or a hardened variant of the standard runtime) — and the scheduler's node-selection logic, ensuring a Pod requesting a specific runtime is only ever placed on nodes actually capable of running it. Because not every node in a heterogeneous cluster necessarily has every alternative runtime installed, RuntimeClass placement exists specifically to prevent a Pod from being scheduled onto a node where its requested runtime is unavailable, which would otherwise surface only as a confusing Pod startup failure well after scheduling had already (incorrectly) succeeded.
The mechanism works by having a RuntimeClass object optionally carry its own node-targeting rules, which the scheduler merges with the Pod's own placement constraints when a Pod references that class.
RuntimeClass Fundamentals
Declaring a RuntimeClass
A RuntimeClass object names a specific container runtime handler configured on the underlying container runtime (containerd, CRI-O), which nodes must have set up correspondingly for Pods using it to actually start successfully.
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: gvisor
handler: runsc
Referencing It from a Pod
spec:
runtimeClassName: gvisor
containers:
- name: sandboxed-app
image: codartium/app:latest
How Placement Is Constrained
scheduling.nodeSelector on the RuntimeClass
A RuntimeClass can carry its own scheduling.nodeSelector, automatically merged into the node selector of any Pod referencing it — this guarantees the Pod is only scheduled onto nodes matching both its own nodeSelector and the RuntimeClass's required labels, without needing every Pod author to remember to add those labels manually themselves.
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: gvisor
handler: runsc
scheduling:
nodeSelector:
sandbox.codartium.io/gvisor: "true"
scheduling.tolerations on the RuntimeClass
Similarly, a RuntimeClass can carry tolerations that are automatically merged into any referencing Pod's tolerations, allowing nodes running the alternative runtime to be tainted (preventing accidental scheduling of ordinary Pods there) while Pods explicitly requesting that runtime automatically tolerate the taint without needing to declare it themselves.
scheduling:
nodeSelector:
sandbox.codartium.io/gvisor: "true"
tolerations:
- key: "sandbox.codartium.io/gvisor"
operator: "Exists"
effect: "NoSchedule"
Why Centralizing Placement Rules on RuntimeClass Matters
Reducing Author Error
Without this centralization, every author of a Pod needing the sandboxed runtime would need to remember to add the correct nodeSelector and toleration manually — a mistake here would not prevent the Pod from being created, but could result in it being scheduled onto an ordinary node lacking the required runtime handler, causing a startup failure discovered only after the fact. Centralizing the rule on the RuntimeClass itself removes this class of mistake entirely, since the merge happens automatically regardless of what the Pod author remembered to specify.
Consistent Enforcement Across Teams
In multi-team clusters, platform teams typically own RuntimeClass definitions and their associated node pool labeling/tainting scheme, while application teams simply reference runtimeClassName in their Pod specs — this division of responsibility keeps the placement logic centrally maintained and consistent, rather than duplicated and potentially drifting across many application manifests.
Interaction with Resource Overhead
The overhead Field
A RuntimeClass can also declare overhead, describing the additional CPU and memory resources the runtime sandbox itself consumes beyond the Pod's own container resource requests (sandboxed runtimes like gVisor or Kata Containers run an additional isolation layer that consumes its own resources). The scheduler adds this overhead on top of the Pod's declared requests when performing its resource fit calculation, ensuring nodes are not over-committed by underestimating the true resource footprint of a sandboxed Pod.
overhead:
podFixed:
cpu: "250m"
memory: "128Mi"
Diagnosing RuntimeClass Placement Issues
kubectl get runtimeclass gvisor -o yaml
kubectl describe pod codartium-sandboxed-app | grep -A 5 "FailedScheduling"
kubectl get nodes -l sandbox.codartium.io/gvisor=true
A Pod referencing a RuntimeClass that fails to schedule is diagnosed the same way as any other scheduling failure, but with particular attention to whether any nodes actually carry the labels the RuntimeClass's scheduling.nodeSelector requires.
Example
apiVersion: v1
kind: Pod
metadata:
name: codartium-runtimeclass-example
spec:
runtimeClassName: gvisor
containers:
- name: sandboxed-app
image: codartium/app:latest
resources:
requests:
cpu: "250m"
memory: "256Mi"