Git, CI/CD & GitOpsLXXXVI · GitOps Failure ModesDetection
Repository unavailable — what happens when Git is down
What you'll learn
- Recognise the symptoms a GitOps controller reports when the repository is unreachable
- Distinguish a transient blip from a sustained outage using the controller log
- Explain why an unreachable repository does not mean an unchanged cluster
- Apply the read-only fallback that keeps the controller from making things worse
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
The first failure mode is the one that motivates the discipline:
the source-of-truth repository becomes unreachable. The
controller cannot pull, reconciliation stalls, and the natural
assumption - “the cluster is safe because nothing new is being
applied” - is wrong. Humans with kubectl, other controllers,
and scheduled jobs all continue to write to the cluster, and the
GitOps reconciliation has gone blind.
The symptom on the controller
The first read is the application status:
argocd app get guestbook
When the repository is unreachable, the status reports
OutOfSync or Unknown and the message column carries a fetch
error: rpc error: code = Unavailable for a network failure or
failed to fetch: repository not found for a misconfigured URL.
The canonical source is the controller log:
kubectl -n argocd logs statefulset/argocd-application-controller
The log shows repeated fetch attempts with exponential backoff.
After three failed attempts Argo CD marks the application
Degraded with reason ComparisonError.
flowchart LR
A[Controller poll] --> B{Repo reachable?}
B -- yes --> C[Fetch manifests]
B -- no --> D[Backoff and retry]
D --> E{Retries exhausted?}
E -- no --> D
E -- yes --> F["Mark Degraded: ComparisonError"]
C --> G[Diff against live]
G --> H[Apply if drift]
Distinguishing transient from sustained
A network blip produces a single failed poll that the next
successful attempt masks. The signal to read is the gap between
the last successful sync timestamp and the controller’s
Degraded annotation. A gap under one minute is a blip; a gap
measured in hours with the same error repeating is an outage.
For Flux, the equivalent is the GitRepository resource:
kubectl get gitrepository -A
The status.conditions field reports Ready=False with reason
GitOperationFailed and the underlying transport error.
Ready=Unknown means the source controller itself is not
running - a separate failure mode covered in the next lesson.
What the controller does during the outage
The reconciliation loop does not stop on a fetch failure. It continues polling at its configured interval (default three minutes for Argo CD, one minute for Flux) and increments the backoff on each failure. The controller does not roll back to the last known good state, because the cluster already reflects that state and there is nothing to revert to.
A controller that reverted on a fetch failure would revert correctly-applied changes every time the network blinked. The trade-off is operator visibility, which must be recovered through alerts, not through automatic rollback.
Production discipline
- Do not sync against a stale cache. Argo CD supports
--revisionto pin a commit - the correct escape hatch when the repository is down but a known-good commit exists. - Treat the controller as degraded, not as correct. The cluster can drift during the outage. When the repository returns, the next diff surfaces real drift.
- Page on
Degraded, not onOutOfSync.OutOfSyncmeans “live differs from desired” and triggers a sync.Degradedmeans “controller cannot fulfil its contract” and is the alert.
Cross-course references
- Linux for Production Sysadmins - Parts XII (RepoSecurity) and XXXIV (ConfigMgmt) cover the apt/dnf mirror-down analogue: a stalled install, not a frozen filesystem.
- Terraform for Production Sysadmins - Parts IX-XII (State) cover state-store unavailability, with the same shape.
Quiz
Knowledge check · 4 questions
Q1. An Argo CD application shows 'Degraded' with reason 'ComparisonError' and 'rpc error: code = Unavailable'. What is the most accurate reading?
Q2. A GitOps controller that cannot reach its repository should preserve the last applied state rather than automatically reverting the cluster.
Q3. Which two commands are the canonical first read when an application looks stale?
Q4. Diagnose the controller state and decide the safe operator action.
A cluster ran for six hours with an Argo CD application in 'Degraded' state because the source GitHub repository had an outage. The outage has just resolved. The operator runs `argocd app get` and sees 'OutOfSync' with a long list of resources that 'require pruning' and 'require creation'.
Passing score: 75%. Answers are checked in this browser.