ЁЯПл The SchoolтА║тШ╕я╕П KubernetesтА║ЁЯдЦ рдзрдбрд╛ 14 тАФ Deploy: CI/CD рдЖрдгрд┐ ArgoCD рд╕рд╣ GitOps (рдПрдХ рдУрд│рдЦ)
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯдЦ рдзрдбрд╛ 14 тАФ Deploy: CI/CD рдЖрдгрд┐ ArgoCD рд╕рд╣ GitOps (рдПрдХ рдУрд│рдЦ)

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 26 рдкреИрдХреА рдзрдбрд╛ 14 тАФ рднрд╛рдЧ 2 (рдкрд╛рдард╡рдгреЗ рдЖрдгрд┐ рд╡рд╛рдврд╡рдгреЗ) рд╕реБрд░реВ ┬╖ рдорд╛рдЧрдЪрд╛: lesson-13-under-the-hood ┬╖ рдкреБрдврдЪрд╛: lesson-15-multi-az-scaling


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

рдЧрд╛рднреНрдпрд╛рдЪреЗ рд╕рд░реНрд╡ 13 рдзрдбреЗ, рдЖрдгрд┐ рд╢реЗрд╡рдЯрдЪрд╛ рднрд╛рдЧ: рдХреЛрдгрддреНрдпрд╛рд╣реА рдорд╛рдгрд╕рд╛рдиреЗ kubectl рди рдЯрд╛рдЗрдк рдХрд░рддрд╛ code рдкреНрд░рддреНрдпрдХреНрд╖ cluster рдкрд░реНрдпрдВрдд рдХрд╕рд╛ рдкреЛрд╣реЛрдЪрддреЛ тАФ robots рдЪреНрдпрд╛ рджреЛрди рдкрджреНрдзрддреА: CI/CD (push) рдЖрдгрд┐ ArgoCD рд╕рд╣ GitOps (pull). рдЦрд▒реНрдпрд╛ files:

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

Robot #1 тАФ рдЧреГрд╣рдкрд╛рдард╛рдЪрд╛ robot (CI/CD, push рдкрджреНрдзрдд). ЁЯУо рддреБрдореНрд╣реА рддреБрдордЪрд╛ рдЧреГрд╣рдкрд╛рда рд╢рд╛рд│реЗрдЪреНрдпрд╛ рдкрддреНрд░рдкреЗрдЯреАрдд рдЯрд╛рдХрддрд╛ (git push). рдПрдХ robot рддреЛ рдЙрдЪрд▓рддреЛ:

  1. рддреЛ рддрдкрд╛рд╕рддреЛ тАФ рд╢реБрджреНрдзрд▓реЗрдЦрди, рдЧрдгрд┐рдд, рд╕рдЧрд│реЗ (tests рдЪрд╛рд▓рд╡рддреЛ). рд╡рд╛рдИрдЯ рдЧреГрд╣рдкрд╛рда рдХрдзреАрдЪ рдкреБрдвреЗ рдЬрд╛рдд рдирд╛рд╣реА.
  2. рддреНрдпрд╛рдЪреА рдЭреЗрд░реЙрдХреНрд╕ рдХрд╛рдврддреЛ тАФ рдЕрдзрд┐рдХреГрдд рдкреНрд░рдд рдмрдирд╡рддреЛ (Docker image рдмрдирд╡рддреЛ ЁЯН▒).
  3. рддреА рдкреНрд░рдд рд╢рд╛рд│реЗрдЪреНрдпрд╛ рдХрдкрд╛рдЯрд╛рдд рдареЗрд╡рддреЛ (ECR registry рд╡рд░ push рдХрд░рддреЛ).
  4. рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрд┐рдХрд╛рдВрдЪреНрдпрд╛ рд╕рд╣реАрдЪреА рд╡рд╛рдЯ рдкрд╛рд╣рддреЛ тЬНя╕П (manual approval рдЪреЗ рдлрд╛рдЯрдХ).
  5. рд╕реНрд╡рддрдГ рдкреНрд░рддреНрдпреЗрдХ рд╡рд░реНрдЧрд╛рдд рдкреЛрд╣реЛрдЪрд╡рддреЛ (cluster рдордзреНрдпреЗ kubectl apply).

