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

ЁЯзСтАНЁЯПл рдзрдбрд╛ 03 тАФ Deployments: рдХрдбрдХ рд╡рд░реНрдЧ-рдкреНрд░рдореБрдЦ

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 13 рдкреИрдХреА рдзрдбрд╛ 03 ┬╖ рдорд╛рдЧрдЪрд╛: lesson-02-pods ┬╖ рдкреБрдврдЪрд╛: lesson-04-services


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

рдзрдбреЗ 01тАУ02, рдЖрдгрд┐: Deployment тАФ рддреБрдордЪреЗ pods рдпреЛрдЧреНрдп рд╕рдВрдЦреНрдпреЗрдиреЗ, рдпреЛрдЧреНрдп version рдЪрд╛рд▓рд╡рдд рдЬрд┐рд╡рдВрдд рдареЗрд╡рдгрд╛рд░рд╛ object. рдЦрд▒реНрдпрд╛ files:

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

рд╢рд┐рдХреНрд╖рд┐рдХрд╛ рд╡рд░реНрдЧ-рдкреНрд░рдореБрдЦрд╛рд▓рд╛ рд╕рд╛рдВрдЧрддрд╛рдд: "рдЭрд╛рдбрд╛рдВрдирд╛ рдкрд╛рдгреА рдШрд╛рд▓рд╛рдпрд▓рд╛ рдиреЗрд╣рдореА 2 рдореБрд▓реЗ рдЕрд╕рд▓реАрдЪ рдкрд╛рд╣рд┐рдЬреЗрдд. рдиреЗрд╣рдореА. рдХрд╕реЗ рддреЗ рдорд▓рд╛ рдорд╛рд╣реАрдд рдирд╛рд╣реА." ЁЯзСтАНЁЯПлЁЯМ▒

рд╡рд░реНрдЧ-рдкреНрд░рдореБрдЦ рд╣реЗ рдЧрд╛рдВрднреАрд░реНрдпрд╛рдиреЗ рдШреЗрддреЛ:

рд╣рд╛рдЪ Deployment. рддреБрдореНрд╣реА Kubernetes рд▓рд╛ рдХрд╛рдп рдХрд░рд╛рдпрдЪреЗ рддреЗ рд╕рд╛рдВрдЧрдд рдирд╛рд╣реА тАФ рддреБрдореНрд╣реА рддреНрдпрд╛рд▓рд╛ рдЬрдЧ рдХрд╕реЗ рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ рддреЗ рд╕рд╛рдВрдЧрддрд╛ ("school-api рдЪреНрдпрд╛ 2 рдкреНрд░рддреА, version v5"), рдЖрдгрд┐ рд╡рд░реНрдЧ-рдкреНрд░рдореБрдЦ рд╡рд╛рд╕реНрддрд╡ рддреБрдордЪреНрдпрд╛ рдЗрдЪреНрдЫреЗрд╢реА рдЬреБрд│рддреЗ рдареЗрд╡рдгреНрдпрд╛рд╕рд╛рдареА рдХрд╛рдпрдо рдХрд╛рдо рдХрд░рддреЛ. Kubernetes рдордзрд▓реА рд╣реА рдПрдХрдореЗрд╡ рд╕рд░реНрд╡рд╛рдд рдореЛрдареА рдХрд▓реНрдкрдирд╛: desired state (рдЗрдЪреНрдЫрд┐рдд рд╕реНрдерд┐рддреА). рддреБрдореНрд╣реА рдЬрд╛рд╣реАрд░ рдХрд░рддрд╛; рддреЛ рдЬреБрд│рд╡реВрди рдШреЗрддреЛ.

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

flowchart TB
    Y["ЁЯзСтАНЁЯПл You declare:<br/>replicas: 2, image: v5"]
    D["Deployment<br/>school-api"]
    RS["ReplicaSet - the monitor<br/>keeps count = 2"]
    P1["ЁЯкС Pod school-api-abc12"]
    P2["ЁЯкС Pod school-api-def34"]
    P3["ЁЯкС Pod school-api-xyz99<br/>auto-created replacement"]
    Y --> D --> RS
    RS --> P1
    RS --> P2
    P1 -. "ЁЯТе crashes" .-> P3
    RS -- "notices 1 missing,<br/>creates a new one" --> P3

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

