PersistentVolume
| Объекты | PersistentVolume, PersistentVolumeClaim, StorageClass |
|---|---|
| Связанный контроллер | StatefulSet |
| Режимы доступа | RWO, ROX, RWX, RWOP |
| Интерфейс драйверов | Container Storage Interface (CSI) |
| Политики возврата | Retain, Delete |
| Примеры хранилищ | облачные диски, NFS, Ceph (Rook), Longhorn, local-path |
PersistentVolume (PV, постоянный том) — объект Kubernetes, представляющий кусок хранилища в кластере: облачный диск, сетевую папку NFS, том в Ceph или каталог на узле. В отличие от файловой системы контейнера, которая исчезает вместе с подом, данные на PersistentVolume сохраняются при перезапуске, пересоздании и переносе пода на другой узел. Поэтому именно через PV в Kubernetes запускают базы данных, очереди и всё, что хранит состояние.
Три объекта
Хранилище в Kubernetes разделено на роли администратора и разработчика:[1]
| Объект | Кто создаёт | Что описывает |
|---|---|---|
| PersistentVolume | администратор или автоматически | конкретный том: размер, тип, где находится |
| PersistentVolumeClaim (PVC) | разработчик | заявку: «нужно 10 ГиБ, запись с одного узла» |
| StorageClass | администратор | «тип хранилища» и драйвер, создающий тома по заявкам |
Под ссылается не на PV, а на PVC — так манифест приложения не зависит от того, где кластер работает: в облаке, на собственном железе или на ноутбуке.
Пример
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
storageClassName: fast-ssd
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Pod
metadata:
name: db
spec:
containers:
- name: postgres
image: postgres:17
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: data
Динамическое выделение
В современных кластерах PV почти никогда не создают вручную. Когда появляется PVC с указанным StorageClass, провижинер — драйвер CSI — сам создаёт диск у провайдера и соответствующий PV, после чего связывает его с заявкой (статус Bound).[2] Один StorageClass обычно помечен как класс по умолчанию.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
type: gp3
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
Режим WaitForFirstConsumer откладывает создание тома, пока под не назначен на узел, — иначе диск может оказаться в другой зоне доступности, чем под.
Режимы доступа
- ReadWriteOnce (RWO) — чтение и запись с одного узла; типично для блочных дисков.
- ReadOnlyMany (ROX) — только чтение с многих узлов.
- ReadWriteMany (RWX) — запись с многих узлов; нужна файловая система с общим доступом (NFS, CephFS, облачные файловые хранилища).
- ReadWriteOncePod (RWOP) — запись только из одного пода во всём кластере.
Частая ошибка — ждать от облачного блочного диска режима RWX: он не поддерживается, и под на втором узле не запустится.
Жизненный цикл и политики
Когда PVC удаляют, судьба тома определяется политикой reclaimPolicy: Delete — диск удаляется вместе с данными (по умолчанию для динамических томов), Retain — PV остаётся в статусе Released, и данные можно восстановить вручную. Для важных баз данных разумно использовать Retain и всё равно делать резервные копии. Тома можно увеличивать (allowVolumeExpansion) — уменьшать нельзя. Механизм VolumeSnapshot создаёт снимки томов средствами хранилища.[4]
StatefulSet
Для приложений с состоянием используется контроллер StatefulSet: в отличие от Deployment, он даёт подам стабильные имена (db-0, db-1) и через volumeClaimTemplates создаёт каждому реплике свой PVC, который сохраняется при пересоздании пода.[3] Сложные системы с репликацией и переключением обычно разворачивают через оператор, который сам управляет StatefulSet и томами.
CSI и типы хранилищ
Container Storage Interface — стандарт, по которому производители хранилищ пишут драйверы для Kubernetes и других оркестраторов, не меняя код самого Kubernetes.[5] Распространённые варианты:
- Облачные диски — AWS EBS, Google Persistent Disk, Azure Disk, диски Yandex Cloud.
- Локальные тома —
local-path-provisioner(по умолчанию в k3s): быстро, но данные привязаны к узлу. - Распределённые — Rook/Ceph, Longhorn, OpenEBS: реплицируют данные между узлами собственного кластера.
- NFS — простой вариант для RWX.
Диагностика
kubectl get pvc,pv
kubectl describe pvc data # события: почему не Bound
kubectl get storageclass
Если PVC висит в Pending, причины обычно три: нет подходящего StorageClass, драйвер не установлен или заявка требует неподдерживаемый режим доступа.