Run agents under gVisor or Kata
Run an agent’s pod, and the tool sandboxes it claims, under a sandboxed container runtime such as gVisor or Kata Containers. Both put a boundary between the pod and the host kernel, so a kernel vulnerability reachable from inside the pod does not reach the node.
Omnia selects the runtime through a Kubernetes RuntimeClass. It does not install gVisor or Kata.
Prerequisites
Section titled “Prerequisites”- Nodes with the runtime installed and registered with containerd: the
runscshim for gVisor, or a Kata shim such askata-qemu-runtime-rs. GKE Sandbox provides gVisor as the RuntimeClassgvisor; elsewhere use gVisor’s containerd quick start, or kata-deploy, which also creates Kata’s RuntimeClasses. - A RuntimeClass whose
handlernames that shim. - For Kata: nodes that expose hardware virtualisation (
/dev/kvm). See Trade-offs.
Create the RuntimeClass
Section titled “Create the RuntimeClass”Name the RuntimeClass anything; the handler must match the containerd runtime name. Set scheduling.nodeSelector when only some nodes have the runtime, so pods that select it land only on those nodes.
apiVersion: node.k8s.io/v1kind: RuntimeClassmetadata: name: gvisorhandler: runscscheduling: nodeSelector: example.com/gvisor: "true"A pod scheduled onto a node whose containerd has no such handler fails to start with a FailedCreatePodSandBox event. A pod that names a RuntimeClass the cluster does not define is rejected at admission, and the agent’s ReplicaSet reports FailedCreate.
Choose where to set it
Section titled “Choose where to set it”| Pods | Field |
|---|---|
One agent (facade, runtime and the injected policy-broker) | AgentRuntime spec.podOverrides.runtimeClassName |
| Every agent in a workspace | Workspace spec.runtime.runtimeClassName |
| The tool sandboxes of one class | SandboxClass spec.runtimeClassName |
| session-api, memory-api, eval-workers, Arena workers | That workload’s own podOverrides.runtimeClassName |
| A chart-owned Deployment (operator, dashboard, arena-controller, PromptKit LSP, doctor, management API) | <component>.podOverrides.runtimeClassName in Helm values |
An agent’s own spec.podOverrides.runtimeClassName replaces the Workspace default. An agent that sets its own serviceAccountName opts out of the Workspace identity defaults, but still inherits the Workspace runtimeClassName.
The facade and runtime share one pod, so they always run under the same runtime. A RuntimeClass on the agent does not apply to its sandboxes, and a RuntimeClass on a SandboxClass does not apply to the agent.
Run one agent under gVisor
Section titled “Run one agent under gVisor”-
Set
spec.podOverrides.runtimeClassNameon the AgentRuntime.apiVersion: omnia.altairalabs.ai/v1alpha1kind: AgentRuntimemetadata:name: support-agentnamespace: supportspec:podOverrides:runtimeClassName: gvisor# ...the rest of the spec -
Confirm the new pod carries the class.
Terminal window kubectl get pods -n support -l app.kubernetes.io/instance=support-agent \-o jsonpath='{.items[*].spec.runtimeClassName}'
The change alters the pod template, so the Deployment rolls the agent’s pods.
Run every agent in a workspace under gVisor
Section titled “Run every agent in a workspace under gVisor”Set spec.runtime.runtimeClassName on the Workspace. The operator re-reconciles every AgentRuntime in the workspace namespace and rolls each agent that does not set its own runtimeClassName.
apiVersion: omnia.altairalabs.ai/v1alpha1kind: Workspacemetadata: name: supportspec: displayName: Support namespace: name: support runtime: runtimeClassName: gvisorRun the tool sandboxes under gVisor
Section titled “Run the tool sandboxes under gVisor”Set spec.runtimeClassName on the SandboxClass the ToolRegistry names. Sandboxes claimed after the change run under it. See Sandbox security.
apiVersion: omnia.altairalabs.ai/v1alpha1kind: SandboxClassmetadata: name: codegen namespace: supportspec: image: ghcr.io/altairalabs/codegen-sandbox:latest runtimeClassName: gvisor # ...ports, filesystem, resourcesFor the chart’s codegen and browser classes, enable a preset: a copy of the class, beside it, on the RuntimeClass you name. A ToolRegistry handler opts in through sandbox.class:
sandbox: runtimePresets: gvisor: {enabled: true, runtimeClassName: gvisor} # class codegen-gvisor kata: {enabled: true, runtimeClassName: kata-qemu-runtime-rs} # class codegen-kata browserClass: runtimePresets: gvisor: {enabled: true, runtimeClassName: gvisor} # class browser-gvisorCheck the class before you rely on it. kubectl get sandboxclass codegen -n support shows the runtime family the operator resolved (FAMILY) and whether its claims can run (READY).
-
READYisFalsewhen the RuntimeClass does not exist, or when the class uses a workspace or scratch volume on Kata with Firecracker, which cannot serve either. ItsReadycondition gives the reason, and its claims failClassNotReady. -
FAMILYisunknownwhen Omnia does not recognise the RuntimeClass’shandler. The class still runs, but none of the protections is verified on it. Label the RuntimeClass with its family to vouch for it:Terminal window kubectl label runtimeclass my-vm sandbox.omnia.altairalabs.ai/runtime-family=kata
To confirm a sandbox runs on gVisor’s kernel, read its kernel log. gVisor’s log names gVisor; a container on the host kernel reads the host’s log or is denied it.
kubectl exec -n support deployment/<claim>-sandbox -- sh -c 'dmesg | head -3'The facade and runtime images ship without a shell, so check an agent pod by its spec.runtimeClassName instead.
To measure what your runtime keeps on your own nodes, run hack/sandbox-runtime-spike/run.sh from the Omnia repository. It runs a sandbox-shaped pod under each RuntimeClass you name and writes summary.md to the output directory. Delete the spike-<runtimeclass> namespaces it leaves behind.
STORAGE_CLASS=<your RWX class> hack/sandbox-runtime-spike/run.sh ~/.kube/config <context> ./out runc gvisorTrade-offs
Section titled “Trade-offs”gVisor
Section titled “gVisor”gVisor intercepts the pod’s system calls in a user-space kernel and implements most of the Linux system call surface, not all of it. A binary that needs an unimplemented call fails at that call.
- The built-in facade and runtime are Go binaries that use TCP, gRPC, HTTPS and the filesystem, which gVisor implements.
- A custom runtime (see Author a custom runtime) or a framework runtime that starts subprocesses brings its own system call profile. Test it under gVisor before you rely on it.
- gVisor runs networking in its own user-space stack. Every model call, session write and tool call pays that cost, so expect higher per-request latency and lower throughput than on the host kernel. Measure with your own traffic.
- File-heavy work, such as builds in a codegen sandbox, is slower than on the host kernel.
- gVisor needs no hardware virtualisation, so it runs on ordinary cloud VM nodes and on kind.
Kata Containers
Section titled “Kata Containers”Kata runs each pod in a lightweight virtual machine with its own guest kernel, so the system call surface is a full Linux kernel.
- Kata applies no seccomp filter inside its VM. The guest kernel is the boundary.
- Kata on Firecracker has no shared filesystem: a sandbox’s writes to
/workspacenever reach the volume, and scratchsizeLimitis not enforced. Use it only for a class with neither; the class reportsReady=Falseotherwise. - Kata needs hardware virtualisation on the node. On cloud VM nodes that means nested virtualisation, which not every instance type or provider offers. Bare-metal nodes avoid the question.
- Each pod carries the guest VM’s memory and CPU. Declare it in the RuntimeClass’s
overhead.podFixedso the scheduler and resource quotas count it. - Pods start more slowly than under runc or gVisor, which lengthens agent rollouts and the first tool call of a conversation that claims a sandbox.
- Agent pods are long-lived, so the start-up cost applies at rollout and scale-out. Sandboxes start per conversation, so their start-up cost lands on the first tool call that claims one.
- The pod security context, the ServiceAccount and, on a sandbox, the NetworkPolicy apply unchanged. A RuntimeClass adds a boundary and removes none of them.
- A RuntimeClass applies to a whole pod. Every conversation an agent pod serves shares that pod’s boundary.