Постоянное хранилище в Kubernetes

Быстрые ссылки
- A Basic Example
- Storage Classes
- Access Modes
- Conclusion
Введение
Файловые системы внутри Pod в Kubernetes по умолчанию эфемерны. Это соответствует идее «стейтлесс» контейнеров. Постоянные данные следует хранить вне контейнера — даже если они выглядят как часть локальной файловой системы контейнера. Kubernetes предоставляет абстракции для выделения и управления таким хранилищем: PersistentVolume (PV) и PersistentVolumeClaim (PVC).
Коротко о терминах (1 строка каждая):
- PersistentVolume (PV): ресурс кластера, представляющий физический или сетевой том.
- PersistentVolumeClaim (PVC): запрос Pod на использование PV с определёнными параметрами (ёмкость, класс, режим доступа).
- StorageClass: шаблон политики хранения, который выбирает драйвер и параметры для динамического provision.
Важно: PV существуют независимо от Pod. PVC связывает Pod с PV. Если PVC используется, Kubernetes может создать PV, который переживёт любой отдельный Pod.
A Basic Example
Ниже — простой пример, где мы вручную создаём PersistentVolume и PersistentVolumeClaim, а затем монтируем PVC в Pod. Каждый ресурс лежит в своём manifest-файле. Применение кластера выполняется командой:
kubectl applyСоздание PersistentVolume
Пример манифеста PV (yaml):
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-volume
namespace: pvc-demo
spec:
storageClassName: manual
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/dataЭто создаёт том с именем my-volume, ёмкостью 2Gi, расположенный на узле по пути /mnt/data. Поскольку том создаётся вручную, мы указываем storageClassName: manual. StorageClass позволяет требовать привязки томов и PVC к одному и тому же классу.
Создание PersistentVolumeClaim
Пример PVC (yaml):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-volume-claim
namespace: pvc-demo
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1GiЭтот PVC запрашивает 1Gi пространства в storage-классе manual. Ранее созданный PV удовлетворяет этим условиям и будет сопряжён (bound) с PVC. После создания оба ресурса покажут статус Bound.
Проверка состояния (примеры команд):
kubectl get pv my-volume
kubectl get pvc my-volume-claimДобавление Pod
Пример Pod, который использует PVC:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: pvc-demo
spec:
containers:
- name: my-container
image: my-image:latest
volumeMounts:
- mountPath: /path/in/container
name: my-pod-volume
volumes:
- name: my-pod-volume
persistentVolumeClaim:
claimName: my-volume-claimВ volumes указываем ссылку на PVC по имени claimName. В volumeMounts используем совпадающее имя и указываем mountPath, куда том будет примонтирован внутри контейнера. Всё, что будет записано в /path/in/container, попадёт на том PV и сохранится при пересоздании Pod.
Storage Classes
StorageClass описывает «политику» хранилища: какой provisioner использовать, какие параметры передать и как реализовать reclaimPolicy. Для облачных сервисов Kubernetes обычно предоставляет предустановленные StorageClass, которые соответствуют блочному хранилищу платформы (например, Google Persistent Disk или аналог в DigitalOcean).
Если вы используете managed Kubernetes:
- не нужно создавать PV вручную; создайте PVC с нужным
storageClassNameи размером; провайдер спровижинит том автоматически; - убедитесь, что
storageClassNameсуществует в кластере и соответствует ожидаемому профилю производительности и репликации.
Примеры storageClass-провиженеров (терминология и имена зависят от провайдера):
- GKE: gcePersistentDisk
- DigitalOcean: do-block-storage
Советы:
- Для production указывайте storageClass явно, чтобы избежать привязки к дефолту.
- Используйте аннотации и параметры (например, type, fsType) в StorageClass для тонкой настройки.
Режимы доступа (Access Modes)
Поддерживаемые значения для поля accessModes:
- ReadWriteOnce — том одновременно монтируется только на один узел с правами чтения-записи.
- ReadOnlyMany — том может монтироваться на несколько узлов, но только в режиме только для чтения.
- ReadWriteMany — том может быть смонтирован на несколько узлов одновременно с правами чтения-записи.
Только один режим может быть «активным» для конкретного тома в момент связывания. Поэтому два PVC привяжутся к одному PV только если оба заявляют совместимый режим доступа.
Режим доступа влияет на планировщик: если нужен шардированный/реплицированный Pod на нескольких узлах с общим томом — используйте ReadWriteMany или ReadOnlyMany в зависимости от сценария.
Ограничение: не все провайдеры поддерживают ReadWriteMany. Проверьте совместимость драйвера.
Полезная памятка и чеклисты
Роль: Разработчик
- Указывайте
mountPathи проверяйте права внутри контейнера. - Используйте PVC в Pod-манифестах, а не напрямую PV.
- Тестируйте recovery: удалите Pod и убедитесь, что данные сохранились.
Роль: SRE / Оператор кластера
- Определите StorageClass с политиками Reclaim, provisioner и параметрами производительности.
- Настройте бэкап/снапшоты для PV, если это важно.
- Мониторьте SLI: доступность томов, latency IO, ошибки монтирования.
Роль: Админ кластера
- Управляйте правами на создание StorageClass и PV.
- Очистка: настройте ReclaimPolicy (Delete или Retain) в PV в зависимости от жизненного цикла данных.
Короткий SOP для добавления постоянного тома в приложение:
- Определить требования к объёму, IOPS, режиму доступа.
- Выбрать/создать StorageClass подходящего типа.
- Создать PVC с
resources.requests.storageиstorageClassName. - Обновить манифест Pod/Deployment с
volumeMountsиvolumesна PVC. - Протестировать монтирование и доступ к данным.
- Настроить бэкапы и политики хранения (Retention).
Точки отказа и когда это не сработает
- Если StorageClass не поддерживает нужный accessMode, PVC не будет связан с PV.
- Если PV размещён на конкретном узле (hostPath) и Pod запланирован на другой узел, монтирование не сработает.
- ReadWriteOnce не подходит для масштабируемых мультиузловых приложений, требующих записи с разных узлов.
Безопасность и приватность
- Контролируйте RBAC для создания PVC/PV/StorageClass — это снижает риск неавторизованного выделения томов.
- Шифруйте данные на уровне облачного провайдера или в файловой системе, если требуется защита данных.
- При обработке персональных данных убедитесь в соответствии с локальным регламентом (например, GDPR): предусмотреть шифрование, логирование доступа и политики удаления данных.
Советы по миграции и совместимости
- При миграции между провайдерами создайте новый PVC на целевом провайдере и синхронизируйте данные через rsync/backup-restore.
- Обратите внимание, что hostPath-тома не портируемы между узлами; используйте сетевые или блочные тома, если нужен перенос.
- Для приложений с высоким I/O выбирайте SSD-backed StorageClass и проверьте лимиты IOPS на стороне провайдера.
Диагностика проблем (короткий чек)
- PVC в статусе Pending: нет подходящего PV или StorageClass не поддерживает динамический provision.
- Pod в состоянии CrashLoop при обращении к тому: проверьте права доступа и SELinux/AppArmor политики, а также owner и uid файлов на томе.
- Ошибки монтирования: проверьте логи kubelet на узле и events в namespace.
Команды для отладки:
kubectl describe pvc my-volume-claim -n pvc-demo
kubectl describe pv my-volume
kubectl get events -n pvc-demo
journalctl -u kubeletФакты и рекомендации
- Типичные единицы измерения: Gi, Ti (используйте двоичные суффиксы для совместимости с Kubernetes).
- Рекомендация: явно задавайте
storageClassNameв манифестах для predictability. - ReclaimPolicy: Delete — автоматическое удаление тома при удалении PV; Retain — сохранить данные для ручной очистки.
Примеры облачных сценариев
- GKE: создайте PVC с
storageClassName: standard(или другим существующим классом). GKE автоматически создаст и привяжет диск. - DigitalOcean Managed Kubernetes: используйте
do-block-storageвstorageClassName.
Ниже пример типичного PVC для облака (yaml):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cloud-volume-claim
namespace: production
spec:
storageClassName: standard
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10GiПримеры тестов и критерии приёмки
Критерии приёмки для внедрения PVC в приложение:
- PVC получает статус
Boundв течение ожидаемого окна времени (например, минуты). - После перезапуска Pod данные в примонтированной директории сохраняются.
- При масштабировании replicaSet, если требуется общий том, используются поддерживаемые accessModes.
Тесты:
- Записать файл в монтированную папку, удалить Pod, создать Pod заново и проверить файл.
- Создать два Pod на разных узлах с PVC, если нужен ReadWriteMany — убедиться, что запись в одном Pod видна в другом.
Мероприятия при инциденте и откат
Если PV потерял данные или PVC повредился:
- Остановите приложения, чтобы избежать дополнительной порчи данных.
- Снимите snapshot (если поддерживается) или экспортируйте доступные данные для резервного копирования.
- Если есть Retain-политика, вручную подключите том к тестовому узлу и оцените целостность.
- При необходимости восстановите данные из резервной копии и создайте новый PVC/PV.
Decision flow (выбор подхода) — Mermaid
flowchart TD
A[Нужно ли сохранять данные после перезапуска Pod?] -->|Нет| B[Не нужен PV: используйте обычные volumes]
A -->|Да| C[Нужно ли делиться данными между узлами?]
C -->|Нет| D[ReadWriteOnce]
C -->|Да, только чтение| E[ReadOnlyMany]
C -->|Да, чтение/запись| F[ReadWriteMany]
D --> G{Managed K8s?}
G -->|Да| H[Создать PVC с нужным StorageClass]
G -->|Нет| I[Создать PV + PVC вручную]
H --> J[Примонтировать в Pod]
I --> JЧасто задаваемые вопросы
Нужно ли создавать PersistentVolume вручную в облаке?
Нет. В большинстве управляемых кластеров достаточно создать PVC с правильным storageClassName — провайдер создаст PV автоматически.
Можно ли использовать hostPath в production?
hostPath удобен для тестирования и локальных кластеров, но в production он не портируем и привязан к конкретному узлу.
Что происходит с данными, если PVC удалён?
Поведение зависит от ReclaimPolicy PV. Если ReclaimPolicy = Delete, том и данные будут удалены; если Retain — данные сохранятся для ручной обработки.
Вывод
PersistentVolume и PersistentVolumeClaim — простая и надёжная модель для хранения постоянных данных в Kubernetes. Для управляемых кластеров обычно достаточно PVC с нужным StorageClass. Для ручного управления используйте PV + PVC. Всегда учитывайте режим доступа, совместимость провайдера и политику Reclaim для безопасности данных.
Important: всегда тестируйте сценарии восстановления и настройте резервное копирование для важных данных.