ЁЯПл The SchoolтА║тШ╕я╕П KubernetesтА║ЁЯП╖я╕П рдзрдбрд╛ 22 тАФ StatefulSets: рдирд╛рд╡рд╛рдЪреНрдпрд╛ рдкрд╛рдЯреНрдпрд╛ рдЕрд╕рд▓реЗрд▓реЗ рдмрд╛рдХ
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯП╖я╕П рдзрдбрд╛ 22 тАФ StatefulSets: рдирд╛рд╡рд╛рдЪреНрдпрд╛ рдкрд╛рдЯреНрдпрд╛ рдЕрд╕рд▓реЗрд▓реЗ рдмрд╛рдХ

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: рдзрдбрд╛ 22 / 26 ┬╖ рдорд╛рдЧреАрд▓: lesson-21-daemonsets ┬╖ рдкреБрдвреАрд▓: lesson-23-qos-evictions


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

рдЖрдзреАрдЪреЗ рд╕рдЧрд│реЗ, рдЖрдгрд┐ рдзрдбрд╛ 12 рдиреЗ рдлрдХреНрдд рджреБрд░реВрдирдЪ рджрд╛рдЦрд╡рд▓реЗрд▓рд╛ workload рдЖрдХрд╛рд░ тАФ рдЖрддрд╛ рдкреНрд░рддреНрдпрдХреНрд╖ рд╣рд╛рддрд╛рдиреЗ. рдЦрд░реА file:

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

Deployment рдЪреА рдореБрд▓реЗ рдПрдХрдореЗрдХрд╛рдВрдЪреНрдпрд╛ рдЬрд╛рдЧреА рдЪрд╛рд▓рдгрд╛рд░реА рдЕрд╕рддрд╛рдд тАФ рдирд╡реЗ рдореВрд▓, рдирд╡реЗ random рдирд╛рд╡ (school-api-7d9f8-xk2lp), рдХреЛрдгрддрд╛рд╣реА рдмрд╛рдХ, рд╕рд╛рдорд╛рдпрд┐рдХ reception рдирдВрдмрд░. Stateless рдХрд╛рдорд╛рд╕рд╛рдареА рдЙрддреНрддрдо; database рд╕рд╛рдареА рдирд┐рд░реБрдкрдпреЛрдЧреА. Database рдореБрд▓рд╛рд▓рд╛ рд╣рд╡реЗ:

  1. рдирд╛рд╡рд╛рдЪреА рдкрд╛рдЯреА ЁЯП╖я╕П: postgres-0. рдореЗрд▓реЗ? рддреНрдпрд╛рдЪреНрдпрд╛ рдЬрд╛рдЧреА рдпреЗрдгрд╛рд░реЗрд╣реА postgres-0 тАФ рддреЗрдЪ рдирд╛рд╡, рддреАрдЪ рдУрд│рдЦ, рдереЗрдЯ postgres-0.postgres рдпрд╛ рдкрддреНрддреНрдпрд╛рд╡рд░ рдкреЛрд╣реЛрдЪрддрд╛ рдпреЗрддреЗ (headless Service рдордзреВрди тАФ "рдЬреЛ рдореЛрдХрд│рд╛ рдЕрд╕реЗрд▓ рддреЛ" рдРрд╡рдЬреА рддреБрдореНрд╣рд╛рд▓рд╛ рдард░рд╛рд╡реАрдХ рдореБрд▓рд╛рдХрдбреЗ рдЬреЛрдбреВрди рджреЗрдгрд╛рд░реЗ reception).
  2. рд╕реНрд╡рддрдГрдЪрд╛ drawer ЁЯЧДя╕П: volumeClaimTemplates рдкреНрд░рддреНрдпреЗрдХ pod рд╕рд╛рдареА рд╡реИрдпрдХреНрддрд┐рдХ PVC рдмрдирд╡рддреЗ тАФ postgres-0 рдиреЗрд╣рдореА рд╕реНрд╡рддрдГрдЪрд╛рдЪ drawer рдЙрдШрдбрддреЛ (рдзрдбрд╛ 12 рдЪреА рдЧреНрд░рдВрдерд╛рд▓рдпрд╛рддрд▓реА рдлрд│реА, рдЖрддрд╛ рдореБрд▓рд╛рдЪреЗ рдирд╛рд╡ рдХреЛрд░рд▓реЗрд▓реА). Pod delete рдХреЗрд▓реНрдпрд╛рдиреЗ drawer рдХрдзреАрдЪ delete рд╣реЛрдд рдирд╛рд╣реА.
  3. рдХреНрд░рдо ЁЯУ╢: рдореБрд▓реЗ рдПрдХреЗрдХ рдХрд░реВрди рдпреЗрддрд╛рдд (-0, рдордЧ -1, рдордЧ -2) рдЖрдгрд┐ рдЙрд▓рдЯреНрдпрд╛ рдХреНрд░рдорд╛рдиреЗ рдЬрд╛рддрд╛рдд тАФ replicated databases рдирд╛ followers рддреНрдпрд╛рдЪреНрдпрд╛рдХрдбреВрди copy рдХрд░рдгреНрдпрд╛рдЖрдзреА рдкрд╣рд┐рд▓реЗ рдореВрд▓ рддрдпрд╛рд░ рдЕрд╕рд╛рдпрд▓рд╛ рд▓рд╛рдЧрддреЗ.

