ЁЯПл The SchoolтА║ЁЯдЦ ArgoCDтА║ЁЯкСтЖйя╕П рдзрдбрд╛ 09 тАФ Self-heal: рдЦреБрд░реНрдЪреНрдпрд╛ рд╡рд╣реАрдд рд▓рд┐рд╣рд┐рд▓реНрдпрд╛рдкреНрд░рдорд╛рдгреЗ рдкрд░рдд рдЬрд╛рдЧреЗрд╡рд░
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯкСтЖйя╕П рдзрдбрд╛ 09 тАФ Self-heal: рдЦреБрд░реНрдЪреНрдпрд╛ рд╡рд╣реАрдд рд▓рд┐рд╣рд┐рд▓реНрдпрд╛рдкреНрд░рдорд╛рдгреЗ рдкрд░рдд рдЬрд╛рдЧреЗрд╡рд░

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 09 ┬╖ рдорд╛рдЧреАрд▓: lesson-08-sync-policies ┬╖ рдкреБрдвреАрд▓: lesson-10-rollback-history


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбреЗ 01тАУ08, рдЖрдгрд┐ рддреНрдпрд╛рд╕реЛрдмрдд рдзрдбрд╛ 02 рдЪреНрдпрд╛ рд╡реЗрджрдиреЗрдЪреЗ рдлрд│: ArgoCD drift рдХрд╛рд╣реА рд╕реЗрдХрдВрджрд╛рдВрдд рдУрд│рдЦреВрди рдЙрд▓рдЯрд╡рддреЛ рд╣реЗ рдкрд╛рд╣рдгреЗ тАФ рдЖрдгрд┐ рдордЧ рдмрджрд▓ рдХрд░рдгреНрдпрд╛рдЪреА рдпреЛрдЧреНрдп рдкрджреНрдзрдд рд╢рд┐рдХрдгреЗ (рд╡рд╣реА рдмрджрд▓рд╛!).

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рдзрдбрд╛ 02 рдЖрдард╡рддреЛ? рдПрдХрд╛ рдореБрд▓рд╛рдиреЗ рдЦреБрд░реНрдЪреНрдпрд╛ рд╣рд▓рд╡рд▓реНрдпрд╛, рддреАрди рдорд╣рд┐рдиреЗ рдХреЛрдгрд╛рдЪреНрдпрд╛рдЪ рд▓рдХреНрд╖рд╛рдд рдЖрд▓реЗ рдирд╛рд╣реА, рдЖрдгрд┐ рдПрдХреЗ рджрд┐рд╡рд╢реА рдПрдХрд╛ "reset" рдиреЗ рдиреЛрдВрдж рди рдХреЗрд▓реЗрд▓реА рдкреНрд░рддреНрдпреЗрдХ рджреБрд░реБрд╕реНрддреА рдирд╖реНрдЯ рдХреЗрд▓реА. ЁЯШ▒

рддреАрдЪ рд╢рд╛рд│рд╛, рдирд╡рд╛ рдХреЗрдЕрд░рдЯреЗрдХрд░. рдПрдХ рдореВрд▓ 15:00 рд▓рд╛ рдЦреБрд░реНрдЪреНрдпрд╛ рд╣рд▓рд╡рддреЗтАж

Drift рд▓рд╛ рдмрдВрджреА рдЖрд▓реА рдирд╛рд╣реА тАФ рддреЛ рдЯрд┐рдХрд╡реВрди рдареЗрд╡рдгреЗ рдЕрд╢рдХреНрдп рдЭрд╛рд▓реЗ. рд╣рд╛рдЪ рдирд┐рдпрдо рдЖрдгрд┐ reconcile loop рдпрд╛рдВрддрд▓рд╛ рдлрд░рдХ рдЖрд╣реЗ.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    hand["ЁЯШИ you, by hand<br/>kubectl scale --replicas=5"]
    drift["ЁЯПл cluster: 5 pods<br/>book says 2 тЖТ OutOfSync ЁЯЯб"]
    argo["ЁЯдЦ ArgoCD selfHeal<br/>re-applies the book"]
    fixed["тЬЕ back to 2 pods<br/>the book wins"]
    right["ЁЯзСтАНЁЯОУ the RIGHT way:<br/>edit git тЖТ PR тЖТ merge<br/>robot scales up happily"]
    hand -->|"1"| drift -->|"2 noticed in seconds"| argo -->|"3"| fixed
    fixed -.->|"4 want 5 for real?"| right

