Skip to content
Published on

containerd Architecture Internals

Authors

containerd Architecture Internals

containerd is the industry-standard container runtime, originally extracted from Docker and developed as an independent project. It implements the Kubernetes CRI (Container Runtime Interface) and manages the complete container lifecycle.


1. containerd Overview

1.1 Position and Role

containerd sits in the middle layer of the container stack:

Kubernetes (kubelet)
    |
    v (CRI gRPC)
containerd
    |
    v (OCI runtime)
runc / kata / gVisor
    |
    v
Linux kernel (namespaces, cgroups)

Key responsibilities: image management, container lifecycle management, snapshot management, namespace isolation, and task (process) management.

1.2 Core Design Principles

  • Simplicity: Do one thing well
  • Plugin-based: All functionality implemented as plugins
  • OCI compliant: Follows OCI image and runtime specs
  • gRPC API: All interactions through gRPC

2. gRPC API Structure

2.1 Key Services

containerd provides these gRPC services: Containers, Content, Images, Namespaces, Snapshots, Tasks, Events, and Leases.

2.2 Namespaces

containerd namespaces are different from Kubernetes namespaces -- they isolate resources within containerd internally:

  • k8s.io: Used by Kubernetes (CRI)
  • moby: Used by Docker
  • default: Default namespace

3. Plugin System

3.1 Plugin Types

All containerd functionality is implemented as plugins: Service, Snapshotter, Runtime, GC, Content Store, Metadata, and Differ.

3.2 Dependency Resolution

At startup, containerd analyzes all plugin dependencies and initializes them in the correct order via topological sort.

3.3 Plugin Configuration

version = 2

[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "registry.k8s.io/pause:3.9"

[plugins."io.containerd.grpc.v1.cri".containerd]
  default_runtime_name = "runc"

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

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true

4. CRI Implementation

4.1 CRI Services

containerd implements CRI as a built-in plugin:

  • RuntimeService: Pod/container lifecycle (RunPodSandbox, CreateContainer, StartContainer, etc.)
  • ImageService: Image management (PullImage, ListImages, etc.)

4.2 CRI Request Flow

  1. kubelet calls RunPodSandbox via CRI
  2. containerd creates pause container (sets up network namespace)
  3. CNI plugin called for network configuration
  4. kubelet calls CreateContainer + StartContainer
  5. containerd runs container through shim process

5. Shim v2 Architecture

5.1 Shim Role

The Shim is an intermediate process between containerd and the actual container runtime (runc):

containerd --> shim (containerd-shim-runc-v2) --> runc --> container process

Responsibilities: keeping containers alive across containerd restarts, managing stdin/stdout/stderr, collecting exit codes, reporting OOM events.

5.2 Shim v2 Protocol

Shim v2 uses ttrpc (tiny-ttrpc), a lightweight alternative to gRPC with protobuf serialization, Unix domain socket communication, lower memory usage, and no HTTP/2 overhead.

5.3 Various Shim Implementations

ShimRuntimeDescription
containerd-shim-runc-v2runcDefault OCI runtime
containerd-shim-kata-v2KataLightweight VM-based
containerd-shim-runsc-v1gVisorUser-space kernel
containerd-shim-wasmWasmWebAssembly runtime

6. Metadata Store

containerd uses BoltDB for metadata storage including container definitions, image metadata, snapshot metadata, lease information, and namespace information.

/var/lib/containerd/
  io.containerd.metadata.v1.bolt/meta.db
  io.containerd.content.v1.content/blobs/sha256/
  io.containerd.snapshotter.v1.overlayfs/snapshots/

7. Summary

containerd's plugin-based architecture provides high extensibility and flexibility. The Shim v2 process isolation model keeps containers stable across containerd restarts, and efficient communication via ttrpc minimizes overhead. The next post covers containerd's image management and snapshot system in detail.