рд╣реА рддрд┐рдХрдбреА тАФ рдЪрд┐рдХрдЯрд▓реЗрд▓реЗ рдирд╛рд╡, рдЪрд┐рдХрдЯрд▓реЗрд▓рд╛ drawer, рдХреНрд░рдорд╛рдиреЗ рдпреЗрдгреЗ тАФ рд╣рд╛рдЪ StatefulSet рдЖрдгрд┐ Deployment рдпрд╛рдВрдордзрд▓рд╛ рд╕рдВрдкреВрд░реНрдг рдлрд░рдХ.

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

flowchart LR
    ss["ЁЯП╖я╕П StatefulSet: postgres<br/>replicas: 1"]
    hs["тШОя╕П headless Service<br/>'connect me to postgres-0<br/>SPECIFICALLY'"]
    subgraph pod0["ЁЯкС postgres-0 - named desk"]
        pg["postgres:16"]
    end
    pvc["ЁЯЧДя╕П PVC: data-postgres-0<br/>ITS OWN drawer -<br/>survives the pod, reattaches"]
    ss -->|"1 ordered, named"| pod0
    hs -->|"2 by-name address"| pod0
    pod0 ---|"3 always reopens"| pvc

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

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг "database cluster рдордзреНрдпреЗ рдЪрд╛рд▓рд╡реВ рд╢рдХрддреЛ рдХрд╛?" рд╣рд╛ рдкреНрд░рд╢реНрди рдкреНрд░рддреНрдпреЗрдХ team рдордзреНрдпреЗ рд╡рд┐рдЪрд╛рд░рд▓рд╛ рдЬрд╛рддреЛ, рдЖрдгрд┐ рдЖрддрд╛ рддреБрдореНрд╣реА рдиреЗрдордХреЗ рдЙрддреНрддрд░ рджреЗрдК рд╢рдХрддрд╛: k8s рддреБрдореНрд╣рд╛рд▓рд╛ рд╣реЗ рджреЗрддреЛ (рдУрд│рдЦ, storage, рдХреНрд░рдо), рд╣реЗ рджреЗрдд рдирд╛рд╣реА (replication, failover, backups тАФ operator рдЪреЗ рдХрд┐рдВрд╡рд╛ RDS рдЪреЗ рдХрд╛рдо), рдЖрдгрд┐ рдзрдбрд╛ 12 рдиреЗ RDS рдХрд╛ рдирд┐рд╡рдбрд▓рд╛ рддреЗ рд╣реЗ. рдпрдВрддреНрд░рдгрд╛ рдорд╛рд╣реАрдд рдЕрд╕рд▓реНрдпрд╛рдореБрд│реЗрдЪ "рднрд╛рдбреНрдпрд╛рдиреЗ рдШреНрдпрд╛" рд╣рд╛ рд╕рд▓реНрд▓рд╛ рд╡рд┐рд╢реНрд╡рд╛рд╕рд╛рд░реНрд╣ рдард░рддреЛ.

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

