containerd/containerd
Garbage collection
A reference-graph garbage collector that runs over the metadata store, marks reachable objects, and deletes the rest. Implemented in plugins/gc/, with the reference walker in core/metadata/gc.go and the leveled scheduler interfaces in core/gc/.
Purpose
- Reclaim unused content blobs and unused snapshots (the only things big enough to matter).
- Honor leases so in-progress operations aren't pruned out from under themselves.
- Run periodically and on-demand when an
ImageDelete/Removereturns.
Reference graph
Each object in the metadata store has a set of references to other objects:
- An image references its root descriptor digest, which transitively references manifests, configs, and layers in the content store.
- A container references its image digest and its working snapshot.
- A lease references arbitrary objects (digests and snapshots) — leases are anti-GC handles.
- A sandbox references its sandbox image.
- A snapshot references its parent snapshot.
core/metadata/gc.go's references function walks the bbolt buckets and emits gc.Node records for each reference. The GC scheduler builds a graph and marks reachable nodes.
Plugin model
plugins/gc/ registers a GCPlugin that exposes a Schedule interface. The metadata store calls Schedule after operations that might create garbage; the scheduler coalesces requests so a flurry of deletes triggers at most one GC pass.
The scheduler's runtime parameters (pause_threshold, deletion_threshold, mutation_threshold, schedule_delay, start_delay) are configurable in [plugins."io.containerd.gc.v1.scheduler"].
Lease handling
A lease is created by client.LeasesService().Create(ctx, lease.WithExpiration(...)) and resources are added with lease.WithResource. While a lease references an object, GC won't delete it.
The transfer pipeline creates a lease at the start of a pull and releases it once the image is committed; this way a long pull doesn't have its blobs pruned because no Image record exists yet.
Run sequence
graph TD
Trigger[delete container / image / lease]
Schedule[scheduler.Schedule]
Wait[debounce / coalesce]
Mark[Walk metadata, mark reachable]
Sweep[Delete unreached blobs and snapshots]
Done
Trigger --> Schedule
Schedule --> Wait
Wait --> Mark
Mark --> Sweep
Sweep --> DoneThe mark phase reads the bbolt metadata using a View transaction (a consistent snapshot) and iterates through every namespace. The sweep phase invokes the content store's Delete and the snapshotter's Remove for each unreachable id.
Failure modes and gotchas
- Forgot to add a reference: any time you add a new object type that holds digests or snapshot keys, you must extend
core/metadata/gc.go'sreferencesfunction. Otherwise GC will delete the very thing you just stored. - No lease around a long pull: blobs land in the content store, GC runs, blobs vanish. Always lease.
- Cross-namespace references: there are none. Each namespace has its own GC scope.
Manual triggers
ctr content gc(and the underlying gRPCContent.GC) requests a GC pass.- The scheduler runs a periodic GC at startup-delay then on-demand.
Entry points for modification
- New object type with references: extend
core/metadata/gc.go'sreferencesfunction. Add tests incore/metadata/gc_test.go. - Tune scheduler defaults: edit
plugins/gc/scheduler.go. - Visualize the reference graph: the metadata store has a
Walk(ctx, fn)per type; collect into a graphviz file for debugging.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.