ЁЯза Desired state тЖТ reconciliation тЖТ actual state

Desired state        replicas: 2          (what you wrote in git)
        тЖУ
Kubernetes continuously compares          (the controller loop, every few seconds, forever)
        тЖУ
Actual state         1 Pod                (one just crashed)
        тЖУ
creates another Pod
        тЖУ
Actual state = Desired state   2 Pods тЬЕ

Kubernetes рд╣реА рдПрдХ reconciliation (рдЬреБрд│рд╡рдгреА) system рдЖрд╣реЗ. рддреБрдореНрд╣реА рддреНрдпрд╛рд▓рд╛ рдХрдзреАрдЪ рдХрд╛рдп рдХрд░рд╛рдпрдЪреЗ рддреЗ рд╕рд╛рдВрдЧрдд рдирд╛рд╣реА тАФ рддреБрдореНрд╣реА рдЧреЛрд╖реНрдЯреА рдХрд╢рд╛ рдЕрд╕рд╛рд╡реНрдпрд╛рдд рддреЗ рд╕рд╛рдВрдЧрддрд╛, рдЖрдгрд┐ controllers рджрд░реА рдмреБрдЬрд╡рддрд╛рдд, рдХрд╛рдпрдо. рд╣рд╛ рдПрдХрдЪ loop Deployments, ReplicaSets, HPA (L09), Jobs (L18), StatefulSets (L22), operators (L25) рдЖрдгрд┐ ArgoCD (L14) рд╕рдордЬрд╛рд╡рддреЛ тАФ рддреЛрдЪ loop, рдлрдХреНрдд рдирд╡реА рдЯреЛрдкреА.

ЁЯдФ рдХрд╛

рдзрдбрд╛ 02 рдореЗрд▓реЗрд▓рд╛ pod рдореЗрд▓реЗрд▓рд╛рдЪ рд░рд╛рд╣рддреЛ рдпрд╛рд╡рд░ рд╕рдВрдкрд▓рд╛. рдЦрд▒реНрдпрд╛ apps рдирд╛ рд░рд╛рддреНрд░реА 3 рд╡рд╛рдЬрддрд╛ рддреБрдордЪреНрдпрд╛рд╢рд┐рд╡рд╛рдп рд╕реНрд╡рддрдГрд╣реВрди рдмрд░реЗ (self-heal) рд╡реНрд╣рд╛рд╡реЗ рд▓рд╛рдЧрддреЗ. Deployment рдореБрд│реЗрдЪ Kubernetes рд╡рд╛рд▓реЗ рд▓реЛрдХ рд╢рд╛рдВрдд рдЭреЛрдкрддрд╛рдд: crash рдЭрд╛рд▓реЗрд▓рд╛ pod, reboot рдЭрд╛рд▓реЗрд▓рд╛ node, рдорд╛рд░рд▓реЗрд▓рд╛ container тАФ рд╡рд░реНрдЧ-рдкреНрд░рдореБрдЦ рдпрд╛ рд╕рдЧрд│реНрдпрд╛рдВрдирд╛ рдмрджрд▓рддреЛ, рдХрд╛рд░рдг рддреБрдордЪреНрдпрд╛ YAML рдиреЗ рд╕рд╛рдВрдЧрд┐рддрд▓реЗ рд╣реЛрддреЗ "2 рдЕрд╕рддреАрд▓". рддреЛ рдПрдХрд╛ рд╡реЗрд│реА рдПрдХ pod рдмрджрд▓реВрди zero-downtime upgrades (рдзрдбрд╛ 11) рд╕реБрджреНрдзрд╛ рд╢рдХреНрдп рдХрд░рддреЛ.

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

k8s/deployment.yaml рдЙрдШрдбрд╛:

spec:
  replicas: 2                 # тЖР the promise: ALWAYS 2 desks
  selector:
    matchLabels:
      app: school-api         # тЖР "my pods wear this sticker"
  template:                   # тЖР lesson 02's pod blueprint
    metadata:
      labels:
        app: school-api       # тЖР the sticker itself (must match!)

