ocicachegc

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 8, 2026 License: MIT Imports: 18 Imported by: 0

README

OCI Cache GC

Mark-and-sweep garbage collector for the shared OCI cache at data_dir/system/oci-cache.

The cache is populated every time an image is pulled or pushed and was previously write-only: nothing ever removed layer, config, or manifest blobs, so the cache grew unbounded. This collector reclaims the space used by manifests and layers that are no longer referenced from index.json.

Configuration

images:
  oci_cache_gc:
    enabled: false
    interval: 1h
    min_blob_age: 1h

When enabled, the server runs one pass immediately and then every interval until shutdown.

Algorithm

  1. Mark. Read index.json and walk every referenced descriptor. For each manifest or manifest-index blob we descend into its config, layers, manifests, and subject references. Any extra digests returned by the configured RootsProvider are walked the same way; this is how BuildKit cache exports under cache/* (which the registry tracks in memory but does not root in index.json) stay marked. The set of visited digests is the live set.
  2. Sweep. List blobs/sha256/. Delete every file whose name is a valid 64-char hex digest, is absent from the live set, and whose mtime is older than min_blob_age.

Blobs that are referenced but unparseable are kept as opaque leaves; the collector never deletes a blob it cannot prove is dead.

Concurrency

Pulls (layout.AppendImage) and pushes (BlobStore.Put) write blobs before updating index.json. During that window a blob exists on disk but is not yet in the live set. min_blob_age is the grace period that protects these in-flight writes — it should comfortably exceed the time it takes to pull the largest image in your environment.

Temporary files (<digest>.tmp used by BlobStore.Put) are ignored entirely because they do not match the blob filename pattern.

Metrics

Metric Type Description
hypeman_oci_cache_gc_sweeps_total counter Sweeps, tagged by status
hypeman_oci_cache_gc_sweep_duration_seconds histogram Sweep duration
hypeman_oci_cache_gc_deleted_blobs_total counter Blobs deleted
hypeman_oci_cache_gc_deleted_bytes_total counter Bytes reclaimed

Documentation

Overview

Package ocicachegc performs mark-and-sweep garbage collection of the shared OCI cache at data_dir/system/oci-cache.

The cache stores content-addressed blobs under blobs/sha256/ and an index.json that references one or more manifests. Blobs are written whenever an image is pulled or pushed and are never removed by the normal code paths, so without a GC the cache grows unbounded.

The collector walks index.json and every manifest (or manifest index) reachable from it to build the set of "live" blob digests, then deletes any blob that is not live. Blobs whose mtime is within MinBlobAge are always kept; this is the grace period used to avoid racing with concurrent pulls, which write layer blobs before updating index.json.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Collector

type Collector struct {
	// contains filtered or unexported fields
}

Collector garbage-collects the shared OCI cache.

func NewCollector

func NewCollector(p *paths.Paths, interval, minBlobAge time.Duration, roots RootsProvider, logger *slog.Logger, meter metric.Meter, tracer trace.Tracer) (*Collector, error)

NewCollector creates a collector. minBlobAge is the minimum age a blob must have before it becomes eligible for deletion; it protects blobs that are currently being written by a concurrent pull or push. roots may be nil; when non-nil it is consulted on every sweep for additional manifest digests to mark live.

func (*Collector) Collect

func (c *Collector) Collect(ctx context.Context) (Stats, error)

Collect performs one full mark-and-sweep pass over the OCI cache.

func (*Collector) Run

func (c *Collector) Run(ctx context.Context) error

Run performs one Collect pass immediately and then every interval until ctx is cancelled. It never returns an error; individual sweep failures are logged and metrics are recorded, but the loop keeps running.

type Metrics

type Metrics struct {
	// contains filtered or unexported fields
}

Metrics holds the OTel instruments for the OCI cache collector.

func (*Metrics) RecordSweep

func (m *Metrics) RecordSweep(ctx context.Context, status string, duration time.Duration, stats Stats)

RecordSweep records the outcome of one sweep.

type RootsProvider

type RootsProvider interface {
	LiveCacheManifestDigests() []string
}

RootsProvider returns extra manifest digests (in "sha256:<hex>" form) that should be treated as live alongside everything reachable from index.json. Used for blobs the registry tracks in memory but does not root in the OCI layout (e.g. BuildKit cache exports under cache/*).

type Stats

type Stats struct {
	LiveBlobs     int
	ScannedBlobs  int
	DeletedBlobs  int
	DeletedBytes  int64
	SkippedRecent int
}

Stats summarises the outcome of one Collect pass.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL