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

ЁЯУЪ рдзрдбрд╛ 12 тАФ Storage рдЖрдгрд┐ state: рджрдкреНрддрд░ рд╡рд┐рд░реБрджреНрдз рдЧреНрд░рдВрдерд╛рд▓рдпрд╛рдЪреЗ рдХрдкрд╛рдЯ

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 13 рдкреИрдХреА рдзрдбрд╛ 12 ┬╖ рдорд╛рдЧрдЪрд╛: lesson-11-rollouts ┬╖ рдкреБрдврдЪрд╛: lesson-13-under-the-hood


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

рдзрдбреЗ 01тАУ11, рдЖрдгрд┐: storage тАФ pod рдореЗрд▓реНрдпрд╛рд╡рд░ рдХрд╛рдп рдЯрд┐рдХрддреЗ рдЖрдгрд┐ рдХрд╛рдп рдирд╛рд╣реА, рдЖрдгрд┐ "рдорд╛рдЭрд╛ database рдХреБрдареЗ рд░рд╛рд╣рд╛рд╡рд╛?" рдпрд╛рдЪреЗ рдкреНрд░рд╛рдорд╛рдгрд┐рдХ рдЙрддреНрддрд░. рдЦрд▒реНрдпрд╛ files:

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

рдПрдЦрд╛рджреЗ рдореВрд▓ рдХрд╛рдпрдордЪреЗ рд╢рд╛рд│рд╛ рд╕реЛрдбреВрди рдЬрд╛рддреЗ, рддреЗрд╡реНрд╣рд╛ рджреЛрди рдкреНрд░рдХрд╛рд░рдЪреНрдпрд╛ рд╡рд╕реНрддреВ рдЕрд╕рддрд╛рдд:

Pod рд▓рд╛ рдХрдкрд╛рдЯрд╛рдд рдЬрд╛рдЧрд╛ рдХрд╢реА рдорд┐рд│рддреЗ? рддреЛ рдПрдХ рдорд╛рдЧрдгреА-рдкрд╛рд╡рддреА рднрд░рддреЛ: "рдорд▓рд╛ 10Gi рдХрдкрд╛рдЯ рд╣рд╡реЗ рдЖрд╣реЗ, рдХреГрдкрдпрд╛" тАФ рд╣рд╛рдЪ PersistentVolumeClaim (PVC). рдЧреНрд░рдВрдердкрд╛рд▓ (рдПрдХ StorageClass + CSI driver тАФ AWS рд╡рд░, рдПрдХ EBS disk) рдЦрд░реЗ рдХрдкрд╛рдЯ рд╢реЛрдзрддреЗ рдХрд┐рдВрд╡рд╛ рдмрдирд╡рддреЗ рдЖрдгрд┐ рддреЗ pod рд▓рд╛ рдЬреЛрдбрддреЗ. рдирдВрддрд░ рдирд╡рд╛ pod? рддреАрдЪ рдкрд╛рд╡рддреА тЖТ рддреЗрдЪ рдХрдкрд╛рдЯ, рддреАрдЪ рдкреБрд╕реНрддрдХреЗ.

рдЖрдгрд┐ рдореБрд▓рд╛рдВрдЪреЗ рд╕рд░реНрд╡рд╛рдд рдореЛрдареЗ рдЧреБрдкрд┐рдд ЁЯдл: рдХрдзреА рдХрдзреА рд╕рд░реНрд╡рд╛рдд рдЪрд╛рдВрдЧрд▓реЗ рдЧреНрд░рдВрдерд╛рд▓рдп рд░рд╕реНрддреНрдпрд╛рдЪреНрдпрд╛ рдкрд▓реАрдХрдбреЗ рдЕрд╕рддреЗ. рд╣рд╛ repo cluster рдЪреНрдпрд╛ рдЖрдд Postgres рдЪрд╛рд▓рд╡рдгреНрдпрд╛рдРрд╡рдЬреА рддреНрдпрд╛рдЪрд╛ database RDS рдордзреНрдпреЗ рдареЗрд╡рддреЛ тАФ AWS рдЪреЗ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХрдкрдгреЗ рдЪрд╛рд▓рд╡рд▓реЗрд▓реЗ рдЧреНрд░рдВрдерд╛рд▓рдп. рджреЛрдиреНрд╣реА рдпреЛрдЧреНрдп рдЖрд╣реЗрдд; рдХрдзреА рдХреЛрдгрддреЗ рдирд┐рд╡рдбрд╛рдпрдЪреЗ рд╣реЗ рдЬрд╛рдгрдгреЗ рд╣рд╛рдЪ рдЦрд░рд╛ рдзрдбрд╛.

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