image: IMAGE_PLACEHOLDER рдХрдбреЗ рд▓рдХреНрд╖ рджреНрдпрд╛ тАФ deploy рдЪреНрдпрд╛ рд╡реЗрд│реА CircleCI рддреНрдпрд╛рдд рдЦрд░рд╛ ECR image tag рдЯрд╛рдХрддреЛ (.circleci/config.yml рдкрд╛рд╣рд╛).

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

kubectl apply -f k8s/namespace.yaml          # the room first (lesson 05 explains)
kubectl apply -f k8s/configmap.yaml          # config (lesson 06 explains)

# For local play, use a public image instead of IMAGE_PLACEHOLDER:
sed 's|IMAGE_PLACEHOLDER|nginxdemos/hello:plain-text|; s|containerPort: 3000|containerPort: 80|' \
  k8s/deployment.yaml | kubectl apply -f -

kubectl -n school get pods                   # 2 pods, names like school-api-xxxxx

# ЁЯШИ Now be the chaos: delete one pod...
kubectl -n school delete pod -l app=school-api --field-selector=status.phase=Running --wait=false
kubectl -n school get pods -w                # ...watch the monitor replace it in seconds!  Ctrl+C to stop

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

kubectl get deploy ┬╖ kubectl get rs ┬╖ kubectl scale ┬╖ kubectl rollout status

ЁЯФЧ рдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд: ЁЯкк AWS L12 (ASG рдореНрд╣рдгрдЬреЗ 'computers рд╕рд╛рдареАрдЪрд╛ Deployment')

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

рджреЛрдирдкреИрдХреА рдПрдХрд╛рд╡рд░ kubectl delete pod тЖТ рдХрд╛рд╣реА рд╕реЗрдХрдВрджрд╛рдВрдд kubectl get pods рдордзреНрдпреЗ NEW pod рдЪреЗ рдирд╛рд╡ рдЖрдгрд┐ рдкреБрдиреНрд╣рд╛ 2/2 рджрд┐рд╕рддреЗ тАФ reconciliation рдкреНрд░рддреНрдпрдХреНрд╖ рдХрд╛рдо рдХрд░рддрд╛рдирд╛.

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

local cluster: kubectl delete -f k8s/ (рдХрд┐рдВрд╡рд╛ рддреБрдореНрд╣реА apply рдХреЗрд▓реЗрд▓реА file) тАФ EKS рд╡рд░ рдЪрд╛рд▓реВ рд░рд╛рд╣рд┐рд▓реЗрд▓реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдЧреЛрд╖реНрдЯреАрдЪреЗ рддрд╛рд╕рд╛рдкреНрд░рдорд╛рдгреЗ рдмрд┐рд▓ рд▓рд╛рдЧрддреЗ

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

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

рдЖрддрд╛ pods рд╕реНрд╡рддрдГрд╣реВрди рдмрд░реЗ рд╣реЛрддрд╛рдд тАФ рдкрдг рддреНрдпрд╛рдВрдЪреА рдирд╛рд╡реЗ рдЖрдгрд┐ IPs рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА рдмрджрд▓рддрд╛рдд. рдордЧ рдХреЛрдгреА рддреНрдпрд╛рдВрдирд╛ рдЦрд╛рддреНрд░реАрдиреЗ рд╢реЛрдзрд╛рдпрдЪреЗ рдХрд╕реЗ? Service тАФ рд╢рд╛рд│реЗрдЪреЗ рд╕реНрд╡рд╛рдЧрдд-рдХрдХреНрд╖ (reception).

git checkout lesson-04-services

ЁЯзСтАНЁЯПл Lesson 03 тАФ Deployments: the strict class monitor

ЁЯУН You are here: Lesson 03 of 13 ┬╖ Previous: lesson-02-pods ┬╖ Next: lesson-04-services


ЁЯУж What's in this branch

Lessons 01тАУ02, plus: the Deployment тАФ the object that keeps your pods alive, in the right number, running the right version. Real files:

ЁЯзТ Explain like I'm 5

The teacher tells the class monitor: "There must ALWAYS be 2 kids watering the plants. Always. I don't care how." ЁЯзСтАНЁЯПлЁЯМ▒

The monitor takes this seriously:

