containerd/containerd
containerd-shim-runc-v2
The default per-container shim. One process per container (or per pod sandbox), spawned by the daemon's runtime v2 plugin and surviving daemon restarts. The shim is the bridge between containerd and runc.
Purpose
A shim:
- Receives a
Create/Start/Exec/Kill/Deleterequest over ttrpc from the daemon. - Translates it into a runc invocation (
runc create,runc start, etc.). - Holds the container's stdio (pipes, fifos, or streamed over the daemon's streaming service).
- Reaps the container's process and forwards
TaskExit,TaskOOM, and friends back to the daemon.
Because the shim is a separate process, the daemon can be restarted (or crash) without killing running containers.
Directory layout
cmd/containerd-shim-runc-v2/
├── main.go # 30-line entry point: shim.Run("io.containerd.runc.v2", manager.NewShimManager)
├── main_tracing.go # build-tag-gated OTel hookup
├── manager/ # shim manager: responds to Start (spawn) / Stop (cleanup)
├── runc/ # runc invocation helpers (cgroup, mounts, console)
├── process/ # the per-process abstraction (init, exec'd, signals)
└── task/ # the ttrpc TaskService implementationHow it runs
sequenceDiagram
participant Daemon
participant Shim as containerd-shim-runc-v2
participant Runc
Daemon->>Shim: spawn binary with --address, --bundle, --id, ...
Shim->>Shim: register ttrpc TaskService on socket
Daemon->>Shim: Create (bundle, options)
Shim->>Runc: runc create
Daemon->>Shim: Start
Shim->>Runc: runc start
Shim-->>Daemon: TaskStart event
Note over Shim,Runc: shim watches container PID
Runc-->>Shim: process exits
Shim-->>Daemon: TaskExit event
Daemon->>Shim: Delete
Shim->>Shim: cleanup, exitThe shim binary is invoked twice:
- Start: the daemon execs the shim with mode
start. The shim daemonizes, spawns its own ttrpc server on a derived address, and prints that address back on stdout for the daemon to read. - Serve: the daemonized shim then registers the
TaskServicettrpc handlers undercmd/containerd-shim-runc-v2/task/and waits for requests.
Key abstractions
| Type | File | Purpose |
|---|---|---|
manager.Manager |
cmd/containerd-shim-runc-v2/manager/ |
Implements shim.Manager from pkg/shim; handles Start/Stop of the shim process itself |
task.Service |
cmd/containerd-shim-runc-v2/task/service.go |
TaskService ttrpc implementation (Create, Start, Exec, Kill, Delete, Wait) |
process.Init / process.Exec |
cmd/containerd-shim-runc-v2/process/ |
The state machine for the container's init process and exec'd processes |
runc.NewRunc |
cmd/containerd-shim-runc-v2/runc/ |
Wraps github.com/containerd/go-runc with sane defaults |
Why a separate binary
- Static, no gRPC: built with
CGO_ENABLED=0andBUILDTAGS=no_grpc(see Makefile) so it has no shared-library dependencies and no HTTP/2 stack. - Daemon restart safety: the shim outlives the daemon. After a daemon restart, the daemon re-attaches via the runtime v2 plugin's reconnect path.
- Per-container isolation: shim crashes are contained — only one container fails, and the daemon notices via the closed ttrpc connection.
Stdio
Three modes exist:
- Fifo: stdio is plumbed through named pipes under
--state/.../<id>/. Default forctr run. - TTY: a pseudo-terminal is allocated; stdin/stdout/stderr go through it.
- Streaming: stdio is multiplexed through the daemon's streaming service. The CRI plugin uses this for exec/attach. Implementation:
internal/cri/streaming/andcore/streaming.
Failure paths
- If the shim fails to spawn, the daemon receives the error from the
startinvocation and surfaces it as a Task creation error. - If the shim is killed mid-flight, the daemon's runtime v2 manager (
core/runtime/v2/manager.go) detects the broken ttrpc connection and emitsTaskExitwithExitCode: 137. - If runc fails, the shim translates the error into the appropriate errdefs sentinel (
ErrNotFound,ErrFailedPrecondition, …).
Entry points for modification
- New runc options:
cmd/containerd-shim-runc-v2/runc/. - Different stdio strategy:
cmd/containerd-shim-runc-v2/process/io.goand the streaming integration ininternal/cri/. - Different process state machine: the
process.Init/process.Exectypes are designed to be replaced for non-runc runtimes — seecore/runtime/v2/runc/v2/for an alternative example shim built into containerd's source tree.
For the daemon-side counterpart, see runtime v2 system.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.