Настройка Persistent Volumes (PV/PVC) в Kubernetes

Потеря данных при рестарте пода — частая проблема stateful-приложений в Kubernetes. Мы настраиваем Persistent Volumes и Claims так, чтобы хранилище было надёжным и не зависело от жизненного цикла подов. Наша команда реализует проект под ключ — от аудита StorageClass до внедрения и последующей поддержки.
Часто задаваемые вопросы

Настройка 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: 50Gi

PVC в состоянии Pending означает: Kubernetes не нашёл подходящий PV. Первым делом смотри kubectl describe pvc postgres-data-pvc — в Events будет причина. Типичные варианты: несовпадение storageClassName, accessModes, или PV уже занят другим PVC.

Пошаговая инструкция по устранению Pending PVC

  1. Выполните kubectl get pvc -n <namespace> и найдите проблемный PVC.
  2. Запустите kubectl describe pvc <name> -n <namespace>. Изучите секцию Events: там указана точная причина.
  3. Если причина — несуществующий StorageClass, создайте его или исправьте storageClassName в PVC.
  4. Если PV занят, удалите лишние PVC или измените accessModes.
  5. Для динамического провижининга убедитесь, что 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.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    816
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1141