kubectl apply -f k8s/postgres-statefulset.yaml
kubectl -n school get pods -w                    # postgres-0 тАФ THE name; Ctrl+C
kubectl -n school get pvc                        # data-postgres-0 тАФ THE drawer

# write something, then kill the kid:
kubectl -n school exec postgres-0 -- psql -U school -c "CREATE TABLE proof(id int); INSERT INTO proof VALUES (42);"
kubectl -n school delete pod postgres-0          # ЁЯТе
kubectl -n school get pods -w                    # postgres-0 returns (same name!); Ctrl+C

# same drawer, data intact:
kubectl -n school exec postgres-0 -- psql -U school -c "SELECT * FROM proof;"   # 42 ЁЯОЙ

# cleanup (drawer is kept on purpose тАФ delete it explicitly):
kubectl delete -f k8s/postgres-statefulset.yaml
kubectl -n school delete pvc data-postgres-0

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

kubectl get sts,pvc ┬╖ kubectl get pods -l app=postgres

ЁЯФЧ рдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд: ЁЯкк AWS L17 (RDS тАФ рддреНрдпрд╛рдРрд╡рдЬреА рдиреЛрдВрджреАрдВрдЪреЗ рдХрд╛рд░реНрдпрд╛рд▓рдп рднрд╛рдбреНрдпрд╛рдиреЗ рдШреНрдпрд╛)

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

postgres-0 delete рдХрд░рд╛ тЖТ рддреНрдпрд╛рдЪреНрдпрд╛ рдЬрд╛рдЧреА рдпреЗрдгрд╛рд▒реНрдпрд╛рдЪреЗ рдирд╛рд╡ рдкреБрдиреНрд╣рд╛ postgres-0 рдЕрд╕рддреЗ рдЖрдгрд┐ рддреЛ rows рд╢рд╛рдмреВрдд рдЕрд╕рд▓реЗрд▓рд╛ data-postgres-0 рдкреБрдиреНрд╣рд╛ рдЬреЛрдбрддреЛ.

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

kubectl delete sts postgres PVCs рдареЗрд╡рддреЛ тАФ data рдХрд╛рдвреВрди рдЯрд╛рдХрд╛рдпрдЪрд╛ рдЕрд╕реЗрд▓ рддрд░ рддреЗ рд╕реНрдкрд╖реНрдЯрдкрдгреЗ delete рдХрд░рд╛

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

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

рдмрд╛рдХрд╛рд╡рд░рдЪреЗ рдЬреЗрд╡рдг рд╕рдВрдкрд▓реЗ рддрд░ рдЖрдзреА рдХреЛрдгрд╛рд▓рд╛ рдмрд╛рд╣реЗрд░ рдЬрд╛рдпрд▓рд╛ рд╕рд╛рдВрдЧрд┐рддрд▓реЗ рдЬрд╛рддреЗ? QoS classes рдЖрдгрд┐ evictions тАФ рдирдХрд│рдд рддреБрдореНрд╣реА рдЖрдзреАрдЪ рдЬреНрдпрд╛ рдЙрддрд░рдВрдбреАрдд рдЖрд╣рд╛рдд рддреА.

git checkout lesson-23-qos-evictions

ЁЯП╖я╕П Lesson 22 тАФ StatefulSets: desks with name plates

ЁЯУН You are here: Lesson 22 of 26 ┬╖ Previous: lesson-21-daemonsets ┬╖ Next: lesson-23-qos-evictions


ЁЯУж What's in this branch