рд╣рд╛ robot рдПрдХрд╛ рдореБрдЦреНрдп рдЪрд╛рд╡реАрдиреЗ (CI рдордзреНрдпреЗ рдареЗрд╡рд▓реЗрд▓реА AWS credentials) рд╢рд╛рд│реЗрдд рдШреБрд╕рддреЛ (push). рдЬрд▓рдж рдЖрдгрд┐ рд╕реЛрдкреЗ тАФ рдкрдг рдЪрд╛рд╡реА рд╢рд╛рд│реЗрдЪреНрдпрд╛ рдмрд╛рд╣реЗрд░ рд░рд╛рд╣рддреЗ. ЁЯФСЁЯШм

Robot #2 тАФ рдХрд╛рд│рдЬреАрд╡рд╛рд╣реВ robot (GitOps, pull рдкрджреНрдзрдд). ЁЯдЦ рд╣рд╛ robot рд╢рд╛рд│реЗрдЪреНрдпрд╛ рдЖрддрдЪ рд░рд╛рд╣рддреЛ рдЖрдгрд┐ рддреНрдпрд╛рдЪреНрдпрд╛рдХрдбреЗ рдмрд╛рд╣реЗрд░рдЪреА рдХреЛрдгрддреАрд╣реА рдЪрд╛рд╡реА рдирд╕рддреЗ. рднрд┐рдВрддреАрд╡рд░ рдореБрдЦреНрдп рдкреНрд▓реЕрди-рд╡рд╣реА рдЯрд╛рдВрдЧрд▓реЗрд▓реА рдЕрд╕рддреЗ (рддреБрдордЪрд╛ git repo тАФ k8s/ folder). рджрд░ рдХрд╛рд╣реА рдорд┐рдирд┐рдЯрд╛рдВрдиреА рдХрд╛рд│рдЬреАрд╡рд╛рд╣реВ:

Deploy рдХрд░рд╛рдпрдЪреЗ рдЖрд╣реЗ? рддреБрдореНрд╣реА рд╢рд╛рд│реЗрд▓рд╛ рдЕрдЬрд┐рдмрд╛рдд рд╣рд╛рдд рд▓рд╛рд╡рдд рдирд╛рд╣реА тАФ рддреБрдореНрд╣реА рд╡рд╣реА edit рдХрд░рддрд╛. Roll back рдХрд░рд╛рдпрдЪреЗ рдЖрд╣реЗ? рдХрд╛рд▓рдЪреЗ рдкрд╛рди рдЙрд▓рдЯрд╛ (git revert). рдХрд╛рдп рдЪрд╛рд▓реВ рдЖрд╣реЗ рддреЗ рдЬрд╛рдгреВрди рдШреНрдпрд╛рдпрдЪреЗ рдЖрд╣реЗ? рд╡рд╣реА рд╡рд╛рдЪрд╛ тАФ рддреА рдиреЗрд╣рдореАрдЪ рд╕рддреНрдп рдЕрд╕рддреЗ.

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

flowchart TB
    dev["ЁЯзСтАНЁЯТ╗ git push"]
    subgraph ci["ЁЯУо Robot 1 - CI/CD pipeline"]
        t["тЬЕ test"]
        b["ЁЯН▒ build image"]
        reg["ЁЯЧДя╕П push to registry ECR"]
        hold["тЬНя╕П manual approval"]
        t --> b --> reg --> hold
    end
    subgraph cluster["ЁЯПл Kubernetes cluster"]
        argo["ЁЯдЦ Robot 2 - ArgoCD<br/>lives INSIDE"]
        app["ЁЯкС school-api pods"]
        argo -->|"sync + self-heal"| app
    end
    book["ЁЯУЦ git repo = master plan<br/>k8s/ manifests"]
    dev --> ci
    hold -->|"PUSH style:<br/>kubectl apply from outside"| app
    ci -.->|"GitOps style: CI only<br/>updates the image tag in git"| book
    argo -->|"pulls & compares<br/>every 3 min"| book

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

ЁЯдФ рдХрд╛

рд╣рд╛рддрд╛рдиреЗ рдЪрд╛рд▓рд╡рд▓реЗрд▓реЗ kubectl apply рдЪрд╛рд▓рддреЗ... рд╢реБрдХреНрд░рд╡рд╛рд░реА рд╕рдВрдзреНрдпрд╛рдХрд╛рд│реА 6 рд╡рд╛рдЬреЗрдкрд░реНрдпрдВрдд: рдХрд╛рдп deploy рдЭрд╛рд▓реЗ рдЖрд╣реЗ? рддреЗ рдХреЛрдгреА рдмрджрд▓рд▓реЗ? prod YAML рдкреЗрдХреНрд╖рд╛ рд╡реЗрдЧрд│рд╛ рдХрд╛ рдЖрд╣реЗ? рдХреЛрдгрд╛рд▓рд╛рдЪ рдорд╛рд╣реАрдд рдирд╕рддреЗ. ЁЯФе

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