flowchart TB
    subgraph cluster["ЁЯПл Kubernetes cluster"]
        pod1["ЁЯкС postgres pod v1<br/>ЁЯТе dies"]
        pod2["ЁЯкС postgres pod v2<br/>new desk, same books"]
        pvc["ЁЯУЭ PVC: 'I claim 10Gi'"]
        pod1 -.-> pvc
        pod2 --> pvc
    end
    pv["ЁЯУЪ PersistentVolume<br/>= real EBS disk on AWS<br/>outlives every pod"]
    pvc --> pv
    subgraph outside["ЁЯПЫя╕П across the street - what THIS repo does"]
        rds["AWS RDS Postgres<br/>backups, patching, failover<br/>managed by AWS"]
    end
    api["ЁЯкС school-api pods"] -->|"DATABASE_URL from the Secret<br/>lesson 06"| rds

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

ЁЯдФ рдХрд╛

рдзрдбреЗ 01тАУ11 рдордзрд▓реЗ рд╕рдЧрд│реЗ рдЪрд╛рд▓рд▓реЗ рдХрд╛рд░рдг pods рдЯрд╛рдХрд╛рдК рд╣реЛрддреЗ тАФ рддреНрдпрд╛рдВрдирд╛ рдорд╛рд░рд╛, рд╣рд▓рд╡рд╛, рд╡рд╛рдврд╡рд╛. Databases рд╣реА рдЬрд╛рджреВ рдореЛрдбрддрд╛рдд: data рдЯрд╛рдХрд╛рдК рдЕрд╕рддрд╛ рдХрд╛рдорд╛ рдирдпреЗ. PV/PVC рдЬреАрд╡рдирдЪрдХреНрд░ рд╡рд┐рднрд╛рдЧреВрди рд╣реА рдЬрд╛рджреВ рдкрд░рдд рдЖрдгрддрд╛рдд: pods cattle рд░рд╛рд╣рддрд╛рдд, storage pet рдмрдирддреЗ. рдкрдг production database рдиреАрдЯ рдЪрд╛рд▓рд╡рдгреЗ (backups, upgrades, failover, tuning) рд╣реЗ рдкреВрд░реНрдгрд╡реЗрд│рдЪреЗ рдХрд╛рдо рдЖрд╣реЗ тАФ рдореНрд╣рдгреВрдирдЪ рд▓рд╣рд╛рди teams рд╕рд╣рд╕рд╛ рдЧреНрд░рдВрдердкрд╛рд▓рдЪ рднрд╛рдбреНрдпрд╛рдиреЗ рдШреЗрддрд╛рдд (RDS) рдЖрдгрд┐ cluster stateless рдареЗрд╡рддрд╛рдд. рдЕрдиреБрднрд╡рд╛рдЪрд╛ рдирд┐рдпрдо: cluster рдордзреНрдпреЗ stateless, state managed services рдордзреНрдпреЗ тАФ рдЕрдЧрджреА рдпрд╛ repo рдЪрд╛ рдЖрдХрд╛рд░.

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

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

# Feel the difference between backpack and shelf (local cluster):
kubectl -n school apply -f - <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: shelf }
spec:
  accessModes: [ReadWriteOnce]
  resources: { requests: { storage: 1Gi } }
EOF
kubectl -n school run scribe --restart=Never --image=busybox \
  --overrides='{"spec":{"containers":[{"name":"scribe","image":"busybox",
    "command":["sh","-c","echo my homework > /shelf/notes.txt; sleep 3600"],
    "volumeMounts":[{"name":"s","mountPath":"/shelf"}]}],
    "volumes":[{"name":"s","persistentVolumeClaim":{"claimName":"shelf"}}]}}'

kubectl -n school delete pod scribe          # kid leaves school ЁЯТе
# New kid, same claim тАФ the homework is still there:
kubectl -n school run scribe2 --restart=Never --image=busybox \
  --overrides='{"spec":{"containers":[{"name":"scribe2","image":"busybox",
    "command":["sh","-c","cat /shelf/notes.txt; sleep 60"],
    "volumeMounts":[{"name":"s","mountPath":"/shelf"}]}],
    "volumes":[{"name":"s","persistentVolumeClaim":{"claimName":"shelf"}}]}}'
kubectl -n school logs scribe2               # тЖТ "my homework" ЁЯОЙ
kubectl -n school delete pod scribe2 && kubectl -n school delete pvc shelf

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

kubectl get pv,pvc ┬╖ kubectl describe pvc

ЁЯФЧ рдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд: ЁЯкк AWS L11 (EBS) ┬╖ L14 (S3) ┬╖ L17 (RDS)

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

postgres pod рдорд╛рд░рд╛ тЖТ рдирд╡реНрдпрд╛ pod рд▓рд╛ рддреНрдпрд╛рдЪ PVC рд╡рд░ рддреНрдпрд╛рдЪ rows рд╕рд╛рдкрдбрддрд╛рдд.

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

data рдирд╛рд╣реАрд╕рд╛ рдХрд░рд╛рдпрдЪрд╛ рдЕрд╕реЗрд▓ рддрд░ kubectl delete pvc (PVC рдореБрджреНрджрд╛рдо pod рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдЯрд┐рдХрддреЛ)

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

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

рд╢реЗрд╡рдЯрдЪрд╛ рдзрдбрд╛: рд╢рд╛рд│реЗрдЪреНрдпрд╛ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдЪреЗ рджрд╛рд░ рдЙрдШрдбрд╛ рдЖрдгрд┐ рд╣реЗ рд╕рдЧрд│реЗ рдШрдбрд╡реВрди рдЖрдгрдгрд╛рд▒реНрдпрд╛ рдпрдВрддреНрд░рдгреЗрд▓рд╛ рднреЗрдЯрд╛ тАФ control plane.

git checkout lesson-13-under-the-hood

ЁЯУЪ Lesson 12 тАФ Storage & state: backpack vs library shelf

ЁЯУН You are here: Lesson 12 of 13 ┬╖ Previous: lesson-11-rollouts ┬╖ Next: lesson-13-under-the-hood


ЁЯУж What's in this branch

Lessons 01тАУ11, plus: storage тАФ what survives a pod's death and what doesn't, and the honest answer to "where should my database live?" Real files:

ЁЯзТ Explain like I'm 5

When a kid leaves school for good, two kinds of stuff exist:

How does a pod get shelf space? It files a request slip: "I need 10Gi of shelf, please" тАФ that's a PersistentVolumeClaim (PVC). The librarian (a StorageClass + CSI driver тАФ on AWS, an EBS disk) finds or creates a real shelf and clips it to the pod. New pod later? Same slip тЖТ same shelf, same books.

And the biggest kid secret ЁЯдл: sometimes the best library is across the street. This repo keeps its database in RDS тАФ AWS's professionally-run library тАФ instead of running Postgres inside the cluster. Both are valid; knowing when to choose which is the real lesson.

ЁЯЧ║я╕П Diagram

flowchart TB
    subgraph cluster["ЁЯПл Kubernetes cluster"]
        pod1["ЁЯкС postgres pod v1<br/>ЁЯТе dies"]
        pod2["ЁЯкС postgres pod v2<br/>new desk, same books"]
        pvc["ЁЯУЭ PVC: 'I claim 10Gi'"]
        pod1 -.-> pvc
        pod2 --> pvc
    end
    pv["ЁЯУЪ PersistentVolume<br/>= real EBS disk on AWS<br/>outlives every pod"]
    pvc --> pv
    subgraph outside["ЁЯПЫя╕П across the street - what THIS repo does"]
        rds["AWS RDS Postgres<br/>backups, patching, failover<br/>managed by AWS"]
    end
    api["ЁЯкС school-api pods"] -->|"DATABASE_URL from the Secret<br/>lesson 06"| rds

тЭУ What

ЁЯдФ Why

Everything in lessons 01тАУ11 worked because pods were disposable тАФ kill them, move them, multiply them. Databases break that spell: data must NOT be disposable. PV/PVC restores the spell by splitting the lifecycle: pods stay cattle, storage becomes the pet. But running a production database well (backups, upgrades, failover, tuning) is a full-time job тАФ which is why small teams usually rent the librarian (RDS) and keep the cluster stateless. Rule of thumb: stateless in the cluster, state in managed services тАФ exactly this repo's shape.

ЁЯФз How (in this repo)

ЁЯзк Try it

# Feel the difference between backpack and shelf (local cluster):
kubectl -n school apply -f - <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: shelf }
spec:
  accessModes: [ReadWriteOnce]
  resources: { requests: { storage: 1Gi } }
EOF
kubectl -n school run scribe --restart=Never --image=busybox \
  --overrides='{"spec":{"containers":[{"name":"scribe","image":"busybox",
    "command":["sh","-c","echo my homework > /shelf/notes.txt; sleep 3600"],
    "volumeMounts":[{"name":"s","mountPath":"/shelf"}]}],
    "volumes":[{"name":"s","persistentVolumeClaim":{"claimName":"shelf"}}]}}'

kubectl -n school delete pod scribe          # kid leaves school ЁЯТе
# New kid, same claim тАФ the homework is still there:
kubectl -n school run scribe2 --restart=Never --image=busybox \
  --overrides='{"spec":{"containers":[{"name":"scribe2","image":"busybox",
    "command":["sh","-c","cat /shelf/notes.txt; sleep 60"],
    "volumeMounts":[{"name":"s","mountPath":"/shelf"}]}],
    "volumes":[{"name":"s","persistentVolumeClaim":{"claimName":"shelf"}}]}}'
kubectl -n school logs scribe2               # тЖТ "my homework" ЁЯОЙ
kubectl -n school delete pod scribe2 && kubectl -n school delete pvc shelf

ЁЯФз kubectl for this lesson

kubectl get pv,pvc ┬╖ kubectl describe pvc

ЁЯФЧ Builds on: ЁЯкк AWS L11 (EBS) ┬╖ L14 (S3) ┬╖ L17 (RDS)

тЬЕ Verify тАФ what you should see

kill the postgres pod тЖТ the new pod finds the same rows on the same PVC.

ЁЯз╣ Clean up

kubectl delete pvc if you want the data gone (a PVC outlives the pod on purpose)

тЪая╕П Common mistakes

тПня╕П Next

Final lesson: open the school office door and meet the machinery that made ALL of this happen тАФ the control plane.

git checkout lesson-13-under-the-hood
тЖР PreviousrolloutsNext тЖТunder the hood

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