Cheatsheet - gVisor
runsc
runsc (run Sandboxed Container) is the OCI-compliant executable used to interact with the gVisor sandbox. It functions similarly to runc but wraps the process in a secure user-space kernel (the Sentry).
Installation & Environment
| Subcommand | Description | Example / Usage |
|---|---|---|
install |
Configures Docker to use runsc. Updates /etc/docker/daemon.json. |
sudo runsc install |
version |
Shows the version, commit, and build info. | runsc version |
flags |
Lists all global flags available to the runsc binary. |
runsc flags |
capabilities |
Lists the Linux capabilities supported by the sandbox. | runsc capabilities |
Lifecycle Management
These commands follow the OCI runtime specification for managing container states.
| Subcommand | Description | Command Example |
|---|---|---|
run |
Creates and starts a container (bundle must exist). | runsc run <container-id> |
create |
Creates a container but does not start it (waiting for start). |
runsc create <id> |
start |
Starts a container previously created by create. |
runsc start <id> |
kill |
Sends a signal (default SIGTERM) to the container. | runsc kill <id> SIGKILL |
delete |
Deletes any resources held by the container (must be stopped). | runsc delete <id> |
pause |
Suspends all processes inside the container. | runsc pause <id> |
resume |
Resumes processes inside a paused container. | runsc resume <id> |
Execution & Inspection
Use these to see what is happening inside the sandbox.
| Subcommand | Description | Command Example |
|---|---|---|
list |
Lists containers started by runsc and their status. |
runsc list |
ps |
Lists processes running inside a specific container. | runsc ps <container-id> |
exec |
Executes a new process inside an existing container. | runsc exec <id> /bin/bash |
state |
Outputs the state (JSON) of a container. | runsc state <id> |
events |
Displays container stats (CPU, Memory) in a stream. | runsc events <id> |
Debugging & Advanced Diagnostics
These are critical for troubleshooting syscall failures or performance bottlenecks.
| Subcommand | Description | Notes |
|---|---|---|
debug |
Shows the Sentry's internal state (for developer use). | Requires --debug flag. |
trace |
Manages "session" traces (e.g., syscall tracing). | runsc trace metadata |
boot |
Manual internal command to start a sandbox. | Used by runsc internally. |
do |
Fast Testing: Runs a process in a sandbox without a full OCI bundle. | runsc do /bin/ls |
runsc trace
The runsc trace command suite is used to interact with gVisor's internal Trace Sessions. Unlike standard strace, which monitors syscalls from the host side, runsc trace allows you to hook into the Sentry (the gVisor kernel) to capture detailed execution data with lower overhead and higher detail.
runsc trace Subcommands:
| Subcommand | Description | Example |
|---|---|---|
list |
Lists all available trace points (events) gVisor can track. | runsc trace list |
metadata |
Shows schema information for trace points (fields, types). | runsc trace metadata |
create |
Starts a new tracing session based on a configuration file. | runsc trace create --config=cfg.json <session-id> |
delete |
Stops and removes an active tracing session. | runsc trace delete <session-id> |
procfs |
(Internal/Diagnostic) Displays a virtual directory tree of tracing sessions. | runsc trace procfs |
Examples
# To find the root folder:
$ ps aux | grep runsc
# look for --root flag
# For Docker created containers:
$ sudo runsc --root /var/run/docker/runtime-runc/moby trace procfs CONTAINER_ID
runsc ps vs runsc trace procfs
While both commands provide a way to "look inside" a running gVisor sandbox, they operate at completely different layers of the system.
Quick Comparison Table:
| Feature | runsc ps |
runsc trace procfs |
|---|---|---|
| Primary Goal | List Application Processes. | Inspect Tracing Infrastructure. |
| Perspective | What is the container doing? | What is the gVisor kernel monitoring? |
| Output Type | Tabular (PID, Command, etc.). | Virtual Directory Tree (Files/Paths). |
| Standard | Part of OCI Runtime Spec. | gVisor-specific diagnostic tool. |
| Analogy | Looking at a "Task Manager" for the app. | Looking at the "Settings" of a security camera. |
Essential Global Flags
These flags must be placed before the subcommand (e.g., runsc --debug run ...).
--debug: Enables debug logging.--debug-log=<path>: Directs logs to a file or directory. gVisor logs are very verbose and categorized by component (Sentry, Gofer).--platform=<name>: Selects the syscall interception method.systrap(Default): Modern, signal-based interception.kvm: Hardware virtualization (requires/dev/kvm).ptrace: Universal but slow.
--network=<type>:sandbox(Default): Uses gVisor’s internal Go network stack (Isolated).host: Uses the host network stack (Faster, but less secure).
--rootless: Allows running containers without root privileges.--profile-cpu=<file>: Captures a Go CPU profile for performance analysis.
The "runsc do" Shortcut
One of the most useful commands for quick testing without needing Docker or a config.json bundle:
# Run a shell inside a gVisor sandbox immediately
runsc do /bin/sh
# Check the kernel version inside the sandbox
runsc do uname -a
Troubleshooting Common Errors
- "Read-only file system": gVisor is strict about mounts. Ensure your mount points in
config.jsonare correct. - "Function not implemented": The application called a syscall gVisor doesn't support yet.
- Fix: Run with
--debug --debug-log=/tmp/logs/and search for "unsupported syscall".
- Fix: Run with
- Performance Issues:
- Fix: Try switching to the KVM platform:
runsc --platform=kvm run <id>. - Fix: If using heavy networking, test with
--network=hostto see if the Go netstack is the bottleneck.
- Fix: Try switching to the KVM platform:
Installation (Quick Start)
# Download the binary
curl -LO https://storage.googleapis.com/gvisor/releases/release/latest/x86_64/runsc
curl -LO https://storage.googleapis.com/gvisor/releases/release/latest/x86_64/runsc.sha256
# Verify and install
sha256sum -c runsc.sha256
chmod +x runsc
sudo mv runsc /usr/local/bin/
Docker Configuration
To use gVisor with Docker, you must register runsc as a runtime.
Update /etc/docker/daemon.json:
{
"runtimes": {
"runsc": {
"path": "/usr/local/bin/runsc"
}
}
}
Restart Docker:
sudo systemctl restart docker
Running a container with gVisor:
docker run --runtime=runsc -it ubuntu /bin/bash
containerd Configuration
To apply global configuration changes to all gVisor sandboxes managed by containerd, you need to modify the containerd configuration file (typically located at /etc/containerd/config.toml).
There are two primary ways to do this: by passing flags directly in the containerd config, or by pointing gVisor to a dedicated global configuration file.
Method 1: Direct Configuration in config.toml (Recommended)
This method involves adding runtime_args to the specific runtime handler used for gVisor. Open the config file: /etc/containerd/config.toml
Locate the runsc runtime section. If it doesn't exist, you will need to create it. Add your desired flags (like changing the platform to KVM) inside the runtime_args array.
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
runtime_type = "io.containerd.runsc.v1"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc.options]
# These args apply to every gVisor container
runtime_args = [
"--platform=kvm",
"--network=sandbox",
"--debug",
"--debug-log=/var/log/runsc/"
]
Restart containerd:
sudo systemctl restart containerd
Method 2: Using an External gVisor Config File
If you want to keep your gVisor settings separate from your containerd settings, you can create a dedicated gVisor JSON configuration file and tell containerd to use it.
-
Create the gVisor config file (e.g.,
/etc/gvisor/config.json):{ "platform": "kvm", "network": "sandbox", "debug": true, "debug-log": "/var/log/runsc/" } -
Point containerd to this file in
/etc/containerd/config.toml:[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc] runtime_type = "io.containerd.runsc.v1" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc.options] runtime_args = ["--config=/etc/gvisor/config.json"] -
Restart containerd:
sudo systemctl restart containerd
Common Configuration Scenarios
Here are the most common settings people change globally:
1. Enable KVM (Hardware Acceleration)
If your host supports virtualization, KVM is significantly faster than the default systrap.
- Flag:
--platform=kvm - Note: Ensure
/dev/kvmis accessible.
2. Change Networking Stack
By default, gVisor uses a Go-based userspace network stack (sandbox).
- For Isolation:
--network=sandbox(Default) - For Performance:
--network=host(Warning: Reduces security as the sandbox shares the host network namespace).
3. Global Debugging
If you are troubleshooting why containers won't start:
- Flags:
--debug,--debug-log=/var/log/runsc/ - Note: Ensure the directory exists and is writable by the user running containerd.
How to verify the changes applied?
After restarting containerd, start a new gVisor container and check the runsc logs or the container's environment.
If you enabled KVM, you can verify it by looking at the logs:
grep "Platform: KVM" /var/log/runsc/runsc.log.*
Or check the kernel name from inside the container:
kubectl run -it --rm --restart=Never --overrides='{"spec":{"runtimeClassName":"gvisor"}}' test-pod --image=alpine -- uname -a
Kubernetes Integration (RuntimeClass)
- Create the RuntimeClass:
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: gvisor
handler: runsc
- Use it in a Pod Spec:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
runtimeClassName: gvisor
containers:
- name: nginx
image: nginx
Selection of Platforms (--platform)
The platform determines how gVisor intercepts syscalls.
| Platform | Best For | Description |
|---|---|---|
| KVM | Performance | Uses hardware virtualization (VT-x/AMD-V). Fast, but requires nested virtualization if running in a VM. |
| ptrace | Compatibility | Works everywhere (even inside restricted VMs). Slower due to context switching. |
| systrap | Modern Linux | Uses a specialized signal-based approach. Often the default for newer versions. |
Changing the platform in Docker:
Modify /etc/docker/daemon.json:
"runsc": {
"path": "/usr/local/bin/runsc",
"runtimeArgs": ["--platform=kvm"]
}
Verification: Is it working?
To check if a container is actually running inside gVisor, check the kernel name from within the container:
docker run --runtime=runsc --rm alpine uname -a
# Output should mention "gVisor" instead of "Linux version..."
Check the dmesg output (it will be simulated):
docker run --runtime=runsc --rm alpine dmesg
Troubleshooting & Performance
- Networking: gVisor has its own network stack (Netstack). If performance is an issue, you can use
--network=host, but it reduces isolation. - Filesystem: Use
--fsdiscard-mountsfor better performance on ephemeral mounts. - Unsupported Syscalls: If an app fails, check
runsclogs. gVisor implements ~300+ Linux syscalls, but some niche ones (or specific/proc//syspaths) may be missing. - Debugging Logs:
# Enable debug logging in daemon.json "runtimeArgs": ["--debug", "--debug-log=/tmp/runsc.log"]