The Namespaces That Must Never Route Through Harbor: Every Loop, Written Down
Harbor pulling through itself is the obvious loop — but kyverno with failurePolicy=Fail is the measured worst case: Harbor down means no pod creation cluster-wide, including the pods needed to repair Harbor.
Every exclusion in the routing policy exists because routing that namespace would make Harbor depend on something that depends on Harbor. Some are obvious. The worst one is measured, not assumed.
The loop table
| Namespace | Images | Why routing it breaks recovery |
harbor | 10 goharbor/* | cannot pull itself through itself — unrecoverable after a full outage |
kyverno | 6 reg.kyverno.io/* | webhooks are failurePolicy=Fail — the single most important exclusion |
flux-system | 4 fluxcd/* | Flux deploys the fix — losing it mid-incident is the worst moment |
envoy-gateway-system | 2 envoyproxy/* | terminates Harbor's ingress — no Envoy, no reachable Harbor |
cert-manager | 3 jetstack/* | issues Harbor's TLS — expiry plus inability to start is a deadlock |
external-secrets | 1 | supplies Harbor's credentials — no secrets, no Harbor |
dragonfly-operator-system | 2 | runs Harbor's Redis — Harbor will not start without it |
Plus kube-system: Cilium is the CNI Harbor itself needs to serve traffic. Routing the control plane is routing your own recovery.
The full exclusion list with its failure modes — and the kyverno row, which deserves its own sentence.
The kyverno row, measured
The manifest comment does not assert the risk; it walks the chain: Harbor down → Kyverno cannot pull → Kyverno down → its admission webhooks have failurePolicy=Fail, so the API server refuses matching pod creation cluster-wide — including the pods needed to repair Harbor. That is why the kyverno exclusion is called the single most important one.
A finer point from the same analysis: dragonflydb/dragonfly itself is routable — it also runs in gitlab, so it gets cached and scanned through that namespace while harbor keeps pulling direct. Only the operator is excluded. The exclusions apply to namespaces, and an image's fate follows every namespace it runs in.
Reading a loop aloud
Each exclusion is easier to trust when the loop is spoken as a sentence. The kyverno one, at full length: Harbor is down; a Kyverno pod needs to start (or restart); its image lives on reg.kyverno.io, which — if kyverno were routed — Harbor would fetch through itself; Harbor cannot fetch, so Kyverno stays down; Kyverno's admission webhooks have failurePolicy=Fail, so the API server rejects matching pod creation cluster-wide; the Harbor pods someone just tried to create to fix Harbor are themselves rejected. The loop closes. No ordering of recovery steps breaks it, because every recovery step requires creating a pod, and pod creation is the thing that is down.
The harbor exclusion is the same sentence with the middle removed: Harbor cannot pull itself through itself. After a full outage — control-plane included — the first Harbor pod has no cache, no source, and no path.
The near-loops that are not on the list
The analysis also identified couplings that look like exclusions but are not, and the distinction matters for future components:
- dragonflydb/dragonfly runs in
gitlabas well asharbor— thegitlabinstance is routable and gets cached and scanned; only the operator (solely indragonfly-operator-system) is excluded. An image's fate follows every namespace it runs in; an image with one safe home is a routable image. - flux-system is "not a strict loop" — Flux does not serve Harbor's traffic — but it deploys the fix, and losing the deployer during a Harbor incident is the worst possible moment. Excluded on operational grounds, and labeled as such.
The documentation therefore records, per exclusion, which kind of reason applies: hard loop, recovery-path loss, or governance. That taxonomy is what makes the list extendable — a new component is classified, not argued.
The test for candidates
The runbook's implicit test, made explicit: for component X to be routable, there must exist a recovery path for Harbor that does not require creating a pod whose image X serves, guards, authenticates, or deploys. Harbor's recovery path currently runs through: the CNI (Cilium), ingress (Envoy), TLS (cert-manager), credentials (external-secrets), cache (dragonfly), policy (Kyverno), and deployment (Flux). Seven components, seven exclusions, one sentence each.
Next: the bare reference — the one image tag in the repo that must never be fully qualified.