Push рдкрджреНрдзрдд тАФ рдЖрдзреАрдЪ рдЬреЛрдбрд▓реЗрд▓реА: .circleci/config.yml test-node + test-python рдПрдХрд╛рдЪ рд╡реЗрд│реА рдЪрд╛рд▓рд╡рддреЗ тЖТ build-and-push (рджреЛрдиреНрд╣реА images тЖТ ECR, git SHA рдиреЗ tag рдХреЗрд▓реЗрд▓реНрдпрд╛) тЖТ hold-for-approval тЖТ deploy-to-eks (kubectl apply + rollout status, рдзрдбрд╛ 11 рдЪреЗ рдлрд╛рдЯрдХ). least-privilege рдЪрд╛ рддрдкрд╢реАрд▓ рд▓рдХреНрд╖рд╛рдд рдШреНрдпрд╛: test jobs рдирд╛ AWS credentials рдЕрдЬрд┐рдмрд╛рдд рдорд┐рд│рдд рдирд╛рд╣реАрдд; рдлрдХреНрдд AWS рд▓рд╛ рд╕реНрдкрд░реНрд╢ рдХрд░рдгрд╛рд▒реНрдпрд╛ jobs рдирд╛рдЪ рд╕рд╛рдорд╛рдпрд┐рдХ credentials context рдорд┐рд│рддреЛ.

Pull рдкрджреНрдзрдд тАФ рд╣рд╛ рдзрдбрд╛ рддреА рдЬреЛрдбрддреЛ: argocd-app.yaml ArgoCD рд▓рд╛ рд╕рд╛рдВрдЧрддреЗ: "рдпрд╛ repo рдЪреНрдпрд╛ main branch рдордзрд▓рд╛ k8s/ folder рдкрд╛рд╣рдд рд░рд╛рд╣рд╛, namespace school рддреНрдпрд╛рдЪреНрдпрд╛рд╢реА рдЬреБрд│рддрд╛ рдареЗрд╡, delete рдХреЗрд▓реЗрд▓реНрдпрд╛ рдЧреЛрд╖реНрдЯреА рдХрд╛рдвреВрди рдЯрд╛рдХ (prune), рдЖрдгрд┐ drift self-heal рдХрд░."

spec:
  source:
    repoURL: https://github.com/BaluRaut/learn-kubernetes-school.git
    targetRevision: main
    path: k8s                    # ЁЯУЦ the master plan pages
  syncPolicy:
    automated:
      prune: true                # deleted from git тЖТ deleted from cluster
      selfHeal: true             # hand-edits get reverted. The book wins.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛ (рд╕рдЧрд│реЗ local, ~15 min)

# 1) Install the caretaker robot into your local cluster:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 2) Open its UI:
kubectl -n argocd port-forward svc/argocd-server 8080:443 &
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath='{.data.password}' | base64 -d; echo   # login: admin + this password
# browse https://localhost:8080

# 3) Fork this repo on GitHub, then edit argocd-app.yaml's repoURL to YOUR fork,
#    and in k8s/deployment.yaml replace IMAGE_PLACEHOLDER with a real image
#    (e.g. nginxdemos/hello:plain-text) тАФ commit & push to your fork.

# 4) Hand ArgoCD the plan book:
kubectl apply -f lessons/14-deploy-gitops/argocd-app.yaml
# watch the UI: it clones your repo, shows a diff, and syncs the school into being ЁЯОЙ

# 5) Feel GitOps тАФ deploy WITHOUT kubectl:
#    edit k8s/deployment.yaml in your fork: replicas: 2 тЖТ 3, push...
#    ...and watch a third pod appear on its own within ~3 minutes.

# 6) Feel self-heal тАФ try to cause drift by hand:
kubectl -n school scale deployment school-api --replicas=5
kubectl -n school get pods -w    # the caretaker puts it back to 3. The book wins. ЁЯдЦ

ЁЯФз рдпрд╛ рдзрдбреНрдпрд╛рд╕рд╛рдареА kubectl

kubectl get applications -n argocd ┬╖ argocd app sync

ЁЯФЧ рдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд: ЁЯН▒ Docker L12 (CI build рдЖрдгрд┐ push рдХрд░рддреЛ) ┬╖ ЁЯдЦ ArgoCD рд╢рд╛рд│рд╛ (рд╕рд░реНрд╡ 12 рдзрдбреЗ)

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

