Workloads pinned to :latest or no tag at all
What does ZopNight detect here?
A container image referenced as :latest or with no tag resolves to whatever the registry holds at pull time. Two pods in 1 ReplicaSet can run different code, and a rollback does not roll anything back. ZopNight checks 3 workload kinds.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1711 · RC-1811 · RC-1911 · RC-1712 · RC-1812 · RC-1912 · RC-1713 · RC-1813 · RC-1913 |
| Category | reliability |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | internal/rules/k8s/image_latest.go |
Where it applies
The same manifest, different code
:latest is not a version. It is a mutable pointer, resolved when the kubelet pulls, so the
image a pod runs depends entirely on when it started.
That produces the failure mode people find hardest to debug: two pods in the same ReplicaSet running different builds. One started before the tag moved, one after, both report the same image string, and they behave differently.
Omitting the tag entirely is identical, since Kubernetes defaults to :latest.
Rollback stops working
This is the consequence that matters most in an incident.
kubectl rollout undo restores the previous pod spec. If both the current and previous specs
say myapp:latest, the rollback restores an identical spec and pulls whatever latest points at
now, which is the broken build you are trying to escape.
The rollout reports success. Nothing changed. That discovery, mid-incident, is the argument for this rule.
imagePullPolicy interacts badly
With :latest, the default pull policy is Always, so every pod start re-pulls. That means a
node failure at 3am silently upgrades the rescheduled pod to whatever is newest: an unplanned
deploy triggered by an unrelated event.
With an explicit tag the default becomes IfNotPresent, and behaviour is predictable.
Digests are stronger than tags
An immutable tag is good; a digest is absolute:
image: myapp@sha256:abc123...A digest cannot be repointed by anyone. For anything where supply-chain integrity matters, that is the only reference that guarantees the bytes you tested are the bytes that run.
Filtering images for latest or no tag
kubectl get deploy,statefulset,daemonset -A -o json | jq -r ' .items[] | . as $w | .spec.template.spec.containers[] | select((.image | test(":") | not) or (.image | endswith(":latest"))) | "\($w.kind) \($w.metadata.namespace)/\($w.metadata.name): \(.image)"'Enforcing it
Tag immutability in the registry stops latest moving under you. ECR, GAR and ACR all support
it, and it is off by default in each.