GKE Sandbox microVMs Go GA for Isolating AI Agent Code
GKE Sandbox microVMs went generally available on October 7, 2026. Each Pod now gets its own Linux kernel behind a hypervisor boundary on GKE. If your agents execute code a model wrote five seconds ago, that boundary matters more than any container setting. Below: what shipped, how it compares with gVisor, the node pool command, a test Pod, and the NetworkPolicy you have to add yourself.
What shipped on October 7
The GKE release notes say the microVM sandbox type is GA with GKE Sandbox on clusters running 1.37.0-gke.4713000 or later. It uses Kata Containers with the Cloud Hypervisor VMM, so each Pod runs in a lightweight VM with a full guest kernel. A container escape lands in the guest, not on your node.
Google's own list of fits starts with AI agents that generate and run code unsupervised, followed by browser automation such as Puppeteer.
GKE Sandbox microVMs vs gVisor
GKE Sandbox already had gVisor. The microVM type is a second option with different trade-offs:
| | gVisor | microVM | |---|---|---| | Isolation | Syscalls intercepted by a userspace kernel | Dedicated guest kernel, hardware virtualization | | Overhead | Dynamic, low base memory | Fixed 250 mCPU and 130 MiB per Pod | | Start time | Under 200 ms | About 1 to 2 seconds | | Node setup | Standard pools; default in Autopilot | Nested virtualization required | | GPU / TPU | Specific models and versions | None | | Metadata server | Blocked by default | Not blocked, needs a NetworkPolicy |
The fixed overhead adds up fast: 100 sandboxed Pods reserve 25 vCPU and about 12.7 GiB before any code runs. In return you get a real kernel, and privileged containers are allowed, with root confined to the guest OS.
Create a node pool for GKE Sandbox microVMs
The hardening guide gives this command. The Google Cloud console can't select the microVM type, so use gcloud:
gcloud container node-pools create <node-pool-name> \
--cluster=<cluster-name> \
--location=<control-plane-location> \
--sandbox=type=microvm \
--enable-nested-virtualization \
--machine-type=<nested-virt-machine-type>
Pick a machine type whose row in the machine series comparison table says nested virtualization is supported. Nested virtualization can't be switched on for an existing pool, so this is a new pool. A Standard cluster also needs at least one non-sandboxed pool.
Run an agent Pod with the microvm RuntimeClass
The RuntimeClass is named microvm. On manually created node pools GKE adds the node affinity and toleration for you.
apiVersion: apps/v1
kind: Deployment
metadata:
name: code-runner
namespace: agents
labels:
app: code-runner
spec:
replicas: 1
selector:
matchLabels:
app: code-runner
template:
metadata:
labels:
app: code-runner
spec:
runtimeClassName: microvm
containers:
- name: runner
image: <your-registry>/code-runner:<tag>
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: "1"
memory: 1Gi
Google recommends limits on every sandboxed container so a broken or hostile workload can't starve the node. To confirm the Pod really is in a VM, run kubectl exec <pod-name> -n agents -- cat /sys/class/dmi/id/product_name. The docs say the output should be cloud-hypervisor.
Block the metadata endpoints with a NetworkPolicy
gVisor hides the metadata server at the OS level. microVMs don't, so code running in the guest can reach it unless you stop it. Google's docs name 169.254.169.252/32 (port 988) and, on GKE Dataplane V2, 169.254.169.254/32 (port 80). With Workload Identity Federation for GKE, also block 169.254.169.254. This policy denies both addresses entirely, which is stricter than the per-port rules:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: block-metadata
namespace: agents
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 169.254.169.252/32
- 169.254.169.254/32
The Google page lists the addresses but ships no manifest, so this one is plain Kubernetes NetworkPolicy built from its values. Check that your cluster enforces NetworkPolicy, then try a request to the metadata address from inside the Pod. A policy nobody enforces is just a comment.
Gotchas
- No GPUs or TPUs. Keep inference on normal accelerator nodes and sandbox only the Pod that runs generated code. Google points GPU and TPU workloads to gVisor.
- Nested virtualization costs performance, and an organization policy that disables it blocks the feature outright.
- Unsupported in sandboxed Pods:
hostNetwork: true, seccomp, AppArmor and SELinux. - Metrics. Only Pod-level memory metrics work, not container-level.
- Cold starts. At 1 to 2 seconds, a fresh sandbox per tool call will show up in agent latency. Reuse one Pod per session if that hurts.
What to move first on Monday
Move the Pods that execute model-generated code: the code interpreter, the shell tool, the notebook runner. Leave the orchestrator that calls the model where it is. Upgrade a test cluster to 1.37.0-gke.4713000 or later, create the pool, add runtimeClassName: microvm to the runner Deployment, apply the NetworkPolicy, and confirm the metadata address is unreachable.
If your agents run code you didn't write, a dedicated kernel per Pod is now a production-ready option on GKE instead of a bespoke Kata install.