Open-Source Wikis

/

containerd

/

Systems

/

Plugin runtime

containerd/containerd

Plugin runtime

The plugin runtime is the part of the daemon that owns which plugins exist, in what order they initialize, and how they discover each other. It's a thin layer on top of github.com/containerd/plugin, with containerd-specific wiring in cmd/containerd/server/server.go and a per-type registry in plugins/types.go.

Purpose

  • Register all built-in plugins via init() side effects (blank imports from cmd/containerd/builtins/).
  • Translate operator-supplied proxy plugin entries in config.toml into in-process plugin registrations whose InitFn dials a remote socket.
  • Compute a dependency-ordered initialization graph and run each plugin's InitFn.
  • Make the resulting plugin instances visible to other plugins through the plugin.Set passed via InitContext.

Plugin types

The complete set of plugin types is defined as plugin.Type constants in plugins/types.go. Each constant encodes the URI scheme that the daemon uses to address the plugin in config and introspection:

const (
    InternalPlugin       plugin.Type = "io.containerd.internal.v1"
    RuntimePlugin        plugin.Type = "io.containerd.runtime.v1"   // legacy
    RuntimePluginV2      plugin.Type = "io.containerd.runtime.v2"
    ServicePlugin        plugin.Type = "io.containerd.service.v1"
    GRPCPlugin           plugin.Type = "io.containerd.grpc.v1"
    TTRPCPlugin          plugin.Type = "io.containerd.ttrpc.v1"
    SnapshotPlugin       plugin.Type = "io.containerd.snapshotter.v1"
    DiffPlugin           plugin.Type = "io.containerd.differ.v1"
    MetadataPlugin       plugin.Type = "io.containerd.metadata.v1"
    ContentPlugin        plugin.Type = "io.containerd.content.v1"
    GCPlugin             plugin.Type = "io.containerd.gc.v1"
    EventPlugin          plugin.Type = "io.containerd.event.v1"
    LeasePlugin          plugin.Type = "io.containerd.lease.v1"
    StreamingPlugin      plugin.Type = "io.containerd.streaming.v1"
    TracingProcessorPlugin plugin.Type = "io.containerd.tracing.processor.v1"
    MetricsPlugin        plugin.Type = "io.containerd.metrics.v1"
    NRIApiPlugin         plugin.Type = "io.containerd.nri.v1"
    TransferPlugin       plugin.Type = "io.containerd.transfer.v1"
    SandboxStorePlugin   plugin.Type = "io.containerd.sandbox.store.v1"
    SandboxControllerPlugin plugin.Type = "io.containerd.sandbox.controller.v1"
    PodSandboxPlugin     plugin.Type = "io.containerd.podsandbox.controller.v1"
    ImageVerifierPlugin  plugin.Type = "io.containerd.image-verifier.v1"
    WarningPlugin        plugin.Type = "io.containerd.warning.v1"
    CRIServicePlugin     plugin.Type = "io.containerd.cri.v1"
    ShimPlugin           plugin.Type = "io.containerd.shim.v1"
    HTTPHandler          plugin.Type = "io.containerd.http.v1"
    ServerPlugin         plugin.Type = "io.containerd.server.v1"
    MountManagerPlugin   plugin.Type = "io.containerd.mount-manager.v1"
    MountHandlerPlugin   plugin.Type = "io.containerd.mount-handler.v1"
)

The same file defines RuntimeRuncV2, RuntimeRunhcsV1 (runtime IDs reachable from CRI config), the property keys PropertyRootDir, PropertyStateDir, PropertyGRPCAddress, PropertyTTRPCAddress and the SnapshotterRootDir exports key.

How plugins discover each other

Each plugin's Registration lists the types it needs:

&plugin.Registration{
    Type: plugins.GRPCPlugin,
    ID:   "containers",
    Requires: []plugin.Type{plugins.ServicePlugin},
    InitFn: func(ic *plugin.InitContext) (any, error) {
        plugins, err := ic.GetByType(plugins.ServicePlugin)
        ...
    },
}

registry.Graph returns the registrations in topological order, so by the time InitFn runs, all required types are already initialized and reachable via ic.Get(t) or ic.GetByType(t).

Proxy plugins

server.LoadPlugins (in cmd/containerd/server/server.go) iterates config.ProxyPlugins (from [proxy_plugins.*]) and synthesizes a plugin.Registration per entry. Currently supported types:

TOML type Mapped to Wrapper
snapshot SnapshotPlugin core/snapshots/proxy.NewSnapshotter
content ContentPlugin core/content/proxy.NewContentStore
sandbox SandboxControllerPlugin core/sandbox/proxy.NewSandboxController
diff DiffPlugin core/diff/proxy.NewDiffApplier

The wrapper opens a gRPC connection to the configured address (lazily, sharing a connection per address via proxyClients) and returns a Go-native interface implementation that forwards calls.

Initialization sequence

  1. apply(ctx, config) — handle deprecated config keys, apply OOM score, configure sub-reapers.
  2. For each Timeouts entry, timeout.Set the duration so plugins can read it.
  3. LoadPlugins builds the graph.
  4. For each StreamProcessors entry, register a binary differ via diff.RegisterProcessor.
  5. Walk the graph: build an InitContext, call Init, store the result.
  6. Track RequiredPlugins; at the end, error out if any required ID failed.
  7. recordConfigDeprecations writes any deprecated-key warnings into the warning service for later read by containerd deprecations (see plugins/services/warning).

Failure semantics

server.New distinguishes three plugin outcomes:

  • Skipped (plugin.IsSkipPlugin(err) — typically platform unsupported): logged at INFO and continues.
  • Failed required: aborts daemon startup.
  • Failed optional: logged at WARN, plugin is omitted, but if the plugin had already called RegisterReadiness then containerd treats this as fatal (the plugin promised to come up).

Key source files

File Purpose
plugins/types.go Plugin type and property constants
cmd/containerd/server/server.go New, LoadPlugins, Server.Start, Server.Stop, proxy plugin wiring
cmd/containerd/builtins/builtins.go Cross-platform blank imports
cmd/containerd/builtins/builtins_linux.go Linux-specific imports (devmapper, blockio, NRI, …)
vendor/github.com/containerd/plugin/registry/registry.go Topological sort over registrations

Entry points for modification

  • New plugin type: add a constant in plugins/types.go and a corresponding service interface (typically under core/<area>/).
  • New built-in: add a Go file under plugins/<type>/<name>/, register it in init(), and blank-import it from cmd/containerd/builtins.
  • New proxy plugin shape: extend the switch pp.Type in LoadPlugins.
  • Different startup ordering: prefer Requires over hand-coded sequences.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Plugin runtime – containerd wiki | Factory