CubeShim: Implementing the containerd Shim v2 Interface in Cube Sandbox

CubeShim is the Rust-based containerd shim component that implements the Shim v2 API, translating high-level container lifecycle commands into MicroVM operations for the Cube Sandbox runtime.

CubeShim serves as the critical bridge between containerd and Cube Sandbox's virtualization layer. Distributed as the binary containerd-shim-cube-rs, it exposes the standard Shim v2 gRPC/ttrpc interface while internally managing KVM MicroVM lifecycle through the CubeHypervisor. This architecture allows containerd to treat MicroVMs as standard containers without awareness of the underlying virtualization complexity.

Architectural Role of CubeShim

CubeShim occupies the middle layer in the Cube Sandbox architecture, sitting between the containerd control plane and the in-VM agent process.

Control Plane Integration

Containerd issues standard container lifecycle commands—Create, Start, Exec, Kill, and Delete—through the Shim v2 API. CubeShim receives these commands as the registered runtime handler, appearing to containerd as a standard container runtime while actually orchestrating MicroVMs.

Shim Layer Implementation

The CubeShim binary (containerd-shim-cube-rs) implements the actual Shim v2 gRPC/ttrpc interface defined in CubeShim/shim/src/service/mod.rs. The Service struct in this module receives containerd requests and translates them into actions on the KVM MicroVM. This implementation hides all VM-level details from containerd, presenting a unified container interface.

VM Communication Bridge

Inside the MicroVM, the cube-agent process executes the actual container workload. CubeShim communicates with this agent over ttrpc (via vsock), forwarding commands from containerd and returning execution results. This communication flow follows the path Cubelet → CubeShim → CubeHypervisor as documented in the architecture overview at docs/architecture/overview.md (lines 25‑27).

How CubeShim Implements the Shim v2 API

The implementation follows a strict lifecycle from process launch through request handling.

Process Launch and Runtime Registration

When containerd creates a new sandbox with the cube runtime, it spawns the binary containerd-shim-cube-rs. The entry point in CubeShim/shim/src/main.rs initializes the Tokio runtime and registers CubeShim as the runtime io.containerd.cube.rs:

// CubeShim/shim/src/main.rs
runtime.block_on(shim_run::<Service>("io.containerd.cube.rs", Some(c)));

Containerd configuration maps this runtime to the shim binary in /etc/containerd/config.toml:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.cube]
  runtime_type = "io.containerd.cube.v2"

Service Implementation

The core Shim v2 logic resides in CubeShim/shim/src/service/mod.rs and CubeShim/shim/src/service/srv.rs. The Service struct implements the required RPC methods, receiving containerd calls and forwarding them to the in-VM cube-agent:

// Conceptual implementation based on CubeShim/shim/src/service/srv.rs
impl Service {
    async fn create(&self, req: CreateTaskRequest) -> Result<CreateTaskResponse> {
        // Forward request to Cubelet to launch VM
        let vm_id = self.vm_manager.launch_vm(req).await?;
        // Wait for vsock handshake from cube-agent
        self.vsock.wait_for_agent(vm_id).await?;
        // Respond to containerd
        Ok(CreateTaskResponse { pid: vm_id.pid, .. })
    }
}

VM Lifecycle Orchestration

For a Create request, CubeShim coordinates with Cubelet to launch a MicroVM, passing the rootfs, memory file, and kernel parameters. After the VM boots and establishes the vsock channel, CubeShim reports the sandbox as running to containerd. Subsequent operations like Exec, Kill, and Delete are proxied to the cube-agent inside the MicroVM.

State Reporting and Event Emission

CubeShim emits lifecycle events and status changes using the Shim v2 event model, enabling containerd to monitor sandbox health and handle container exits. This includes forwarding exit codes from the in-VM process back to the containerd control plane.

Advanced Features

CubeShim provides additional capabilities beyond basic container lifecycle management.

Auto-Pause and Snapshot Support

The shim supports in-place snapshotting of the MicroVM through the snapshot management code in CubeShim/shim/src/snapshot/. This enables the auto-pause/resume mechanism used by Cubelet to freeze idle workloads and restore them on demand. The helper binary in CubeShim/cube-runtime/src/main.rs performs the actual snapshot/restore operations on the VM.

I/O Forwarding

Standard input, output, and error streams, along with Unix signals, are proxied between the host and the container process inside the MicroVM. This ensures that interactive containers and signal handling behave identically to native containerd runtimes.

Code Examples

Registering CubeShim with containerd

Configure containerd to use CubeShim by adding the runtime configuration:


# /etc/containerd/config.toml

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.cube]
  runtime_type = "io.containerd.cube.v2"

Containerd will invoke containerd-shim-cube-rs whenever a pod specifies runtime: cube, as documented in CubeShim/README.md (lines 79‑87).

Launching a Sandbox via containerd

ctr run --rm --runtime=cube \
    docker.io/library/ubuntu:latest my-sandbox /bin/bash

This triggers the entry point in main.rs, which initializes the Shim v2 service.

Communicating with the In-VM Agent

CubeShim uses the ttrpc crate (as declared in CubeShim/README.md) to communicate with cube-agent over vsock:

let client = ttrpc::client::Client::new("/run/vhost/vsock");
let agent = cube_agent::AgentClient::new(client);
let exec_resp = agent.exec(ExecRequest { 
    cmd: "/bin/ls".into(), 
    .. 
}).await?;

Summary

  • CubeShim implements the containerd Shim v2 interface as a Rust-based shim binary (containerd-shim-cube-rs).
  • The Service struct in CubeShim/shim/src/service/mod.rs handles the gRPC/ttrpc interface for container lifecycle operations.
  • CubeShim registers as the runtime io.containerd.cube.rs and translates containerd commands into MicroVM operations via the CubeHypervisor.
  • Communication with the in-VM workload occurs through ttrpc over vsock to the cube-agent.
  • The implementation supports auto-pause/resume through in-place VM snapshotting and provides full I/O forwarding between host and MicroVM.

Frequently Asked Questions

What is the binary name of CubeShim?

The compiled CubeShim binary is named containerd-shim-cube-rs. This executable serves as the entry point that containerd spawns when creating new sandboxes with the Cube runtime, as defined in CubeShim/shim/src/main.rs.

How does CubeShim communicate with containers inside the MicroVM?

CubeShim communicates with the in-VM cube-agent process using ttrpc (a lightweight RPC framework) over a vsock channel. This allows the shim to forward commands like Exec and Kill from containerd to the actual container process running inside the KVM MicroVM.

What runtime name does CubeShim register with containerd?

CubeShim registers itself as the runtime io.containerd.cube.rs in the main.rs entry point. Containerd administrators configure this runtime in config.toml to route container operations to the CubeShim binary.

How does CubeShim handle VM snapshots?

CubeShim implements auto-pause/resume functionality through in-place snapshotting managed by the code in CubeShim/shim/src/snapshot/. When Cubelet requests a pause, CubeShim coordinates with the CubeHypervisor to snapshot the MicroVM state, enabling fast restoration when the workload resumes.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →