Blog

Deploying gVisor on Kubernetes for AI agent sandboxes

· by

Installing gVisor on a Kubernetes node is not enough. Before the scheduler sends an AI agent sandbox to that node, verify the effective container runtime configuration during the current boot. Then run a real Kubernetes Pod through the declared RuntimeClass.

We reached this rule during controlled node tests at plori on September 6, 2026. A RuntimeClass existed while its named runtime handler was absent. In another test, an installation success marker remained after the effective configuration no longer contained the handler. Later tests admitted two fresh nodes with local proof. We separately verified a representative Kubernetes workload on the first node and after rebooting it.

What does a working gVisor installation require?

The upstream gVisor installation guide describes supported hosts and installation packages. Current release archives contain runsc, its containerd shim, and adjacent helper binaries. Keep the complete installed package together.

For containerd, the gVisor quick start adds a named runtime handler, restarts containerd, and runs a container with that handler. Kubernetes then maps a RuntimeClass name to the handler. Kubernetes communicates with container runtimes through the Container Runtime Interface (CRI).

These are separate objects:

Object What it establishes
Installed gVisor files The node has the runtime and its required files
Effective containerd handler The active CRI configuration can select gVisor
Kubernetes RuntimeClass A Pod can request that named handler
Successful Pod and DNS test Scheduling, runtime execution, and name resolution worked for the tested workload

Kubernetes documents this mapping in RuntimeClass. The handler value must match the runtime configuration on every eligible node. RuntimeClass scheduling rules can also direct Pods to nodes that support that handler.

Why are install markers and Node Ready insufficient?

An installer can finish while the active runtime configuration is incomplete or later replaced. In one of our historical tests, a completion signal existed although the effective gVisor handler did not remain present. Our evidence did not identify the exact process that changed that configuration, so we do not assign a more specific cause.

Node Ready proves a different property. It says kubelet considers the node available. It does not prove that an optional runtime handler exists. A RuntimeClass object also lives at cluster scope. Creating it does not configure containerd on each node.

Read the active CRI state after node initialization ends. Verify that the named handler resolves to the expected runtime type. Verify runtime readiness and network readiness when the CRI reports those conditions. Start a local test container through that exact handler. Verify runtime-specific evidence from inside it.

Tie this proof to the node identity and current boot. A result from yesterday's boot says nothing about the process state after today's reboot.

How should you qualify a fresh node for agent workloads?

Two synchronous arrangements in our controlled experiments created ordering failures. Node initialization and runtime preparation waited on each other. An asynchronous, retryable preparation process avoided that dependency in our environment.

Use this general verification checklist:

  1. Keep the node ineligible while you prepare the runtime.
  2. Install a pinned, complete gVisor release after the provider's node initialization settles.
  3. Verify the active CRI handler and current runtime conditions.
  4. Run a bounded local container through gVisor during the current boot.
  5. Publish node eligibility only after the local verification passes.
  6. Independently verify a representative Kubernetes Pod, its RuntimeClass, and required networking.

The automated local test qualifies the node before the admission process publishes eligibility. It isolates the runtime installation from Kubernetes networking. The independent Pod test happens after publication and covers scheduling, CRI sandbox creation, and Pod networking. The Kubernetes SIG Agent Sandbox gVisor quickstart also uses a RuntimeClass for sandbox workloads. Each cluster still needs a reliable way to qualify compatible nodes.

In our controlled run, automated local admission passed on two newly created nodes. We then ran the independent Kubernetes and DNS validation on the first node. After one deliberate reboot of that node, admission rejected the old proof, qualified the new boot, and passed the independent validation again. These runs required no manual runtime repair.

What happens when the runtime configuration disappears?

Scheduling metadata is only an admission signal. It cannot guarantee that runtime configuration remains present after qualification.

We tested this boundary by removing the gVisor handler on a disposable node while deliberately leaving its readiness label in place. A new protected Pod reached that node and failed sandbox creation with a missing-handler error. We observed no fallback to the default runtime. After we withdrew the label, another protected workload remained unscheduled.

This failure is preferable to silently running an agent sandbox with a different runtime. Keep the RuntimeClass handler explicit, and use node eligibility to prevent known-unprepared nodes from receiving the workload.

Readiness metadata can remain stale during startup or while the Kubernetes API is unreachable. Our tests do not establish continuous runtime health or qualify every storage and network integration. They also do not constitute a security assessment. Repeat representative workload tests after changes to the node image, container runtime, gVisor release, or cluster networking.