тЭУ рдХрд╛рдп

ЁЯдФ рд╣реЗ рд╕рд░реНрд╡рд╛рдд рдЬрдмрд░рджрд╕реНрдд feature рдХрд╛ рдЖрд╣реЗ

рдзрдбрд╛ 04, рдЦрдбреНрдбрд╛ #1 тАФ "рджреЛрди deploys рджрд░рдореНрдпрд╛рди рдЦреЛрд▓реАрд╡рд░ рдХреЛрдгреА рд▓рдХреНрд╖ рдареЗрд╡рдд рдирд╛рд╣реА" тАФ рдЖрддрд╛ рд╕рд░рд│ рдЦреЛрдЯреЗ рдард░рддреЗ: рдХрд╛рд╣реАрддрд░реА рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрд▓реАрд╡рд░, рджрд░ рдХрд╛рд╣реА рдорд┐рдирд┐рдЯрд╛рдВрдиреА, рдХрд╛рдпрдо рд▓рдХреНрд╖ рдареЗрд╡рддреЗ, рдЖрдгрд┐ рддреНрдпрд╛рдЪреА "рдмрд░реЛрдмрд░" рдЪреА рдХрд▓реНрдкрдирд╛ рдореНрд╣рдгрдЬреЗ review рдЭрд╛рд▓реЗрд▓реА, version рдЕрд╕рд▓реЗрд▓реА рд╡рд╣реА. Incidents "рддреАрди рдорд╣рд┐рдиреНрдпрд╛рдВрдЪреЗ рд░рд╣рд╕реНрдпрдордп рдмрджрд▓" рдкрд╛рд╕реВрди рдЖрдХреБрдВрдЪрди рдкрд╛рд╡реВрди "ArgoCD рдиреЗ 15:00:30 рд▓рд╛ рджрд╛рдЦрд╡рд▓реЗрд▓рд╛ diff" рдЗрддрдХреЗ рд╣реЛрддрд╛рдд.

тЬЕ рдЦрдбреНрдбрд╛ 1 рдмреБрдЬрд▓рд╛. Drift рдПрдХрд╛ refresh рдордзреНрдпреЗ (~3 рдорд┐рдирд┐рдЯреЗ, рдХрд┐рдВрд╡рд╛ webhook рд╕рд╣ рдХрд╛рд╣реА рд╕реЗрдХрдВрдж) рдУрд│рдЦрд▓рд╛ рдЬрд╛рддреЛ рдЖрдгрд┐ selfHeal рд╕рд╣ рдЙрд▓рдЯрд╡рд▓рд╛ рдЬрд╛рддреЛ тАФ рдЦреЛрд▓реА рдЖрддрд╛ рдЧреБрдкрдЪреВрдк рд╡рд╣реАрд╢реА рдЕрд╕рд╣рдордд рд░рд╛рд╣реВ рд╢рдХрдд рдирд╛рд╣реА.

ЁЯФз рдХрд╕реЗ (рдирд╡реАрди рдХрд╛рд╣реАрдЪ configure рдХрд░рд╛рдпрдЪреЗ рдирд╛рд╣реА!)

рд╣реЗ рддреБрдордЪреНрдпрд╛рдХрдбреЗ рдЖрдзреАрдЪ рдЖрд╣реЗ: argocd/application.yaml рдордзрд▓реЗ selfHeal: true (рдзрдбрд╛ 08). рд╣рд╛ рдзрдбрд╛ рдХреЗрд╡рд│ рдкреНрд░рд╛рддреНрдпрдХреНрд╖рд┐рдХ рдЖрд╣реЗ.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛ тАФ robot рд╢реА рднрд╛рдВрдбрдг рдЙрдХрд░реВрди рдХрд╛рдврд╛

# round 1: FIGHT!
kubectl -n gitops-school scale deployment hello-school --replicas=5
kubectl -n gitops-school get pods -w
# ...watch the extra pods appear тАФ and then get terminated within moments. Ctrl+C.

# round 2: sneakier тАФ edit an env-ish detail:
kubectl -n gitops-school patch deployment hello-school --type merge \
  -p '{"spec":{"template":{"metadata":{"labels":{"hacked":"true"}}}}}'
kubectl -n gitops-school get deploy hello-school -o jsonpath='{.spec.template.metadata.labels}'
# wait ~a moment, check again: the label is GONE. The book wins. ЁЯдЦ