manifest рдордзрд▓рд╛ рдмрджрд▓ push рдХрд░рд╛ тЖТ ArgoCD рдЖрдзреА OutOfSync рдЖрдгрд┐ рдордЧ Synced рджрд╛рдЦрд╡рддреЛ; рд╣рд╛рддрд╛рдиреЗ kubectl scale рдХрд░рд╛ тЖТ рддреЗ рд▓рдЧреЗрдЪ рдкреВрд░реНрд╡реАрд╕рд╛рд░рдЦреЗ рд╣реЛрддреЗ.

ЁЯз╣ рд╕рд╛рдлрд╕рдлрд╛рдИ

local рдХрд╛рдо рдЭрд╛рд▓реНрдпрд╛рд╡рд░ kubectl delete namespace argocd

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

ЁЯОУ рд╢реЗрд╡рдЯ тАФ рдпрд╛ рд╡реЗрд│реА рдЦрд░реЛрдЦрд░рдЪрд╛

Push pipelines, pull reconcilers, рдЖрдгрд┐ рдЬреЗрд╡рдгрд╛рдЪреНрдпрд╛ рдбрдмреНрдпрд╛рдВрдкрд╛рд╕реВрди control plane рдкрд░реНрдпрдВрдд рдордзрд▓реЗ рд╕рдЧрд│реЗ. рдЖрддрд╛ рддреБрдореНрд╣рд╛рд▓рд╛ рдлрдХреНрдд рддреБрдордЪреЗ app рдХрд╛рдп рдЪрд╛рд▓рд╡рддреЗ рд╣реЗрдЪ рдирд╛рд╣реА, рддрд░ рддреЗ рдХреЛрдг deploy рдХрд░рддреЗ рдЖрдгрд┐ рдкреНрд░рд╛рдорд╛рдгрд┐рдХ рдареЗрд╡рддреЗ рд╣реЗрд╣реА рд╕рдордЬрддреЗ. рдПрдХ рд╢реЗрд╡рдЯрдЪрд╛ рдмреЛрдирд╕: рдЗрдорд╛рд░рддреАрддрд▓реА рдЖрдЧ рдЖрдгрд┐ рдкрд░реАрдХреНрд╖реЗрдЪреНрдпрд╛ рдирд┐рдХрд╛рд▓рд╛рдЪрд╛ рджрд┐рд╡рд╕ рдпрд╛рддреВрди рддреЗ рдЯрд┐рдХрд╡рдгреЗ.

git checkout lesson-15-multi-az-scaling   # multi-AZ + the scaling ladder ЁЯПлЁЯПл

ЁЯдЦ Lesson 14 тАФ Deploy: CI/CD & GitOps with ArgoCD (an introduction)

ЁЯУН You are here: Lesson 14 of 26 тАФ Part 2 (shipping & scaling) begins ┬╖ Previous: lesson-13-under-the-hood ┬╖ Next: lesson-15-multi-az-scaling


ЁЯУж What's in this branch

All 13 core lessons, plus the finale: how code actually reaches the cluster without a human typing kubectl тАФ two robot styles: CI/CD (push) and GitOps with ArgoCD (pull). Real files:

ЁЯзТ Explain like I'm 5

Robot #1 тАФ the homework robot (CI/CD, push style). ЁЯУо You drop your homework in the school letterbox (git push). A robot picks it up:

  1. Checks it тАФ spelling, math, everything (runs the tests). Bad homework never goes further.
  2. Photocopies it тАФ makes the official copy (builds the Docker image ЁЯН▒).
  3. Files the copy in the school cabinet (pushes to the ECR registry).
  4. Waits for the headteacher's signature тЬНя╕П (the manual approval gate).
  5. Delivers it to every classroom itself (kubectl apply into the cluster).

The robot pushes its way into the school with a master key (AWS credentials stored in CI). Fast and simple тАФ but the key lives outside the school. ЁЯФСЁЯШм

Robot #2 тАФ the caretaker robot (GitOps, pull style). ЁЯдЦ This robot lives inside the school and holds no outside key. On the wall hangs the master plan book (your git repo тАФ the k8s/ folder). Every few minutes the caretaker:

Want to deploy? You don't touch the school at all тАФ you edit the book. Want to roll back? Flip to yesterday's page (git revert). Want to know what's running? Read the book тАФ it's always the truth.

ЁЯЧ║я╕П Diagram

