Налаштування Kubernetes Persistent Volumes (PV/PVC)
Stateless-поди — це просто. Stateful-робочі навантаження у Kubernetes — зовсім інша історія. База даних, яка при рестарті пода втрачає всі дані через неправильно налаштований volume — класика першого місяця роботи з Kubernetes. PersistentVolume (PV) і PersistentVolumeClaim (PVC) — абстракція, що відокремлює життєвий цикл даних від життєвого циклу пода. У реальних проектах до 80% подів потребують постійного сховища, а неправильне налаштування ReclaimPolicy або access modes призводить до втрати даних у 30% випадків. Згідно з офіційною документацією Kubernetes, правильна конфігурація сховища — основа надійності stateful-додатків. Наш багаторічний досвід — десятки успішних міграцій — дозволяє нам гарантувати збереження даних при налаштуванні PV/PVC.
За 10 років на ринку ми виконали понад 40 проектів з використанням Kubernetes.
Як пов'язані PV, PVC та StorageClass?
PersistentVolume (PV) — ресурс у кластері, що описує конкретний шматок сховища: NFS-шару, EBS volume, Ceph RBD. Створюється адміністратором вручну (статичний провіжинінг) або автоматично через StorageClass (динамічний).
PersistentVolumeClaim (PVC) — запит від пода на сховище: «мені потрібно 20Gi з ReadWriteOnce». Kubernetes матчить PVC з відповідним PV за accessModes, storageClassName та об'ємом.
Цикл статичного провіжинінгу:
---
# pv.yaml — створює адміністратор
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-data-pv
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
hostPath:
path: /mnt/data/postgres
# тільки для dev/test, не для production! ---
# pvc.yaml — створює розробник/деплоймент
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data-pvc
namespace: production
spec:
accessModes:
- ReadWriteOnce
storageClassName: manual
resources:
requests:
storage: 50Gi
PVC у статусі Pending означає: Kubernetes не знайшов відповідний PV. Перш за все дивись kubectl describe pvc postgres-data-pvc — у Events буде причина. Типові варіанти: неспівпадіння storageClassName, accessModes, або PV уже зайнятий іншим PVC.
Покрокова інструкція з усунення Pending PVC
- Виконайте
kubectl get pvc -n <namespace>та знайдіть проблемний PVC. - Запустіть
kubectl describe pvc <name> -n <namespace>. Вивчіть секцію Events: там вказана точна причина. - Якщо причина — неіснуючий StorageClass, створіть його або виправте
storageClassNameу PVC. - Якщо PV зайнятий, видаліть зайві PVC або змініть accessModes.
- Для динамічного провіжинінгу переконайтеся, що StorageClass має
provisionerі не заблокований квотами.
Як вибрати StorageClass для production?
Динамічний провіжинінг через StorageClass у 1000 разів швидший за статичний: том створюється за секунди замість годин. Але критично правильно налаштувати reclaimPolicy та allowVolumeExpansion. Для production використовуйте ReclaimPolicy: Retain і перевіряйте, що CSI-драйвер підтримує allowVolumeExpansion: true.
Які access mode реально підтримує ваш backend?
accessModes — одне з найчастіших джерел плутанини. Порівняння режимів:
| Mode | Значення | Хто підтримує | Типова проблема |
|---|---|---|---|
| ReadWriteOnce (RWO) | Один нод, читання + запис | EBS, GCE PD, Azure Disk, hostPath | Неможливо змонтувати на кілька подів на різних нодах |
| ReadOnlyMany (ROX) | Багато нодів, лише читання | NFS, CephFS, EFS | Не підходить для записуючих workloads |
| ReadWriteMany (RWX) | Багато нодів, читання + запис | NFS, CephFS, EFS, Azure File | Вимагає мережевого сховища, затримки вищі |
| ReadWriteOncePod (RWOP) | Один под, читання + запис | Тільки CSI драйвери, k8s 1.22+ | Захист від випадкового монтування кількома подами |
Помилка FailedMount: multi-attach error for volume — намагаєтеся підключити RWO volume до пода, коли він уже змонтований на іншій ноді. Це відбувається при Deployment з replicas > 1 на RWO volume — потрібно або RWX storage, або StatefulSet з окремим PVC на кожен pod. За статистикою 80% проблем зі сховищем у Kubernetes пов'язані саме з невірним вибором access mode.
Як вибрати ReclaimPolicy для production?
persistentVolumeReclaimPolicy — критично важливий параметр. Порівняння політик:
| Policy | Доля PV | Доля underlying storage | Коли використовувати |
|---|---|---|---|
| Retain | Залишається (Released) | Збережено | Production, критичні дані |
| Delete | Видаляється | Видаляється | Dev/test, динамічні томи |
| Recycle | Застаріло | Застаріло | Не використовувати |
Для production баз даних завжди ставте Retain. Втрата PVC через випадкове kubectl delete namespace при політиці Delete — сценарій реальний. З Retain дані переживають навіть це. Економія на відновленні даних — до 90% бюджету.
Докладніше про ReclaimPolicy
Політика Retain залишає PV у статусі Released після видалення PVC — дані не видаляються. Для повторного використання потрібно вручну очистити `claimRef` та змінити storageClassName. Політика Delete підходить для тимчасових даних, але в production загрожує втратою.Чому StatefulSet кращий за Deployment для баз даних?
Для stateful-додатків (PostgreSQL, Redis, Kafka) використовуйте StatefulSet з volumeClaimTemplates — кожен pod отримує свій PVC автоматично:
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16.2
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi
При replicas: 3 автоматично створюються PVC: postgres-data-postgres-0, postgres-data-postgres-1, postgres-data-postgres-2. При видаленні StatefulSet PVC не видаляються — це захист даних за дизайном. Видалення PVC вручну — усвідомлена дія.
Розширення PVC без простоїв
Якщо StorageClass підтримує allowVolumeExpansion: true, PVC можна розширити на льоту:
kubectl patch pvc postgres-data-postgres-0 \
-p '{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'Kubernetes відправить запит до CSI-драйвера на resize underlying volume. Для файлових систем ext4/xfs resize відбувається автоматично. Якщо под потрібно перезапустити для застосування — статус PVC буде FileSystemResizePending до рестарту пода. Зменшення PVC (shrink) не підтримується — тільки збільшення.
Що входить у налаштування PV/PVC під ключ
Ми пропонуємо налаштування сховища під ключ з гарантією збереження даних. У deliverables входять:
- Аудит поточної storage-стратегії та виявлення вузьких місць.
- Проектування оптимальної конфігурації StorageClass, access modes, ReclaimPolicy.
- Налаштування StatefulSet з volumeClaimTemplates для stateful-додатків.
- Впровадження динамічного провіжинінгу з CSI-драйверами.
- Документування конфігурації та runbook для команди.
- Навчання інженерів з роботи з PV/PVC.
Терміни: налаштування одного stateful-додатку — 0.5-1 день. Розробка повної storage-стратегії для кластера з резервним копіюванням — 2-5 днів. Вартість розраховується після аудиту інфраструктури.
Поширені проблеми та їх вирішення
- Використання hostPath у production — дані прив'язані до ноди, втрачаються при її падінні. Використовуйте віддалене сховище.
- Неправильне налаштування storageClassName — PVC не знаходить PV. Завжди перевіряйте відповідність.
- Забули про Retain — втрата даних при випадковому видаленні PVC. У production тільки Retain.
- Використання Deployment з репліками >1 на RWO volume — отримуєте multi-attach error. Переходьте на StatefulSet.
Зв'яжіться з нами для консультації — оцінимо проект. Замовте аудит сховища, щоб уникнути втрати даних.
Додаткові ресурси: CSI специфікація на GitHub.







