Handbooks / Kubernetes / Chapter 4
Storage
6 pages · ~4 min✓ Reviewed
Builds on ConfigMaps and Secrets. Next up: Scaling and Health.
Volumes, PersistentVolumes and Claims
1. Volumes, PV and PVC
- Volume outlives container restarts, not the Pod
emptyDir: dies with the PodhostPath: node path; avoid in production- PV: cluster-scoped storage
- PVC: namespaced request
- PVC binds 1:1 to a PV matching size,
accessModes,storageClassName
2. Access Modes
| Mode | Mounts |
|---|---|
RWO ReadWriteOnce | read-write, one node |
ROX ReadOnlyMany | read-only, many nodes |
RWX ReadWriteMany | read-write, many nodes |
RWOP ReadWriteOncePod | one Pod only |
3. Example: 1Gi Claim
- Pod mounts the claim via
claimNameplusvolumeMounts
yaml
kind: PersistentVolumeClaim
metadata: {name: data}
spec:
accessModes: [ReadWriteOnce]
resources:
requests: {storage: 1Gi}the claim
yaml
volumes:
- name: d
persistentVolumeClaim:
claimName: data
# in the container:
volumeMounts: [{name: d, mountPath: /data}]the Pod
4. Gotchas
- PVC
Pending: no matching PV or StorageClass DeletereclaimPolicy wipes data with the PVCRetain: PV goesReleased, no rebind untilclaimRefcleared
StorageClasses and Dynamic Provisioning
1. What a StorageClass Holds
- PVC with
storageClassNamecreates its PV automatically - Default class: annotation
storageclass.kubernetes.io/is-default-class: "true" storageClassName: ""turns dynamic provisioning off
yaml
kind: StorageClass
metadata: {name: fast}
provisioner: ebs.csi.aws.com
parameters: {type: gp3}
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: truenames a provisioner, then holds its settings
2. Binding and Provisioning
| Mode | Binds when | Effect |
|---|---|---|
Immediate | PVC created | zone mismatch risk |
WaitForFirstConsumer | Pod scheduled | PV matches Pod's zone |
| Static | Dynamic | |
|---|---|---|
| PV made by | Admin, by hand | Class, on demand |
| Needs class | No | Yes |
- Expand: raise PVC
requests.storage, never lower - Needs
allowVolumeExpansion: true
3. Gotchas
- Dynamic PVs default to reclaimPolicy Delete
storageClassNamecannot change on an existing PVC- No default class and none named: PVC stays Pending
Remember
Class name on the PVC means dynamic. Empty string means static only.
StatefulSets: Stable Identity and Storage
1. Identity and Order
- Pods named name-0 to name-N-1
- DNS:
web-0.web.<ns>.svc.cluster.local - Needs a headless Service (
clusterIP: None) set inspec.serviceName podManagementPolicy: Paralleldrops the ordering
- Create0 to N-1
- TerminateN-1 to 0
2. Storage per Pod
volumeClaimTemplatesmake one PVC per Pod, e.g.data-web-0- The PVC reattaches to the same-named Pod after a reschedule
yaml
serviceName: web
volumeClaimTemplates:
- metadata: {name: data}
spec:
accessModes: [ReadWriteOnce]
resources: {requests: {storage: 1Gi}}| Deployment | StatefulSet | |
|---|---|---|
| Pods | interchangeable | unique |
| Volume | one shared claim | own PVC each |
| Fits | stateless apps | databases, brokers |
3. Gotchas
- Scale-down or delete keeps PVCs: clean up by hand or set
persistentVolumeClaimRetentionPolicy - Rolling updates go from the highest ordinal down
Canary
updateStrategy.rollingUpdate.partition: 2 holds back ordinals below 2 on the old revision.
DaemonSets, Jobs and CronJobs
1. DaemonSet
- One Pod per matching node
- Use for log shippers, node monitors, CNI agents
- New node joins: Pod added automatically
nodeSelectorlimits which nodes qualify
2. Job and CronJob
- CronJobcron schedule
- Jobruns to completion
- Podsretried on failure
| Field | Sets |
|---|---|
completions | successes needed |
parallelism | Pods running at once |
backoffLimit | retries, default 6 |
restartPolicy | OnFailure or Never |
concurrencyPolicy | Allow, Forbid or Replace |
startingDeadlineSeconds | limit on late starts |
timeZone | zone for the schedule |
3. Which Controller?
| Need | Controller |
|---|---|
| Stateless replicas | Deployment |
| Stable identity and storage | StatefulSet |
| One Pod per node | DaemonSet |
| Run-once work | Job |
| Scheduled work | CronJob |
4. Gotchas
- Finished Jobs and Pods stay until
ttlSecondsAfterFinishedis set - DaemonSet skips tainted nodes (control plane) without tolerations
restartPolicy: Alwaysis rejected for Jobs
Remember
Job Pods must end: restartPolicy is OnFailure or Never.
Storage and Controllers Cheat Sheet
1. Inspect and retain
bash
kubectl get pv,pvc,sc
kubectl describe pvc <name>
kubectl patch pv <name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'describe shows the Events behind a Pending claim; patch before deleting a claim you may need back
2. StatefulSet ops and one-offs
bash
kubectl get sts kubectl scale sts <name> --replicas=N kubectl rollout status sts/<name> kubectl delete pvc -l app=<label> kubectl create job <name> --image=<img> -- <cmd> kubectl create job <name> --from=cronjob/<cron> kubectl logs job/<name>
delete pvc removes leftover claims; --from=cronjob triggers a CronJob now
3. Quick map
| Setting | Values |
|---|---|
| Access modes | RWO, ROX, RWX, RWOP |
| Binding modes | Immediate, WaitForFirstConsumer |
| Reclaim policies | Delete, Retain |
kubectl get ds | per-node DaemonSet coverage |
Before deleting a claim
Delete wipes the data with the PVC. Patch the PV to Retain first. Scaling a StatefulSet down keeps its PVCs.
Check yourself
A PVC sets storageClassName: "" and no PV matches its size. What status does it show, and why?
- Pending
""turns dynamic provisioning off, so only a hand-made matching PV can bind
A 3-replica StatefulSet with a volumeClaimTemplate is scaled to 1, then back to 3. What happens to web-2's data?
- The PVCs survive the scale-down
- web-2 returns and reattaches
data-web-2, so the data is intact
A Job manifest sets restartPolicy: Always. What is the bug?
- The API server rejects it
- Jobs need
OnFailureorNever; Always would restart finished Pods forever