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
Servicestruct inCubeShim/shim/src/service/mod.rshandles the gRPC/ttrpc interface for container lifecycle operations. - CubeShim registers as the runtime
io.containerd.cube.rsand 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →