Both CubeShim (containerd-shim-cube-rs) and
containerd-shim-runc-v2 are containerd Shim v2 implementations. They
behave identically from containerd’s point of view. They diverge in
what sits behind the shim.
runc path
containerd → containerd-shim-runc-v2 → runc → runc exec → container process
(fork/namespaces/cgroups)
One shim per container (or per pod). The shim supervises a runc binary,
which fork(2)s into a namespaced, cgroup-scoped process. The shim stays
resident after runc exits to manage stdio, signals, and status. Everything
runs in the host kernel.
CubeShim path
containerd → containerd-shim-cube-rs → Cubelet (gRPC) → cube-hypervisor (HTTP)
└→ cube-agent (ttrpc/vsock) ── inside VM ──►
rustjail → container
One shim per sandbox. The shim doesn’t fork the container; it asks Cubelet for a VM, waits for that VM to be ready, then talks to the in-VM agent over vsock. The agent runs rustjail inside the VM to actually launch the container process.
Where the models diverge
Process supervision
- runc shim: classic reaper pattern — shim is the subreaper; container
is its child.
wait(2)on PID fires when the container exits. - CubeShim: the container process is not the shim’s child. Exit detection comes via ttrpc notifications from cube-agent. If vsock dies, the shim has to distinguish “container exited” from “transport failure.”
Stdio
- runc shim: FIFOs on the host filesystem.
- CubeShim: FIFOs on the host filesystem, plus a vsock channel that cube-agent uses to shuttle bytes between the container’s real stdio and the FIFOs.
Signals
- runc shim:
kill(2)directly. - CubeShim: ttrpc
SignalProcessrequest → cube-agent forwards to rustjail → rustjail delivers viakill(2)inside the VM.
Teardown
- runc shim:
rm -rfcgroup, reap processes, exit. - CubeShim: ask cube-agent to stop containers, ask Cubelet to stop the VM (either destroy or return to pool), reap local resources, exit.
Snapshot path
- runc shim: no such concept. Snapshot/restore of a container process is CRIU territory, never part of the shim itself.
- CubeShim:
cube-runtime(sibling binary in the same workspace) is the CLI that Cubelet invokes for snapshot/restore operations on the VM. See/appendix/snapshot-cloning.
FreeBSD implications
A FreeBSD port would replace the runc path wholesale — runc is
Linux-OCI-specific — but could keep the Shim v2 structure. The interesting
questions:
- FreeBSD containerd. Exists, maintained. Shim v2 API is Go and portable.
- containerd-shim-rs on FreeBSD. Less certain. The framework is Rust
and uses
nix(3)for Linux-ish primitives; portability work is bounded but real. - Jail-equivalent “runc”.
runjexists as a proof-of-concept (OCI-compliant jail launcher). If CubeShim’s in-VM architecture is abandoned in favor of jails, you want something like runj in place of rustjail — and now you’re shipping a fundamentally different security model.
If the FreeBSD port keeps the microVM model, cube-agent stays inside the
guest and rustjail stays OCI/Linux — because the guest is Linux. The
host-side CubeShim then needs to talk to bhyve instead of cube-hypervisor,
which is a swap of the CubeShim/shim/src/hypervisor/ client module, not
a rewrite of the shim.