Syself Autopilot ships three runtime classes. A workload can select the runtimeclass that fits it. This page describes what each one is, when to use it, and how to set it. ## What is a runtime class? A [RuntimeClass](https://kubernetes.io/docs/concepts/containers/runtime-class/) is a Kubernetes object that selects the runtime a pod runs on. Syself Autopilot ships three of them: `standard`, `runc`, and `secure`. A pod picks one with the `runtimeClassName` field, and a pod that sets nothing runs on `standard`. The three differ in the runtime behind them and in how far each pod is isolated from the node, from a shared kernel up to a private virtual machine. ## Container runtimes Each runtime class below lists what it is and a case where it fits. ### `standard` `standard` is the default runtime class. Behind it is crun, a lightweight OCI runtime written in C. Most Kubernetes clusters run runc, which is written in Go. Syself uses crun because it starts containers faster and uses less memory per container. It runs on every node type, cloud and bare metal, and a pod that sets no `runtimeClassName` uses it. This covers the large majority of workloads, from stateless APIs and web servers to background workers and batch Jobs. Unless a workload has a specific reason to change, such as an image that misbehaves on crun or code that needs VM isolation, leave it on `standard`. ### `runc` `runc` is the reference OCI runtime, the one most Kubernetes clusters run by default. On Syself Autopilot it is a fallback. A small number of container images behave differently on crun, and `runc` exists for those cases. Like `standard`, it shares the node's kernel and runs on every node type. Use `runc` when a specific image does not start or misbehaves under `standard`. A third-party image built and tested only against runc, for example, might fail on crun. Setting `runtimeClassName: runc` runs it on the runtime it expects, without changing anything else about the workload. ### `secure` `secure` runs each pod in its own lightweight virtual machine with its own kernel, using Kata Containers. If a process escapes the container it stays inside that VM and cannot reach the host or a neighbouring pod, even through a kernel-level bug. This is a stronger boundary than the shared-kernel runtimes, and it costs more, because each pod carries the VM's startup time and a fixed amount of CPU and memory overhead. Kata needs hardware virtualization (KVM), which on Hetzner exists only on [bare-metal nodes](/docs/hetzner/apalla/servers-and-nodes/bare-metal/add-bare-metal-servers), so `secure` pods do not schedule on cloud VMs. The runtime class carries its own node selector, so a `secure` pod with no capable node stays `Pending` instead of falling back to a shared kernel. A pod that sets `hostNetwork: true` or runs as `privileged` cannot use `secure`, since neither is compatible with the VM boundary. Use `secure` for code you do not trust, or cannot afford to have escape onto the node. A platform that runs customer-supplied builds, or executes code its own users submit, can place each of those workloads on `secure` so a breakout is contained to its own VM instead of reaching the kernel that every other pod on the node shares. ## Why crun is the default Syself chose crun over runc, the more common default, for two reasons that show up at scale. crun is written in C rather than Go, so it starts containers faster, which shortens the gap between a pod being scheduled and its container running when you scale up. It also uses less memory per container, so each node keeps more memory free for your workloads. Both effects grow with the number of pods on a node, which is why crun is the cluster-wide default rather than something you opt into. ## Select a runtime class Select a runtime class per workload with the `runtimeClassName` field on the pod spec. A pod that sets nothing runs on `standard`, so you set this field only to switch to `runc` or `secure`. ```yaml title="deployment.yaml" apiVersion: apps/v1 kind: Deployment metadata: name: app spec: replicas: 2 selector: matchLabels: app: app template: metadata: labels: app: app spec: runtimeClassName: secure # standard (default), runc, or secure containers: - name: app image: nginx:stable ``` ### Secure runtime requirements and overhead `secure` schedules only on bare-metal nodes with hardware virtualization, and adds roughly 250m CPU and 160Mi memory of VM overhead per pod on top of the container's own requests. Account for that when you schedule workloads and set resource requests. ## Related - [Run a workload in a user namespace](/docs/hetzner/apalla/workloads/secure/run-in-a-user-namespace) - [Set security contexts](/docs/hetzner/apalla/workloads/secure/set-security-contexts)