flowchart TB
    dev["ЁЯзСтАНЁЯТ╗ git push"]
    subgraph ci["ЁЯУо Robot 1 - CI/CD pipeline"]
        t["тЬЕ test"]
        b["ЁЯН▒ build image"]
        reg["ЁЯЧДя╕П push to registry ECR"]
        hold["тЬНя╕П manual approval"]
        t --> b --> reg --> hold
    end
    subgraph cluster["ЁЯПл Kubernetes cluster"]
        argo["ЁЯдЦ Robot 2 - ArgoCD<br/>lives INSIDE"]
        app["ЁЯкС school-api pods"]
        argo -->|"sync + self-heal"| app
    end
    book["ЁЯУЦ git repo = master plan<br/>k8s/ manifests"]
    dev --> ci
    hold -->|"PUSH style:<br/>kubectl apply from outside"| app
    ci -.->|"GitOps style: CI only<br/>updates the image tag in git"| book
    argo -->|"pulls & compares<br/>every 3 min"| book

тЭУ What

ЁЯдФ Why

Hand-run kubectl apply works... until Friday 6 PM: what's deployed? who changed it? why is prod different from the YAML? Nobody knows. ЁЯФе

ЁЯФз How (in this repo)

Push style тАФ already wired: .circleci/config.yml runs test-node + test-python in parallel тЖТ build-and-push (both images тЖТ ECR, tagged with the git SHA) тЖТ hold-for-approval тЖТ deploy-to-eks (kubectl apply + rollout status, lesson 11's gate). Note the least-privilege detail: test jobs get no AWS credentials; only the AWS-touching jobs receive the shared credentials context.

Pull style тАФ this lesson adds it: argocd-app.yaml tells ArgoCD: "watch the k8s/ folder of this repo's main branch, keep namespace school matching it, prune deleted things, and self-heal drift."

spec:
  source:
    repoURL: https://github.com/BaluRaut/learn-kubernetes-school.git
    targetRevision: main
    path: k8s                    # ЁЯУЦ the master plan pages
  syncPolicy:
    automated:
      prune: true                # deleted from git тЖТ deleted from cluster
      selfHeal: true             # hand-edits get reverted. The book wins.

ЁЯзк Try it (all local, ~15 min)

# 1) Install the caretaker robot into your local cluster:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 2) Open its UI:
kubectl -n argocd port-forward svc/argocd-server 8080:443 &
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath='{.data.password}' | base64 -d; echo   # login: admin + this password
# browse https://localhost:8080

# 3) Fork this repo on GitHub, then edit argocd-app.yaml's repoURL to YOUR fork,
#    and in k8s/deployment.yaml replace IMAGE_PLACEHOLDER with a real image
#    (e.g. nginxdemos/hello:plain-text) тАФ commit & push to your fork.

# 4) Hand ArgoCD the plan book:
kubectl apply -f lessons/14-deploy-gitops/argocd-app.yaml
# watch the UI: it clones your repo, shows a diff, and syncs the school into being ЁЯОЙ

# 5) Feel GitOps тАФ deploy WITHOUT kubectl:
#    edit k8s/deployment.yaml in your fork: replicas: 2 тЖТ 3, push...
#    ...and watch a third pod appear on its own within ~3 minutes.

# 6) Feel self-heal тАФ try to cause drift by hand:
kubectl -n school scale deployment school-api --replicas=5
kubectl -n school get pods -w    # the caretaker puts it back to 3. The book wins. ЁЯдЦ

ЁЯФз kubectl for this lesson

kubectl get applications -n argocd ┬╖ argocd app sync

ЁЯФЧ Builds on: ЁЯН▒ Docker L12 (CI builds & pushes) ┬╖ ЁЯдЦ ArgoCD school (all 12 lessons)

тЬЕ Verify тАФ what you should see

push a manifest change тЖТ ArgoCD shows OutOfSync then Synced; kubectl scale by hand тЖТ it snaps back.

ЁЯз╣ Clean up

kubectl delete namespace argocd when done locally

тЪая╕П Common mistakes

ЁЯОУ The end тАФ for real this time

Push pipelines, pull reconcilers, and everything from lunchboxes to the control plane in between. You now understand not just what runs your app, but what deploys it and keeps it honest. One last bonus: making it survive a building fire and exam-results day.

git checkout lesson-15-multi-az-scaling   # multi-AZ + the scaling ladder ЁЯПлЁЯПл
тЖР Previousunder the hoodNext тЖТmulti az scaling

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