Модуль 7 / 19
Storage: Volume, PV, PVC, StorageClass и CSI
Содержание
1. Цели модуля
После модуля вы сможете различать ephemeral и persistent volumes, объяснить связь StorageClass, PV и PVC, выбрать access mode и reclaim policy, подтвердить сохранность данных и диагностировать Pending PVC.
- жизненный цикл PV/PVC
- static и dynamic provisioning
- binding и topology
- безопасное удаление данных
2. Теория: Volume и жизненный цикл данных
Writable layer контейнера исчезает вместе с контейнером и не подходит для состояния. emptyDir принадлежит Pod: переживает перезапуск контейнера, но удаляется вместе с Pod. PersistentVolume отделяет жизненный цикл storage от Pod.
Приложение монтирует PVC, а не конкретный диск. Это сохраняет абстракцию между потребителем и реализацией storage. Snapshot, backup, replication и disaster recovery не возникают автоматически только из-за использования PVC.
3. Теория: StorageClass, PV и PVC
PersistentVolume — cluster-scoped представление storage. PersistentVolumeClaim — namespaced запрос на capacity, access mode и StorageClass. Binding связывает PVC с совместимым PV один к одному.
При dynamic provisioning CSI provisioner создаёт PV по StorageClass. volumeBindingMode WaitForFirstConsumer откладывает provisioning и binding до появления Pod, чтобы учитывать topology выбранного Node. Без подходящего provisioner или PV claim остаётся Pending.
4. Теория: access modes и reclaim policy
ReadWriteOnce допускает read-write mount с одного Node и не означает строго один Pod. ReadWriteMany зависит от driver. ReadOnlyMany описывает capability. ReadWriteOncePod ограничивает volume одним Pod и поддерживается CSI-драйверами.
Access modes используются при matching и не являются файловыми ACL и гарантией read-only после mount. Реальное поведение задают driver, mount flags и приложение.
ReclaimPolicy Delete удаляет storage asset после удаления claim, если driver это поддерживает. Retain сохраняет PV и данные для ручного восстановления. Перед production выберите policy осознанно и проверьте backup/restore.
5. Методические указания
- Начинайте с PVC status и Events, затем проверяйте StorageClass и PV
- Сопоставляйте capacity, accessModes, storageClassName, volumeMode и topology
- Не уменьшайте PVC: стандартное expansion поддерживает только увеличение и зависит от StorageClass
- Не удаляйте PVC до проверки reclaim policy и резервной копии
- hostPath допустим только для этой kind-лаборатории, не как production storage
- Проверяйте восстановление данных, а не только статус Bound
6. Лабораторная работа: PV, PVC и writer
Лаборатория ожидает kind-кластер course из модуля 1 с Node course-worker. Сохраните манифест как storage-lab.yaml. hostPath используется только для демонстрации статического binding.
apiVersion: v1
kind: Namespace
metadata:
name: lab-storage
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: lab-storage-pv
spec:
capacity:
storage: 64Mi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual-lab
hostPath:
path: /var/local/course-data
type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
namespace: lab-storage
spec:
storageClassName: manual-lab
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 64Mi
---
apiVersion: v1
kind: Pod
metadata:
name: writer
namespace: lab-storage
spec:
nodeSelector:
kubernetes.io/hostname: course-worker
containers:
- name: app
image: busybox:1.37.0
command: ["sh", "-c", "printf 'persistent-data\n' > /data/message; sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: app-data7. Лабораторная работа: проверяем сохранность
Сохраните второй манифест как storage-reader.yaml. Запишите данные, удалите writer Pod, создайте reader Pod с тем же PVC и прочитайте файл.
apiVersion: v1
kind: Pod
metadata:
name: reader
namespace: lab-storage
spec:
nodeSelector:
kubernetes.io/hostname: course-worker
containers:
- name: app
image: busybox:1.37.0
command: ["sh", "-c", "sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
readOnly: true
volumes:
- name: data
persistentVolumeClaim:
claimName: app-datakubectl apply -f storage-lab.yaml
kubectl get storageclass
kubectl get persistentvolume lab-storage-pv
kubectl get persistentvolumeclaim app-data -n lab-storage
kubectl wait -n lab-storage --for=condition=Ready pod/writer --timeout=120s
kubectl exec -n lab-storage writer -- cat /data/message
kubectl delete pod writer -n lab-storage --wait=true
kubectl apply -f storage-reader.yaml
kubectl wait -n lab-storage --for=condition=Ready pod/reader --timeout=120s
kubectl exec -n lab-storage reader -- cat /data/message
kubectl get pv,pvc -AКритерий: PVC имеет Bound, оба Pod последовательно работают на course-worker, reader после удаления writer возвращает persistent-data, PV всё ещё связан с claim.
8. Диагностика: Pending PVC
Сохраните манифест как storage-pending.yaml. Несуществующий StorageClass не имеет provisioner, поэтому PVC останется Pending, а Pod — Pending из-за unbound claim.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pending-data
namespace: lab-storage
spec:
storageClassName: missing-provisioner
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: blocked
namespace: lab-storage
spec:
containers:
- name: app
image: busybox:1.37.0
command: ["sh", "-c", "sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: pending-datakubectl apply -f storage-pending.yaml
kubectl get pvc,pod -n lab-storage
kubectl describe pvc pending-data -n lab-storage
kubectl describe pod blocked -n lab-storage
kubectl events -n lab-storage --types=Warning
kubectl get storageclass
kubectl get pv
kubectl delete pod blocked -n lab-storage
kubectl delete pvc pending-data -n lab-storage
kubectl delete namespace lab-storage
kubectl get pv lab-storage-pv
kubectl delete pv lab-storage-pvАлгоритм: PVC Events → StorageClass и provisioner → доступные PV → размер и access modes → topology → Pod scheduling Events. Не исправляйте Pod, пока storage request не может быть удовлетворён.
9. Контроль и шпаргалка
- Что переживает restart контейнера, удаление Pod и удаление PVC?
- Почему RWO не означает один Pod?
- Зачем WaitForFirstConsumer знает о scheduling?
- Чем Retain отличается от backup?
- Почему Bound ещё не доказывает работоспособность приложения?
Модуль освоен, если вы связываете Pod → PVC → PV → StorageClass, доказываете сохранность данных после замены Pod и объясняете Pending claim по Events и параметрам binding.
PDF для работы офлайн
Скачайте оформленную версию модуля для чтения без подключения к сети.