92 lines
5.8 KiB
Markdown
92 lines
5.8 KiB
Markdown
# Course VII - The image supply chain: registries, mirrors, tags and digests
|
|
|
|
**Series position:** second course of the delivery arc. Course I taught what an image IS;
|
|
this course teaches how one travels - and how to say its name precisely.
|
|
**Safety gate:** public site - technologies only. Claims source from [[zot-registry]],
|
|
[[homelab-pull-through-registry]], [[work-container-image-tagging]] (generalised: the
|
|
calendar-rev pattern taught as "a human tag scheme", no corp framing), Azure Container
|
|
Registry as the generic managed-registry example, OpenShift IDMS behaviour from public
|
|
Red Hat docs.
|
|
|
|
## Title (thesis)
|
|
**A tag is a promise. A digest is a fact.**
|
|
|
|
## Hook - the uncomfortable default
|
|
`myapp:latest` feels like a name. It is not - it is a sticky note. A tag is a mutable
|
|
pointer anyone with push rights can peel off one image and press onto another, and
|
|
nothing anywhere records that it moved. The digest - sha256 of the content - is the
|
|
image's actual name: same bytes, same digest, forever. Most outages in this territory
|
|
begin with two machines both holding "the same tag" and running different code.
|
|
|
|
## Move 1 - Say the name properly
|
|
Three ways to name an image, in rising order of honesty: `:latest` (a moving target),
|
|
`:1.4.2` (a promise somebody keeps, until they re-push it), `name:1.4.2@sha256:...`
|
|
(a fact - the tag stays for human eyes, the digest does the pulling). Content-addressing
|
|
is the same idea git uses for commits: the name IS the bytes. Pin by digest and "what is
|
|
running?" has exactly one answer.
|
|
Say it like you mean it: **the tag is for reading, the digest is for pulling.**
|
|
FIELD NOTE (amber): `:latest` is how two nodes run different code from one manifest -
|
|
the second node pulled an hour later, after a re-push. Nobody changed the YAML.
|
|
|
|
## Move 2 - Why a fleet pulls once
|
|
Between the build and the node sits the registry chain. Upstream, a managed registry
|
|
(Azure Container Registry as the worked example) holds what CI built. In front of the
|
|
cluster sits a MIRROR - a pull-through cache like zot: the fleet asks the mirror, the
|
|
mirror asks upstream once, everything after is local. Three reasons this exists: rate
|
|
limits and egress cost (a hundred nodes should not make a hundred internet pulls),
|
|
availability (the fleet boots even when upstream is down or the site is disconnected),
|
|
and control (one place to gate, scan and audit what enters). OpenShift formalises the
|
|
re-route with image mirror rules - and carries a sharp edge: its digest-mirror rules
|
|
rewrite DIGEST pulls only, so a by-tag pull skips them - UNLESS an ImageTagMirrorSet is also
|
|
added (the rule type for tag pulls; corrected 2026-08-17). The pinning habit
|
|
from Move 1 is what makes the mirror actually catch the traffic.
|
|
FIELD NOTE: a mirror can also serve a STALE tag->digest mapping while upstream moved the
|
|
tag. Pin by digest and the whole chain becomes content-addressed - the mirror cannot be
|
|
wrong about a hash.
|
|
TIERING (added 2026-08-17, owner ask): at real fleet scale the mirror itself tiers - a
|
|
central pull-through in the cloud fronts upstream once; per-site mirrors pull from the
|
|
centre; nodes pull from their site over the LAN. The load fans out in layers instead of
|
|
every site hammering upstream at once. Say it: mirrors tier - the load fans out in
|
|
layers, never all at once.
|
|
|
|
## Move 3 - Build once, promote by copy
|
|
The anti-pattern: rebuild the image for each environment ("the prod build"). Every
|
|
rebuild is a different artefact - different digest, different bytes, untested by the
|
|
stages before it. The discipline: build ONCE, then PROMOTE the same digest through
|
|
environments by copying (skopeo copy --all --preserve-digests for multi-arch, or the copy takes
|
|
one arch and the promoted digest is not the one that lands) - dev proves the exact bytes
|
|
prod will run. Human-readable tags ride along (a calendar-plus-revision scheme reads well:
|
|
month, year, revision), but the digest is the through-line; promotion never changes it.
|
|
Say it like you mean it: **if the digest changed, it is not a promotion - it is a new
|
|
candidate.**
|
|
|
|
## Close
|
|
Everything in this course is one idea wearing three coats: names that can move are
|
|
convenient exactly until they move. Address content by what it IS, let humans keep their
|
|
readable labels, and the supply chain stops being a chain of trust and becomes a chain
|
|
of arithmetic.
|
|
|
|
## Legend terms (DOM layer)
|
|
tag / digest / content-addressing / pull-through mirror / disconnected pull / rate limit /
|
|
image mirror rule (digest-only rewrite) / build-once / promotion / skopeo copy
|
|
|
|
## Scene concept (hero + slices, the v3 mechanism)
|
|
Exploded left-to-right journey: the layered image CUBE from Course I (familiar - four
|
|
thin slabs, tight formation, reads as one unit now) -> upstream registry TOWER (tall
|
|
managed vault, cool white-cyan) -> the mirror WAY-STATION (squat wide cache block, warm
|
|
cyan, visibly closer to the cluster side) -> the node/cluster CORE. Floating above the
|
|
journey, two seal plates apart from each other: a GHOST RIBBON plate (the tag - faint,
|
|
translucent, edges blurring) and an ENGRAVED SEAL plate (the digest - dense, crisp,
|
|
crystalline). 6 parts, generous void, no connectors. Slice plan: collapse draws the
|
|
journey into the mirror block (everything local); the two seals collapse toward each
|
|
other but never merge - ghost stays ghost.
|
|
|
|
## Page footer - pre-reads + further reading (site convention: every course carries this)
|
|
Pre-reads: Course I (what an image IS - layers, this course ships that object);
|
|
Kubernetes images concept (https://kubernetes.io/docs/concepts/containers/images/).
|
|
Further reading: zot registry docs (https://zotregistry.dev/); Azure Container
|
|
Registry (https://learn.microsoft.com/azure/container-registry/); OpenShift image
|
|
configuration + mirroring (via
|
|
https://docs.redhat.com/en/documentation/openshift_container_platform); skopeo
|
|
(https://github.com/containers/skopeo).
|