Performance Comparisons Between Secure Container Runtimes Supported by OpenSandbox
gVisor delivers the best balance for AI workloads with 10–50 ms cold-start overhead and ~50 MiB memory per sandbox, while Kata Containers with Firecracker minimizes memory to ~5 MiB with 125 ms startup, and Kata with QEMU provides maximum isolation at the cost of ~500 ms cold-start latency.
OpenSandbox extends beyond the default runc implementation to support multiple secure container runtimes that provide varying levels of isolation for untrusted code execution. Understanding the performance comparisons between different secure container runtimes is critical for operators balancing security guarantees against startup latency and memory density in production AI-code environments. The benchmarks documented in OSEP‑0004 and the user guide at docs/secure-container.md provide the empirical basis for these deployment decisions.
Secure Container Runtime Performance Characteristics
OpenSandbox supports five distinct runtime configurations, each trading isolation depth against resource overhead. The following table summarizes the cold-start latency and memory footprint per sandbox as documented in OSEP‑0004 lines 16‑22 and docs/secure-container.md lines 23‑29:
| Runtime | Isolation Mechanism | Startup Overhead (cold) | Memory Overhead per Sandbox | Typical Use Case |
|---|---|---|---|---|
| runc (default) | Process-level cgroups | ~0 ms | Minimal (≈ 5 MiB) | Trusted workloads, local development |
| gVisor | User-space kernel intercepting syscalls | ~10–50 ms | ≈ 50 MiB | General AI-code workloads requiring low overhead |
| Kata (QEMU) | Full virtual machine via QEMU hypervisor | ~500 ms | 20–50 MiB | Maximum compatibility and isolation for untrusted code |
| Kata (Firecracker) | Micro-VM using Firecracker hypervisor | ~125 ms | ≈ 5 MiB | High-density multi-tenant workloads |
| Kata (CLH) | Cloud Hypervisor-based VM | ~200 ms | 10–20 MiB | Balanced performance and isolation |
Architectural Implementation
OpenSandbox selects the runtime once at server start-up via the [secure_runtime] section of ~/.sandbox.toml. The server validates runtime availability against the Docker daemon or Kubernetes RuntimeClass objects, then transparently injects the appropriate flag into every sandbox creation request.
Runtime Resolution Logic
The central mapping logic resides in server/src/services/runtime_resolver.py. The SecureRuntimeResolver class provides two primary methods:
get_docker_runtime()(lines 39‑53): Returns the OCI runtime name (e.g.,runscfor gVisor,kata-runtimefor Kata) thatDockerSandboxServiceinjects into the DockerHostConfigruntime field.get_k8s_runtime_class(): Returns theRuntimeClassname used byBatchSandboxProviderandAgentSandboxProviderto populate the pod spec’sruntimeClassNamefield.
Because the runtime is a server-level configuration, client code using the SDK or REST API requires no changes when switching from runc to a secure runtime.
Server-Level Configuration
Operators define the active runtime in ~/.sandbox.toml:
[secure_runtime]
type = "gvisor" # Options: "", "gvisor", "kata", "firecracker"
docker_runtime = "runsc" # For Docker mode
k8s_runtime_class = "kata-fc" # For Kubernetes mode
The type field determines which isolation mechanism the SecureRuntimeResolver maps to the underlying container engine.
Cold Start vs Warm Start Optimization
OpenSandbox mitigates the high cold-start cost of VM-based runtimes through pre-warmed pools. As documented in OSEP‑0004 lines 24‑30, warm-start latencies drop dramatically when sandboxes are recycled:
- Kata (QEMU): Cold start ~1000 ms → Warm start ~200 ms
- Kata (Firecracker): Cold start ~125 ms → Warm start ~50 ms (estimated from pool amortization)
This optimization makes Kata runtimes viable for latency-sensitive workloads when paired with OpenSandbox’s pool management.
Practical Configuration Examples
The following CLI snippets demonstrate how to configure each runtime. The API payload remains identical across all examples; only the server-side ~/.sandbox.toml configuration changes.
gVisor (Docker Mode)
Configure ~/.sandbox.toml:
[secure_runtime]
type = "gvisor"
docker_runtime = "runsc"
Create a sandbox:
curl -X POST http://localhost:8080/v1/sandboxes \
-H "Content-Type: application/json" \
-d '{
"image": {"uri":"python:3.11"},
"entrypoint":["python","-c","print(\"gVisor sandbox\")"]
}'
Verify the runtime:
docker inspect $(docker ps -q --filter "ancestor=python:3.11") | grep Runtime
# Expected: "Runtime": "runsc"
Kata with QEMU (Docker Mode)
Configure ~/.sandbox.toml:
[secure_runtime]
type = "kata"
docker_runtime = "kata-runtime"
Create a sandbox:
curl -X POST http://localhost:8080/v1/sandboxes \
-H "Content-Type: application/json" \
-d '{
"image": {"uri":"ubuntu:latest"},
"entrypoint":["/bin/bash","-c","uname -a"]
}'
Verify the guest kernel:
docker exec $(docker ps -q --filter "ancestor=ubuntu:latest") uname -a
# Output shows Kata guest kernel (e.g., 5.10.x-kata)
Kata with Firecracker (Kubernetes Mode)
Configure ~/.sandbox.toml:
[secure_runtime]
type = "firecracker"
k8s_runtime_class = "kata-fc"
After creating a sandbox via the API, verify the RuntimeClass:
kubectl get pod <sandbox-pod> -o jsonpath='{.spec.runtimeClassName}'
# Expected output: kata-fc
Default runc (No Secure Runtime)
Configure ~/.sandbox.toml:
[secure_runtime]
type = ""
Create a sandbox:
curl -X POST http://localhost:8080/v1/sandboxes \
-H "Content-Type: application/json" \
-d '{
"image": {"uri":"python:3.11"},
"entrypoint":["python","-c","print(\"runc sandbox\")"]
}'
Verify:
docker inspect $(docker ps -q --filter "ancestor=python:3.11") | grep Runtime
# Expected: "Runtime": "runc"
Selecting the Right Runtime for Your Workload
Choose your runtime based on the trust level of the executing code and your performance constraints:
-
gVisor: Select this for most production AI-code execution scenarios. It provides syscall-level isolation with only 10–50 ms startup penalty and moderate memory overhead (~50 MiB), making it suitable for general untrusted workloads where low latency is desired.
-
Kata (QEMU): Deploy this when absolute isolation is required for untrusted network code or kernel exploits. The full VM model ensures maximum compatibility but imposes ~500 ms cold-start latency and 20–50 MiB memory overhead.
-
Kata (Firecracker): Use this for high-density multi-tenant environments where memory efficiency is paramount. The micro-VM architecture achieves ~125 ms startup with only ~5 MiB overhead, comparable to
runcbut with hardware virtualization isolation. -
Kata (CLH): Choose Cloud Hypervisor when you need a middle ground between Firecracker’s speed and QEMU’s compatibility, offering ~200 ms startup with 10–20 MiB overhead.
Summary
- OpenSandbox supports five secure container runtimes—
runc, gVisor, and three Kata variants (QEMU, Firecracker, CLH)—each offering distinct trade-offs between isolation strength and resource overhead. - gVisor provides the lowest overhead among secure options (~10–50 ms startup, ~50 MiB memory) by intercepting syscalls in user space rather than using hardware virtualization.
- Kata with Firecracker achieves the highest density (~5 MiB memory, ~125 ms startup) through micro-VM technology, making it ideal for multi-tenant scenarios.
- Runtime selection is configured server-side in
~/.sandbox.tomland resolved transparently bySecureRuntimeResolverinserver/src/services/runtime_resolver.py, requiring no client code changes. - Warm-start pools mitigate cold-start penalties for VM-based runtimes, reducing Kata (QEMU) latency from ~1000 ms to ~200 ms.
Frequently Asked Questions
What is the fastest secure container runtime supported by OpenSandbox?
gVisor is the fastest secure runtime, adding only 10–50 ms of cold-start overhead compared to the ~0 ms of standard runc. While runc itself is faster, it provides only process-level isolation via cgroups. For workloads requiring actual syscall interception or kernel isolation, gVisor outperforms Kata variants by avoiding the full VM boot process.
How do I verify which runtime is actually executing my sandbox?
For Docker mode, inspect the container’s runtime field using docker inspect <container-id> | grep Runtime. When using gVisor, this returns "runsc"; for Kata, it returns "kata-runtime"; for default operation, it shows "runc". In Kubernetes mode, check the pod’s runtimeClassName field with kubectl get pod <name> -o jsonpath='{.spec.runtimeClassName}', which returns values like kata-fc for Firecracker.
Can I switch between secure runtimes without modifying my client application code?
Yes. OpenSandbox treats runtime selection as a server-level configuration defined in ~/.sandbox.toml under the [secure_runtime] section. The SecureRuntimeResolver class in server/src/services/runtime_resolver.py transparently injects the appropriate Docker --runtime flag or Kubernetes runtimeClassName during sandbox creation. Client SDKs and REST API calls remain identical regardless of whether the backend uses runc, gVisor, or Kata.
Why does Kata with QEMU consume significantly more memory than Kata with Firecracker?
Kata with QEMU provisions a full virtual machine including a complete QEMU system emulator and a heavyweight guest kernel, resulting in 20–50 MiB of memory overhead per sandbox. In contrast, Kata with Firecracker utilizes a micro-VM architecture that strips unnecessary devices and firmware, reducing the memory footprint to approximately 5 MiB—comparable to standard container overhead while maintaining hardware-level isolation. This makes Firecracker ideal for high-density multi-tenant deployments where QEMU’s resource consumption would be prohibitive.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →