Skip to content

Instantly share code, notes, and snippets.

@dims
Last active February 11, 2026 18:19
Show Gist options
  • Select an option

  • Save dims/be341508bb077b30cfb38b6e45a7eac9 to your computer and use it in GitHub Desktop.

Select an option

Save dims/be341508bb077b30cfb38b6e45a7eac9 to your computer and use it in GitHub Desktop.
Containerd Dependency Analysis (v2.2.1) -- depstat

Containerd Dependency Analysis Report

Project: containerd (main branch, commit 35871e04a) Modules: 2 Go modules (github.com/containerd/containerd/v2 + github.com/containerd/containerd/api) Analysis date: February 11, 2026 Tool: depstat (built from source)


1. Executive Summary

Containerd is a CNCF graduated container runtime with a 2-module repository (main + api). This analysis uses depstat to profile dependency scope, depth, cycles, archived dependencies, and version-to-version change trends.

Key Findings

Metric Value
Direct dependencies 152
Transitive dependencies 270
Total dependencies 293
Max dependency depth 11
Non-test dependencies 243
Test-only dependencies 50
Dependency cycles 18 (11 two-node)
Archived dependencies 14

Headlines

  • Broad dependency surface. 293 total dependencies with 152 direct deps reflects containerd's role as an integration point for container ecosystem components (OCI, CRI, CNI, Windows HCS, encryption, NRI, etc.).
  • Moderate cycle count. 18 cycles with 3 containerd-internal (hcsshim, imgcrypt, zfs mutually depend on containerd/v2), plus external OTel, protobuf, and gRPC cycles.
  • Dependency diet from v2.1.0 to v2.2.1. Net reduction of 23 deps (37 removed, 14 added), notably dropping the entire etcd client stack and legacy gRPC middleware.
  • 14 archived dependenciespkg/errors, json-iterator/go, opencensus, golang/mock, and Windows-specific StackExchange/wmi are priorities for replacement.

2. Module Architecture

Containerd uses a 2-module repository (no go.work):

github.com/containerd/containerd/
├── go.mod     -> github.com/containerd/containerd/v2
└── api/go.mod -> github.com/containerd/containerd/api

The main module containerd/v2 has 153 outgoing edges — the largest fan-out node in the graph. It directly depends on a wide array of containerd sub-projects, OCI components, Kubernetes CRI/kubelet APIs, and platform-specific backends (HCS for Windows, ZFS, etc.).

The api module is a lightweight protobuf/gRPC definitions module depended on by the main module.


3. Dependency Statistics

Metric Value
Direct Dependencies 152
Transitive Dependencies 270
Total (deduplicated) 293
Max Dependency Depth 11

Test vs Non-Test Split

Category Count
Non-test 243
Test-only 50
Combined 293

4. Graph Characteristics

Top In-Degree Dependencies (most depended upon)

Rank Module In-Degree Out-Degree
1 go (stdlib) 70 0
2 golang.org/x/sys 65 1
3 github.com/davecgh/go-spew 37 0
4 github.com/stretchr/testify 37 4
5 google.golang.org/protobuf 37 3
6 gopkg.in/yaml.v3 37 1
7 github.com/pmezard/go-difflib 33 0
8 golang.org/x/net 31 5
9 github.com/google/go-cmp 29 1
10 golang.org/x/text 26 4

Top Out-Degree Modules (most fan-out)

Rank Module Out-Degree In-Degree
1 github.com/containerd/containerd/v2 153 3
2 github.com/Microsoft/hcsshim 114 4
3 github.com/containerd/imgcrypt/v2 58 1
4 k8s.io/client-go 54 1
5 github.com/containernetworking/plugins 48 1
6 github.com/intel/goresctrl 46 1
7 k8s.io/apimachinery 43 4
8 github.com/containerd/zfs/v2 35 1
9 google.golang.org/grpc 35 22
10 github.com/containerd/nri 32 1

Figure 1. Full dependency graph:

Full dependency graph


5. Cycles

Metric Value
Total cycles 18
2-node cycles 11

Two-Node Cycles

Cycle Nature
Microsoft/hcsshimcontainerd/containerd/v2 Internal (Windows backend)
containerd/containerd/v2containerd/imgcrypt/v2 Internal (encryption plugin)
containerd/containerd/v2containerd/zfs/v2 Internal (ZFS snapshotter)
golang/protobufgoogle.golang.org/protobuf External (protobuf)
prometheus/client_golangprometheus/common External (Prometheus)
stretchr/objxstretchr/testify External (testing)
opentelemetry.io/auto/sdkopentelemetry.io/otel External (OTel)
opentelemetry.io/otelopentelemetry.io/otel/metric External (OTel)
opentelemetry.io/otelopentelemetry.io/otel/trace External (OTel)
golang.org/x/cryptogolang.org/x/net External (Go stdlib)
genproto/googleapis/apigoogle.golang.org/grpc External (gRPC)

Top Cycle Participants

Module Cycle Count
go.opentelemetry.io/otel 7
github.com/containerd/containerd/v2 6
github.com/Microsoft/hcsshim 4
go.opentelemetry.io/auto/sdk 4
go.opentelemetry.io/otel/metric 4

3 cycles are containerd-internal (hcsshim, imgcrypt, zfs all mutually depend on containerd/v2). The remainder are external ecosystem cycles.


6. Archived Dependencies

14 archived dependencies detected:

Module Version Repository
StackExchange/wmi v0.0.0-2019... GitHub
census-instrumentation/opencensus-proto v0.2.1 GitHub
client9/misspell v0.3.4 GitHub
golang/mock v1.1.1 GitHub
google/btree v1.1.3 GitHub
google/gofuzz v1.2.0 GitHub
gregjones/httpcache v0.0.0-2019... GitHub
json-iterator/go v1.1.12 GitHub
mitchellh/go-homedir v1.1.0 GitHub
mndrix/tap-go v0.0.0-2017... GitHub
pkg/errors v0.9.1 GitHub
rcrowley/go-metrics v0.0.0-2020... GitHub
go.opencensus.io v0.24.0 GitHub
golang/lint v0.0.0-2019... GitHub

Priority replacements:

  • pkg/errors → stdlib errors/fmt.Errorf with %w
  • json-iterator/goencoding/json or go-json
  • opencensus → already being superseded by OTel
  • golang/mockgo.uber.org/mock
  • StackExchange/wmigithub.com/yusufpapurcu/wmi (maintained fork, used by hcsshim)
  • google/gofuzzsigs.k8s.io/randfill (already added in v2.2.1)

7. Release Diff: v2.1.0 → v2.2.1

Summary

Metric v2.1.0 v2.2.1 Delta
Direct Deps 144 152 +8
Transitive Deps 290 264 -26
Total Deps 309 286 -23
Max Depth 11 11 ±0

Module graph: +14 added, -37 removed, ~82 version changes

Major Removals (37 deps removed)

  • Etcd client stack removedgo.etcd.io/etcd/api/v3, client/pkg/v3, client/v2, client/v3, pkg/v3, raft/v3, server/v3 (7 etcd modules)
  • Legacy gRPC ecosystemgrpc-ecosystem/go-grpc-middleware v1, go-grpc-prometheus, grpc-gateway v1
  • Auth/OIDC stackcoreos/go-oidc, pquerna/cachecontrol
  • Misccontainerd/containerd v1 (self-reference), syndtr/gocapability (replaced by moby/sys/capability)

Major Additions (14 deps added)

  • Wasm runtimetetratelabs/wazero (WebAssembly support)
  • Plugin systemknqyf263/go-plugin (Go plugin framework)
  • Securitycyphar/filepath-securejoin, google/certtostore
  • K8s modernizationsigs.k8s.io/randfill, sigs.k8s.io/structured-merge-diff/v6
  • Platformmoby/sys/capability (replaces syndtr/gocapability)

Figure 2. Diff graph (v2.1.0 → v2.2.1):

Diff v2.1.0 to v2.2.1


8. Why-Traces (Key Dependencies)

gRPC (google.golang.org/grpc)

Directly depended on by 23 modules (2 containerd + 21 external).

Core RPC transport for containerd's plugin architecture (ttrpc/gRPC), CRI API, and image services. Both containerd/v2 and containerd/api directly depend on gRPC.

