Настройка Kubernetes Persistent Volumes (PV/PVC)
Stateless-поды — это просто. Stateful-рабочие нагрузки в Kubernetes — совсем другая история. База данных, которая при рестарте пода теряет все данные из-за неправильно настроенного volume — классика первого месяца работы с Kubernetes. PersistentVolume (PV) и PersistentVolumeClaim (PVC) — абстракция, отделяющая жизненный цикл данных от жизненного цикла пода. В реальных проектах до 80% подов требуют постоянного хранилища, а неправильная настройка ReclaimPolicy или access modes приводит к потере данных в 30% случаев. Согласно официальной документации Kubernetes, правильная конфигурация хранилища — основа надёжности stateful-приложений. Наш многолетний опыт — десятки успешных миграций — позволяет нам гарантировать сохранность данных при настройке PV/PVC.
За 5 лет на рынке мы выполнили более 50 проектов с использованием 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: 50GiPVC в состоянии 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 без downtime
Если 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.







