The L3 half of agent sandboxes on Kubernetes: an aggregated apiserver that
serves sandboxes.agents.x-k8s.io from live node inventory, the warm-pool
driver that fills those nodes, and the e2b-compatible control and data planes in
front of them. The Sandbox API itself is
kubernetes-sigs/agent-sandbox,
consumed as a Go module; this repository stores no copy of it and ships no
controller of its own.
| Component | What it is |
|---|---|
cmd/sandbox-apiserver |
Aggregated apiserver for sandboxes.agents.x-k8s.io/v1beta1: scatter-gather reads, node-local claim/release on create/delete, the pause/resume/fork/snapshot subresources, the optional e2b REST surface, and the in-process SandboxWarmPool driver |
cmd/sandbox-envd-proxy |
The e2b data plane: one public entry point that carries files, commands and pty into a sandbox’s guest port |
cmd/sandbox-e2b |
The e2b surface on a sandboxd mesh with no Kubernetes, with the envd data plane in the same process when asked; see mesh mode |
nodeinventories.sandbox.cocoonstack.io |
The one CRD this repository owns: per-node summary of live sandboxes, warm capacity, promoted templates and the node’s sandboxd address |
api/v1beta1 |
NodeInventory plus the lifecycle subresource payloads |
pkg/scale, pkg/sandboxd, pkg/e2bcompat, pkg/e2bbuild, pkg/envdproxy |
The store, the sandboxd client, the e2b translation layer, its template build executor, the proxy |
pkg/scale/kubeinventory, pkg/scale/meshinventory |
The two inventory sources the store reads: NodeInventory objects through an informer cache, or a sandboxd mesh polled over HTTP |
any Kubernetes client (kubectl / client-go / controller-runtime)
| e2b SDK (E2B_API_URL)
v |
kube-apiserver + agent-sandbox CRDs v
| sandbox-apiserver (aggregated)
+-- upstream controller -> Pod | |
| routed by the pod-template | +-- e2b REST
| contract to a virtual node |
v v
vk-sandbox / vk-cocoon ------------> sandboxd node-local warm pools
^
sandbox-envd-proxy (files / commands / pty)
The Pod path and the L3 path both end at the same node-local warm pool; they
differ in what Kubernetes stores. On the Pod path etcd holds one object per
sandbox. On the L3 path it holds one NodeInventory per node and the pool’s
intent, so object count is O(pools + nodes) however many sandboxes are live —
which is why one SandboxWarmPool patch could take 20 nodes to 50 000 running
microVMs while etcd saw ~2 writes/s.
The cost of that design is a list view assembled from inventory nodes
republish on a ~30 s cadence: list and watch are eventually consistent. A
lookup of one sandbox the inventory does not list yet — by name, by a list or
watch pinned to one name in a namespace, or by claim id from the e2b surface
and the envd proxy — asks the nodes directly.
files, commands and pty into the right
sandbox’s guest port, over vsock and without exposing a nodesandbox.cocoonstack.io/v1beta1. The agents.x-k8s.io and
extensions.agents.x-k8s.io types are upstream’s; their reference is in
agent-sandbox’s docsSource and issue tracker: github.com/cocoonstack/sandbox-operator. Part of the cocoonstack MicroVM platform.