Everything before, plus the workload shape lesson 12 only waved at тАФ now hands-on. Real file:

ЁЯзТ Explain like I'm 5

Deployment kids are interchangeable тАФ new kid, new random name (school-api-7d9f8-xk2lp), any desk, shared reception number. Perfect for stateless work; useless for a database. A database kid needs:

  1. A name plate ЁЯП╖я╕П: postgres-0. Dies? The replacement is also postgres-0 тАФ same name, same identity, addressable directly as postgres-0.postgres (via a headless Service тАФ reception that transfers you to a SPECIFIC kid instead of "whoever's free").
  2. Their own drawer ЁЯЧДя╕П: volumeClaimTemplates mints a personal PVC per pod тАФ postgres-0 always reopens its own drawer (lesson 12's library shelf, now with the kid's name engraved). Deleting the pod never deletes the drawer.
  3. Order ЁЯУ╢: kids arrive one at a time (-0, then -1, then -2) and leave in reverse тАФ replicated databases need the firstborn ready before the followers copy from it.

That trio тАФ sticky name, sticky drawer, ordered arrival тАФ is the entire difference between a StatefulSet and a Deployment.

ЁЯЧ║я╕П Diagram

flowchart LR
    ss["ЁЯП╖я╕П StatefulSet: postgres<br/>replicas: 1"]
    hs["тШОя╕П headless Service<br/>'connect me to postgres-0<br/>SPECIFICALLY'"]
    subgraph pod0["ЁЯкС postgres-0 - named desk"]
        pg["postgres:16"]
    end
    pvc["ЁЯЧДя╕П PVC: data-postgres-0<br/>ITS OWN drawer -<br/>survives the pod, reattaches"]
    ss -->|"1 ordered, named"| pod0
    hs -->|"2 by-name address"| pod0
    pod0 ---|"3 always reopens"| pvc

тЭУ What

ЁЯдФ Why

Because "can we run the database in the cluster?" is asked in every team, and now you can answer precisely: here's what k8s gives you (identity, storage, order), here's what it doesn't (replication, failover, backups тАФ the operator's or RDS's job), and here's why lesson 12 chose RDS. Knowing the machinery is what makes the "rent it" advice credible.

ЁЯзк Try it

kubectl apply -f k8s/postgres-statefulset.yaml
kubectl -n school get pods -w                    # postgres-0 тАФ THE name; Ctrl+C
kubectl -n school get pvc                        # data-postgres-0 тАФ THE drawer

# write something, then kill the kid:
kubectl -n school exec postgres-0 -- psql -U school -c "CREATE TABLE proof(id int); INSERT INTO proof VALUES (42);"
kubectl -n school delete pod postgres-0          # ЁЯТе
kubectl -n school get pods -w                    # postgres-0 returns (same name!); Ctrl+C

# same drawer, data intact:
kubectl -n school exec postgres-0 -- psql -U school -c "SELECT * FROM proof;"   # 42 ЁЯОЙ

# cleanup (drawer is kept on purpose тАФ delete it explicitly):
kubectl delete -f k8s/postgres-statefulset.yaml
kubectl -n school delete pvc data-postgres-0

ЁЯФз kubectl for this lesson

kubectl get sts,pvc ┬╖ kubectl get pods -l app=postgres

ЁЯФЧ Builds on: ЁЯкк AWS L17 (RDS тАФ rent the record office instead)

тЬЕ Verify тАФ what you should see

delete postgres-0 тЖТ the replacement is named postgres-0 again and reattaches data-postgres-0 with the rows intact.

ЁЯз╣ Clean up

kubectl delete sts postgres keeps the PVCs тАФ delete them explicitly if you want the data gone

тЪая╕П Common mistakes

тПня╕П Next

When a desk runs out of lunch, who gets asked to leave first? QoS classes & evictions тАФ the pecking order you're already in without knowing it.

git checkout lesson-23-qos-evictions
тЖР PreviousdaemonsetsNext тЖТqos evictions

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