Figure 3. Why-trace for gRPC:

Why gRPC

OpenTelemetry (go.opentelemetry.io/otel)

Directly depended on by 16 modules (1 containerd + 15 external).

Distributed tracing for containerd operations. Only containerd/v2 directly depends on OTel; it also enters via hcsshim, imgcrypt, and gRPC instrumentation.

Figure 4. OTel dependency subgraph:

Why OTel

bbolt (go.etcd.io/bbolt)

Directly depended on by 4 modules: containerd/v2, Microsoft/hcsshim, containerd/zfs/v2, k8s.io/apiserver.

Used for metadata storage. Enters via direct dependency and also through hcsshim and the k8s apiserver stack.

Figure 5. Why-trace for bbolt:

Why bbolt

Prometheus (github.com/prometheus/client_golang)

Directly depended on by 8 modules (1 containerd + 7 external).

Metrics instrumentation. Containerd/v2 directly depends on it; also enters via hcsshim, docker/go-metrics, intel/goresctrl, k8s apiserver/kubelet.

Figure 6. Why-trace for Prometheus client:

Why Prometheus

errdefs (github.com/containerd/errdefs)

Directly depended on by 6 modules (1 containerd + 5 external).

Containerd's error classification library, used by containerd/v2, hcsshim, imgcrypt, zfs, containernetworking/plugins, and errdefs/pkg.

Figure 7. Why-trace for errdefs:

Why errdefs

OCI runtime-spec (github.com/opencontainers/runtime-spec)

Directly depended on by 10 modules (1 containerd + 9 external).

Core OCI runtime specification. Enters through cgroups, go-runc, hcsshim, nri, imgcrypt, intel/goresctrl, and more.

Figure 8. Why-trace for runtime-spec:

Why runtime-spec


9. Recommendations

  1. Replace archived dependencies — prioritize pkg/errors, json-iterator/go, opencensus, and golang/mock (see Section 6).
  2. Address internal cycles — the 3 containerd-internal cycles (hcsshim ↔ containerd, imgcrypt ↔ containerd, zfs ↔ containerd) increase build complexity. Consider extracting shared interfaces to break these cycles.
  3. Track hcsshim fan-outMicrosoft/hcsshim has 114 outgoing edges and is the second-largest dependency node. It brings in significant transitive weight.
  4. Continue etcd removal — v2.2.1 removed the etcd client stack. Verify no residual etcd dependencies remain in transitive paths.
  5. Monitor test-only deps — 50 test-only dependencies is notable; periodic pruning can reduce CI complexity.

10. Reproducibility

All commands run with -d /path/to/containerd:

# Stats
depstat stats --json -d /path/to/containerd
depstat stats --split-test-only --json -d /path/to/containerd

# Graph
depstat graph --svg -d /path/to/containerd > containerd-full-graph.svg
depstat graph --top both -d /path/to/containerd

# Cycles
depstat cycles --summary --json -d /path/to/containerd

# Archived
GITHUB_TOKEN=$(gh auth token) depstat archived --json -d /path/to/containerd

# Diff
depstat diff v2.1.0 v2.2.1 --verbose -d /path/to/containerd
depstat diff v2.1.0 v2.2.1 --svg -d /path/to/containerd > containerd-diff-v21-v221.svg

# Why-traces
depstat why google.golang.org/grpc --svg -d /path/to/containerd > containerd-why-grpc.svg
depstat graph -p go.opentelemetry.io/otel --svg -d /path/to/containerd > containerd-why-otel.svg
depstat why go.etcd.io/bbolt --svg -d /path/to/containerd > containerd-why-bbolt.svg
depstat why github.com/prometheus/client_golang --svg --max-paths 50 -d /path/to/containerd > containerd-why-client_golang.svg
depstat why github.com/containerd/errdefs --svg -d /path/to/containerd > containerd-why-errdefs.svg
depstat why github.com/opencontainers/runtime-spec --svg -d /path/to/containerd > containerd-why-runtime-spec.svg
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
View raw

(Sorry about that, but we can’t show files that are this big right now.)

Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment