Skip to main content
RunBook Academy

Git, CI/CD & GitOpsLXXXVII · GitOps During IncidentsSelfHeal

Disabling self-heal — how, who, and for how long

Advanced⏱ ~26 mingit

What you'll learn

  • Apply the two Argo CD flags that suspend self-heal and switch to manual sync for a single Application
  • Apply the Flux `suspend` field on a Kustomization or HelmRelease to suspend reconciliation
  • Distinguish per-Application suspension from cluster-wide disablement and choose the surgical option
  • Set and enforce a time bound on the suspension so the break cannot become permanent

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

Not yet marked complete on this device.

Self-heal suspension is the executable form of the break-glass procedure from LXXXVII-02. The discipline is to scope the break to the affected Application, set a time bound, and resume as soon as the bleeding stops. The opposite discipline - disabling self-heal globally on the cluster - is the trap this lesson exists to help the responder avoid.

The two Argo CD commands that compose the surgical break:

argocd app set $APP_NAME --self-heal=false
argocd app set $APP_NAME --sync-policy manual

The first command disables automatic reversion of drift on the named Application. The second command switches the sync policy from automated to manual, so the controller will not even apply non-drift changes without an explicit sync. Both are per-Application; both are reversible by re-running with the inverse flag values.

The two flags and what each does

--self-heal=false is the surgical disablement. The controller stops reverting drift on the named Application but continues to apply Git changes that differ from the cluster (under automated sync). The flag is the minimum break needed to preserve an emergency edit; it does not stop new Git changes from being applied.

--sync-policy manual is the broader disablement. The controller stops applying any Git changes to the named Application without an explicit argocd app sync $APP_NAME invocation. This is the break to use when the incident involves the controller itself or when the responder needs full control over when the next Git change takes effect.

The production rule: use --self-heal=false for the one-line fix shape; use --sync-policy manual for the destructive deletion and the controller-induced incident shapes from LXXXVII-01. Do not disable both globally; do not disable either globally.

flowchart LR
    A["Incident declared"] --> B{"Which shape?"}
    B -- "one-line fix" --> C["--self-heal=false"]
    B -- "destructive deletion" --> D["--sync-policy manual"]
    B -- "controller-induced" --> D
    C --> E["Apply edit, document"]
    D --> E
    E --> F["Commit to Git"]
    F --> G["Resume"]

Flux’s equivalent

Flux’s equivalent is the spec.suspend field on a Kustomization or HelmRelease. Setting it to true pauses reconciliation on the named resource; setting it back to false resumes.

flux suspend kustomization $KS_NAME
flux resume kustomization $KS_NAME

The Flux CLI commands take the resource name and namespace as arguments. They are per-resource and reversible. There is no cluster-wide suspend in Flux; the closest equivalent is to set spec.suspend: true on every Kustomization, which is the wrong default for the same reason that disabling self-heal globally is the wrong default in Argo CD.

The time bound

The suspension has a time bound. The default rule is “the duration of the declared incident, no longer”. The bound is enforced in three places:

  • The incident channel. A timestamped message naming the Application, the flags set, and the expected resume time. The resume time is the incident’s expected close time plus a small buffer.
  • The runbook entry. The break-glass procedure’s duration element specifies the maximum suspension. For most teams this is “until end of incident, hard cap of four hours”.
  • The post-incident repair. The repair step in LXXXVII-02 is the resume; the repair has its own deadline (typically 24 hours from end of incident) that re-enables self-heal even if the responder has not done so.

The hard cap matters because incidents are sometimes forgotten once the bleeding stops. The on-call engineer resolves the incident, walks away, and the suspension persists. The post-incident repair’s job is to catch the forgotten suspension and re-enable self-heal before the next change hits.

Production discipline

  1. Use per-Application flags, never cluster-wide. The break is scoped to the Application in the incident.
  2. Pair the flags with a time bound. The suspension has a documented expected resume time in the incident channel.
  3. Verify the suspension. After running argocd app set, run argocd app get $APP_NAME and confirm the new flags appear in the Sync Policy block.
  4. Resume as part of the repair. The resume command is part of the post-incident repair checklist, not a separate action.

Cross-course references

  • This course, Part LXXXVII-01 (The incident versus GitOps tension) - the three shapes that motivate the two flags.
  • This course, Part LXXXVII-02 (Break-glass procedures) - the procedure that authorises the flags.
  • Kubernetes for Production Sysadmins - Parts on cluster operations cover the broader pattern of scoped versus cluster-wide operational changes.

Quiz

Knowledge check · 4 questions

  1. Q1. An on-call engineer needs to recover a service by removing a failing sidecar container from a Deployment. The recovery is destructive (the sidecar cannot be removed by an `edit`; the Pod must be deleted). Which Argo CD command sequence is correct?

  2. Q2. Disabling self-heal cluster-wide via the Argo CD operator ConfigMap is acceptable during a critical incident because it stops the reconciler faster than per-Application flags.

  3. Q3. What is the Flux CLI equivalent of `argocd app set $APP_NAME --self-heal=false`, and on which resource types does it operate?

  4. Q4. Diagnose the operational mistake and identify the correct per-Application suspension sequence.

    A team has a critical incident at 02:00. A senior engineer runs `kubectl edit cm/argocd-cm -n argocd` and sets `data.selfHeal: 'false'` in the operator ConfigMap to stop self-heal cluster-wide. The engineer then applies the emergency edit on the affected Application. The incident is resolved at 02:45. At 09:00 the next morning, the cluster has drifted on three unrelated Applications because self-heal is still disabled cluster-wide. The team did not notice because the morning's deployments were automated by other Argo CD controllers that do not consult self-heal.

Passing score: 75%. Answers are checked in this browser.