# round 3: do it RIGHT тАФ on your own fork:
#   edit k8s/deployment.yaml тЖТ replicas: 3 тЖТ commit & push
#   (point your Application's repoURL at your fork first)
# тЖТ within ~3 min: 3 pods, no fight, and git shows who wanted 3 and why. ЁЯОЙ

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

Round 1: kubectl -n gitops-school get pods -w рдордзреНрдпреЗ рддреАрди рдЬрд╛рд╕реНрддреАрдЪреЗ pods рджрд┐рд╕рддрд╛рдд рдЖрдгрд┐ рдордЧ рдХрд╛рд╣реА рдХреНрд╖рдгрд╛рдВрдд Terminating рд╣реЛрддрд╛рдд (webhook рдирд╕реЗрд▓ рддрд░ рдХрд╛рд╣реА рдорд┐рдирд┐рдЯрд╛рдВрдкрд░реНрдпрдВрдд). Round 2: рджреБрд╕рд▒реНрдпрд╛ рддрдкрд╛рд╕рдгреАрдд hacked label рдЧреЗрд▓реЗрд▓реЗ рдЕрд╕рддреЗ. kubectl -n argocd get application hello-school рдХрдзреАрдЪ OutOfSync рд╡рд░ рдЯрд┐рдХреВрди рд░рд╛рд╣рдд рдирд╛рд╣реА. Round 3 (рддреБрдордЪрд╛ fork): 3 pods, рдЖрдгрд┐ git log рджрд╛рдЦрд╡рддреЛ рдХреА рддреЗ рдХреЛрдгрд╛рд▓рд╛ рд╣рд╡реЗ рд╣реЛрддреЗ.

ЁЯз╣ рд╕реНрд╡рдЪреНрдЫрддрд╛

рдХрд╛рд╣реАрд╣реА рдХрд╛рдврд╛рдпрдЪреЗ рдирд╛рд╣реА тАФ robot рдиреЗ рддреБрдордЪреНрдпрд╛ рдорд╛рдЧреЗ рдЖрдзреАрдЪ рд╕рд╛рдлрд╕рдлрд╛рдИ рдХреЗрд▓реА рдЖрд╣реЗ. Round 3 рддреБрдордЪреНрдпрд╛ fork рдЪреНрдпрд╛ git history рдордзреНрдпреЗ рд░рд╛рд╣рддреЛ, рдЖрдгрд┐ рдореБрджреНрджрд╛ рддреЛрдЪ рдЖрд╣реЗ.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: selfHeal "рдХреЛрдгреАрддрд░реА prod рд╣рд╛рддрд╛рдиреЗ рдмрджрд▓рд▓реЗ" рдпрд╛рд▓рд╛ рд░рд╣рд╕реНрдпрд╛рдРрд╡рдЬреА timestamp рдЕрд╕рд▓реЗрд▓рд╛ diff рдмрдирд╡рддреЛ. рд╣рд╛рддрд╛рдЪреЗ рдмрджрд▓ рджреБрд░реНрдореАрд│ рдХрд░рдгрд╛рд▒реНрдпрд╛ RBAC (Kubernetes school L17) рд╕реЛрдмрдд рддреЗ рд╡рд╛рдкрд░рд╛, рдЖрдгрд┐ рд╡рд╛рд░рдВрд╡рд╛рд░ рд╣реЛрдгрд╛рд▒реНрдпрд╛ OutOfSync тЖТ Synced рдЙрд▓рдЯрд╛рдкрд╛рд▓рдЯреАрд╡рд░ alert рд▓рд╛рд╡рд╛ тАФ рддреНрдпрд╛рдЪрд╛ рдЕрд░реНрде рдХреЛрдгреАрддрд░реА robot рд╢реА рднрд╛рдВрдбрдд рдЖрд╣реЗ.

тПня╕П рдкреБрдвреЗ

рдЬрд░ рд╡рд╣реА рдиреЗрд╣рдореА рдЬрд┐рдВрдХрддреЗтАж рддрд░ рд╡рд╣реАрдд рдХрд╛рд│рд╛рдд рдорд╛рдЧреЗ рдЬрд╛рдгреЗ рдореНрд╣рдгрдЬреЗ rollback рдЪ рдЕрд╕рд▓рд╛ рдкрд╛рд╣рд┐рдЬреЗ. рддрд╕реЗрдЪ рдЖрд╣реЗ тАФ рдЖрдгрд┐ рддреЗ рдЕрдкреНрд░рддрд┐рдо рдЖрд╣реЗ.

