Файловая система контейнера эфемерна: при перезапуске контейнера все данные теряются. Volumes решают две задачи: сохранение данных при перезапуске контейнера и обмен данными между контейнерами в одном Pod.
[source: kubernetes.io/docs/concepts/storage/volumes/]
Типы Volume
emptyDir
Пустая директория, создаётся при назначении Pod на узел. Существует пока Pod работает. При удалении Pod данные теряются. При перезапуске контейнера — данные сохраняются (это часто удивляет).
Применение: временный кеш, обмен данными между контейнерами одного Pod.
apiVersion: v1
kind: Pod
metadata:
name: shared-data
spec:
containers:
- name: writer
image: busybox:1.36
command: ["sh", "-c", "echo 'hello' > /data/message && sleep 3600"]
volumeMounts:
- name: shared
mountPath: /data
- name: reader
image: busybox:1.36
command: ["sh", "-c", "cat /data/message && sleep 3600"]
volumeMounts:
- name: shared
mountPath: /data
volumes:
- name: shared
emptyDir: {}
emptyDir с medium: Memory хранит данные в tmpfs (RAM) — быстрее, но считается в memory limits Pod:
volumes:
- name: cache
emptyDir:
medium: Memory
sizeLimit: 256Mi
hostPath
Монтирует файл или директорию с файловой системы узла. Данные привязаны к конкретному узлу — при перемещении Pod на другой узел данные недоступны.
volumes:
- name: host-data
hostPath:
path: /var/log/app
type: DirectoryOrCreate
Типы: Directory, DirectoryOrCreate, File, FileOrCreate, Socket, CharDevice, BlockDevice.
Используется редко — в основном для системных компонентов (DaemonSet для мониторинга или логирования). В production приложениях не использовать: нет переносимости, риски безопасности.
configMap и secret
Монтируют данные из ConfigMap или Secret как файлы (подробно в главе 08):
volumes:
- name: config
configMap:
name: app-config
- name: creds
secret:
secretName: db-credentials
PersistentVolume (PV)
PV — ресурс хранения на уровне кластера, подготовленный администратором или динамически через StorageClass. Существует независимо от Pod.
[source: kubernetes.io/docs/concepts/storage/persistent-volumes/]
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-data
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
hostPath:
path: /mnt/data # только для dev/test; production использует CSI-драйвер
PersistentVolumeClaim (PVC)
PVC — запрос пользователя на хранилище. PVC привязывается к подходящему PV по размеру, access mode и StorageClass.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: standard
Привязка PVC к PV
Kubernetes ищет PV, удовлетворяющий требованиям PVC:
capacity.storage>= запрошенный размер- Совпадение
accessModes - Совпадение
storageClassName
Привязка — one-to-one: один PV привязывается к одному PVC.
kubectl get pv
kubectl get pvc
# Статусы PV:
# Available — PV свободен
# Bound — PV привязан к PVC
# Released — PVC удалён, PV ожидает очистки
# Failed — ошибка автоматической очистки
Использование PVC в Pod
apiVersion: v1
kind: Pod
metadata:
name: app-with-storage
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: data
mountPath: /var/lib/app/data
volumes:
- name: data
persistentVolumeClaim:
claimName: app-data-claim
StorageClass
StorageClass определяет «класс» хранилища и позволяет динамически создавать PV при запросе PVC. Не нужно создавать PV вручную.
[source: kubernetes.io/docs/concepts/storage/storage-classes/]
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
throughput: "125"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
При создании PVC с storageClassName: fast-ssd StorageClass автоматически создаст PV.
volumeBindingMode:
Immediate— PV создаётся сразу при создании PVCWaitForFirstConsumer— PV создаётся при назначении Pod на узел, учитывает топологию (availability zone)
WaitForFirstConsumer предпочтительнее для облачных сред — гарантирует создание диска в той же AZ, что и Pod.
Access Modes
Не все типы хранилищ поддерживают все режимы. AWS EBS — только RWO. NFS, Azure Files, GCS Fuse — RWX. RWOP — самый строгий, гарантирует эксклюзивный доступ на уровне Pod.
Reclaim Policy
Определяет, что происходит с PV после удаления PVC:
Retain безопаснее для production — данные можно восстановить. Delete удобнее в dev/test для автоочистки.
Полный пример: PV + PVC + Pod (PostgreSQL)
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-pv
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
hostPath:
path: /mnt/postgres
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: standard
---
apiVersion: v1
kind: Pod
metadata:
name: postgres
spec:
containers:
- name: postgres
image: postgres:16
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: pg-secret
key: password
ports:
- containerPort: 5432
volumeMounts:
- name: pg-data
mountPath: /var/lib/postgresql/data
volumes:
- name: pg-data
persistentVolumeClaim:
claimName: postgres-pvc
В production PostgreSQL запускается через StatefulSet с volumeClaimTemplates — для каждой реплики автоматически создаётся отдельный PVC (глава 11).
Типичные ошибки
PVC зависает в Pending. Причины: нет подходящего PV (если нет динамического провижининга), StorageClass не существует, volumeBindingMode: WaitForFirstConsumer и Pod ещё не назначен на узел. Диагностика: kubectl describe pvc <name>.
Удаление PVC при живом Pod. PVC защищён финализатором kubernetes.io/pvc-protection — удаление зависнет пока Pod жив. Сначала удали Pod.
Неверный AccessMode. Создать PVC с RWX для AWS EBS невозможно — EBS не поддерживает. API Server примет PVC, но привязка к PV завершится ошибкой.
hostPath в production для данных. При перемещении Pod на другой узел данные недоступны. Для multi-replica Deployment с hostPath каждый Pod видит данные только своего узла.
Не настроить allowVolumeExpansion: true. После создания StorageClass без этого параметра расширить PVC невозможно без пересоздания.
Альтернативы
CSI-драйверы (Container Storage Interface) — стандартный механизм подключения хранилищ. AWS EBS CSI, GCE PD CSI, Ceph CSI, Longhorn. Заменили устаревшие in-tree плагины.
Rook/Ceph — распределённое хранилище поверх локальных дисков узлов. Поддерживает RWO, ROX, RWX. Сложен в эксплуатации.
Longhorn — лёгкое распределённое блочное хранилище от Rancher. Проще Ceph, встроенный UI, снапшоты, резервное копирование.
Object Storage (S3, GCS, MinIO) — для неструктурированных данных, медиафайлов, бэкапов. Не через Volume, а через SDK или FUSE-mount (s3fs, mountpoint-s3).