That's a Deployment. You don't tell Kubernetes what to do тАФ you tell it what the world should look like ("2 copies of school-api, version v5"), and the monitor works forever to keep reality matching your wish. This is the single biggest idea in Kubernetes: desired state. You declare; it reconciles.

ЁЯЧ║я╕П Diagram

flowchart TB
    Y["ЁЯзСтАНЁЯПл You declare:<br/>replicas: 2, image: v5"]
    D["Deployment<br/>school-api"]
    RS["ReplicaSet - the monitor<br/>keeps count = 2"]
    P1["ЁЯкС Pod school-api-abc12"]
    P2["ЁЯкС Pod school-api-def34"]
    P3["ЁЯкС Pod school-api-xyz99<br/>auto-created replacement"]
    Y --> D --> RS
    RS --> P1
    RS --> P2
    P1 -. "ЁЯТе crashes" .-> P3
    RS -- "notices 1 missing,<br/>creates a new one" --> P3

тЭУ What

ЁЯза Desired state тЖТ reconciliation тЖТ actual state

Desired state        replicas: 2          (what you wrote in git)
        тЖУ
Kubernetes continuously compares          (the controller loop, every few seconds, forever)
        тЖУ
Actual state         1 Pod                (one just crashed)
        тЖУ
creates another Pod
        тЖУ
Actual state = Desired state   2 Pods тЬЕ

Kubernetes is a reconciliation system. You never tell it what to do тАФ you tell it how things should be, and controllers close the gap, forever. This one loop explains Deployments, ReplicaSets, HPA (L09), Jobs (L18), StatefulSets (L22), operators (L25) and ArgoCD (L14) тАФ same loop, new hat.

ЁЯдФ Why

Lesson 02 ended with a dead pod staying dead. Real apps must self-heal at 3 AM without you. The Deployment is why Kubernetes people sleep well: a crashed pod, a rebooted node, a killed container тАФ the monitor replaces them all, because your YAML said "there shall be 2". It also unlocks zero-downtime upgrades (lesson 11) by swapping pods one at a time.

ЁЯФз How (in this repo)

Open k8s/deployment.yaml:

spec:
  replicas: 2                 # тЖР the promise: ALWAYS 2 desks
  selector:
    matchLabels:
      app: school-api         # тЖР "my pods wear this sticker"
  template:                   # тЖР lesson 02's pod blueprint
    metadata:
      labels:
        app: school-api       # тЖР the sticker itself (must match!)

Note image: IMAGE_PLACEHOLDER тАФ CircleCI stamps in the real ECR image tag at deploy time (see .circleci/config.yml).

ЁЯзк Try it

kubectl apply -f k8s/namespace.yaml          # the room first (lesson 05 explains)
kubectl apply -f k8s/configmap.yaml          # config (lesson 06 explains)

# For local play, use a public image instead of IMAGE_PLACEHOLDER:
sed 's|IMAGE_PLACEHOLDER|nginxdemos/hello:plain-text|; s|containerPort: 3000|containerPort: 80|' \
  k8s/deployment.yaml | kubectl apply -f -

kubectl -n school get pods                   # 2 pods, names like school-api-xxxxx

# ЁЯШИ Now be the chaos: delete one pod...
kubectl -n school delete pod -l app=school-api --field-selector=status.phase=Running --wait=false
kubectl -n school get pods -w                # ...watch the monitor replace it in seconds!  Ctrl+C to stop

ЁЯФз kubectl for this lesson

kubectl get deploy ┬╖ kubectl get rs ┬╖ kubectl scale ┬╖ kubectl rollout status

ЁЯФЧ Builds on: ЁЯкк AWS L12 (an ASG is 'a Deployment for computers')

тЬЕ Verify тАФ what you should see

kubectl delete pod one of the two тЖТ within seconds kubectl get pods shows a NEW pod name and 2/2 again тАФ reconciliation in action.

ЁЯз╣ Clean up

local cluster: kubectl delete -f k8s/ (or the file you applied) тАФ on EKS, anything left running bills by the hour

тЪая╕П Common mistakes

тПня╕П Next

Pods now heal themselves тАФ but their names and IPs change every time. How does anyone find them reliably? The Service тАФ the school reception desk.

git checkout lesson-04-services
тЖР PreviouspodsNext тЖТservices

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