git checkout lesson-10-rollback-history

ЁЯкСтЖйя╕П Lesson 09 тАФ Self-heal: the chairs go back where the book says

ЁЯУН You are here: Lesson 09 of 12 ┬╖ Previous: lesson-08-sync-policies ┬╖ Next: lesson-10-rollback-history


ЁЯУж What's in this branch

Lessons 01тАУ08, plus the payoff for lesson 02's pain: watching ArgoCD detect and revert drift in seconds тАФ then learning the correct way to make changes (edit the book!).

ЁЯзТ Explain like I'm 5

Remember lesson 02? A kid moved the chairs, nobody noticed for three months, and one day a "reset" destroyed every unrecorded fix. ЁЯШ▒

Same school, new caretaker. A kid moves the chairs at 15:00тАж

Drift didn't become forbidden тАФ it became impossible to sustain. That's the difference between a rule and a reconcile loop.

ЁЯЧ║я╕П Diagram

flowchart LR
    hand["ЁЯШИ you, by hand<br/>kubectl scale --replicas=5"]
    drift["ЁЯПл cluster: 5 pods<br/>book says 2 тЖТ OutOfSync ЁЯЯб"]
    argo["ЁЯдЦ ArgoCD selfHeal<br/>re-applies the book"]
    fixed["тЬЕ back to 2 pods<br/>the book wins"]
    right["ЁЯзСтАНЁЯОУ the RIGHT way:<br/>edit git тЖТ PR тЖТ merge<br/>robot scales up happily"]
    hand -->|"1"| drift -->|"2 noticed in seconds"| argo -->|"3"| fixed
    fixed -.->|"4 want 5 for real?"| right

тЭУ What

ЁЯдФ Why this is the killer feature

Lesson 04, gap #1 тАФ "nobody watches the room between deploys" тАФ is now simply false: something watches every room, every few minutes, forever, and its idea of "correct" is the reviewed, versioned book. Incidents shrink from "three months of mystery edits" to "the diff ArgoCD showed at 15:00:30".

тЬЕ Gap 1 closed. Drift is detected within one refresh (~3 minutes, or seconds with a webhook) and, with selfHeal, reverted тАФ the room can no longer quietly disagree with the book.

ЁЯФз How (nothing new to configure!)

You already have it: selfHeal: true in argocd/application.yaml (lesson 08). This lesson is pure demonstration.

ЁЯзк Try it тАФ pick a fight with the robot

# round 1: FIGHT!
kubectl -n gitops-school scale deployment hello-school --replicas=5
kubectl -n gitops-school get pods -w
# ...watch the extra pods appear тАФ and then get terminated within moments. Ctrl+C.

# round 2: sneakier тАФ edit an env-ish detail:
kubectl -n gitops-school patch deployment hello-school --type merge \
  -p '{"spec":{"template":{"metadata":{"labels":{"hacked":"true"}}}}}'
kubectl -n gitops-school get deploy hello-school -o jsonpath='{.spec.template.metadata.labels}'
# wait ~a moment, check again: the label is GONE. The book wins. ЁЯдЦ

# round 3: do it RIGHT тАФ on your own fork:
#   edit k8s/deployment.yaml тЖТ replicas: 3 тЖТ commit & push
#   (point your Application's repoURL at your fork first)
# тЖТ within ~3 min: 3 pods, no fight, and git shows who wanted 3 and why. ЁЯОЙ

тЬЕ Verify тАФ what you should see

Round 1: kubectl -n gitops-school get pods -w shows three extra pods appear and then go Terminating within moments (up to a few minutes without a webhook). Round 2: the hacked label is gone on the second check. kubectl -n argocd get application hello-school never stays OutOfSync. Round 3 (your fork): 3 pods, and git log shows who wanted them.

ЁЯз╣ Clean up

Nothing to remove тАФ the robot already cleaned up after you. Round 3 lives in your fork's git history, which is the point.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: selfHeal turns "somebody changed prod by hand" from a mystery into a diff with a timestamp. Pair it with RBAC (Kubernetes school L17) that makes hand edits rare, and alert on repeated OutOfSync тЖТ Synced flips тАФ they mean someone is fighting the robot.

тПня╕П Next

If the book always winsтАж then going back in time in the book must be a rollback. It is тАФ and it's glorious.

git checkout lesson-10-rollback-history
тЖР Previoussync policiesNext тЖТrollback history

This page is the lesson's README from the lesson-09-self-heal-drift branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.