Простое руководство по реализации постоянного хранилища в Kubernetes

Узнайте, как реализовать постоянное хранилище для stateful-приложений в Kubernetes. Это руководство объясняет суть PersistentVolumes (PVs) и PersistentVolumeClaims (PVCs), а также режимы доступа и StorageClasses. Включает практические примеры YAML для определения PVCs и монтирования хранилища к вашим подам, обеспечивая надежную персистентность данных в ваших контейнеризированных приложениях.

Простое руководство по реализации постоянного хранилища в Kubernetes

Постоянное хранилище Kubernetes решает простую проблему: ваш контейнер может исчезнуть, но файлы базы данных, загрузки или данные очереди не могут. Pod'ы без состояния могут быть заменены в любое время. Приложениям с состоянием нужно хранилище, которое переживает перезапуски Pod'ов, перепланирование и обслуживание узлов.

Это руководство объясняет PersistentVolumes (PV), PersistentVolumeClaims (PVC), режимы доступа и StorageClasses с практическими примерами YAML, которые вы можете адаптировать для реальной рабочей нагрузки.

Понимание PersistentVolumes (PV) и PersistentVolumeClaims (PVC)

Прежде чем монтировать хранилище в Pod, узнайте, какой объект за что отвечает:

  • PersistentVolume (PV): PV — это часть хранилища в кластере, которая была подготовлена администратором или динамически подготовлена с помощью StorageClasses. PV являются ресурсами кластера, как и узлы. Они имеют жизненный цикл, независимый от любого отдельного Pod'а, использующего PV. PV абстрагируют детали реализации базового хранилища (например, NFS, iSCSI, блочное хранилище облачного провайдера).
  • PersistentVolumeClaim (PVC): PVC — это запрос на хранилище от пользователя. Он потребляет ресурсы хранилища, доступные в кластере в виде PV. PVC похожи на Pod'ы тем, что потребляют вычислительные ресурсы, и они ограничены пространством имен. PVC указывает желаемую емкость хранилища, режимы доступа и, опционально, StorageClass.

Это разделение позволяет командам платформы управлять деталями хранилища, в то время как команды приложений запрашивают необходимую емкость и шаблон доступа.

Ключевые концепции: Режимы доступа и StorageClasses

Два параметра управляют большинством поведений PVC: как том может быть смонтирован и какой бэкенд хранилища должен его создать.

Режимы доступа

Режимы доступа определяют, как том может быть смонтирован в Pod. Доступны следующие режимы доступа:

  • ReadWriteOnce (RWO): Том может быть смонтирован для чтения и записи одним узлом.
  • ReadOnlyMany (ROX): Том может быть смонтирован только для чтения многими узлами.
  • ReadWriteMany (RWX): Том может быть смонтирован для чтения и записи многими узлами.
  • ReadWriteOncePod (RWOP): Том может быть смонтирован для чтения и записи одним Pod'ом. Это полезно, когда требуется более строгое поведение одного писателя и ваш CSI-драйвер это поддерживает.

Важно отметить, что фактическая поддержка этих режимов зависит от базового поставщика хранилища.

StorageClasses

StorageClass предоставляет администраторам способ описания «классов» хранилища, которые они предлагают. Разные классы могут соответствовать уровням качества обслуживания, политикам резервного копирования или произвольным политикам, определенным администраторами кластера. StorageClass имеет провизионера, который подготавливает хранилище, и набор параметров для провизионера. Когда PVC создается без указания конкретного PV и запрашивает StorageClass, Kubernetes динамически подготавливает PV с использованием указанного StorageClass.

Реализация постоянного хранилища шаг за шагом

Давайте рассмотрим типичный сценарий: запрос и использование постоянного хранилища для Pod'а.

Шаг 1: Определение PersistentVolumeClaim (PVC)

Сначала нужно создать PVC, который указывает ваши требования к хранилищу. Этот PVC будет действовать как запрос на хранилище для вашего приложения.

Пример pvc.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

В этом примере:

  • name: my-pvc: Это имя нашего PVC.
  • accessModes: - ReadWriteOnce: Мы запрашиваем хранилище, которое может быть смонтировано для чтения и записи одним узлом.
  • resources.requests.storage: 1Gi: Мы запрашиваем 1 гигабайт хранилища.

Применение PVC:

Сохраните приведенное выше содержимое в файл с именем pvc.yaml и примените его к вашему кластеру:

kubectl apply -f pvc.yaml

После применения вы можете проверить статус PVC:

kubectl get pvc my-pvc

Вы должны увидеть вывод, указывающий, что PVC находится в состоянии Bound, если подходящий PV доступен или был динамически подготовлен.

Шаг 2: Создание Pod'а, использующего PVC

Теперь давайте создадим Pod, который будет использовать хранилище, запрошенное нашим PVC. Мы смонтируем том, предоставленный PVC, в определенный каталог внутри нашего контейнера.

Пример pod-with-pv.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: my-stateful-pod
spec:
  containers:
    - name: my-container
      image: nginx
      ports:
        - containerPort: 80
      volumeMounts:
        - name: my-persistent-storage
          mountPath: /usr/share/nginx/html
  volumes:
    - name: my-persistent-storage
      persistentVolumeClaim:
        claimName: my-pvc

В этом примере:

  • volumes: Мы определяем том с именем my-persistent-storage.
  • persistentVolumeClaim.claimName: my-pvc: Это связывает наш том с PVC, который мы создали ранее.
  • volumeMounts: Внутри определения контейнера мы указываем, куда должен быть смонтирован этот том (mountPath: /usr/share/nginx/html).

Применение Pod'а:

Сохраните приведенное выше содержимое в файл с именем pod-with-pv.yaml и примените его:

kubectl apply -f pod-with-pv.yaml

Теперь ваш контейнер nginx будет иметь доступ к постоянному хранилищу, определенному my-pvc, по пути /usr/share/nginx/html. Любые данные, записанные в этот путь внутри контейнера, будут сохранены, даже если Pod будет удален и создан заново, пока PVC и его базовый PV остаются.

Динамическое provisioning с StorageClasses

Ручное создание PV может быть обременительным. Kubernetes предлагает динамическое provisioning, при котором PV создаются автоматически, когда PVC запрашивает хранилище, которое не может быть удовлетворено существующими PV. Это достигается с помощью StorageClasses.

Большинство облачных провайдеров (AWS, GCP, Azure) предлагают предварительно настроенные StorageClasses. Вы можете просмотреть их с помощью:

kubectl get storageclass

Чтобы использовать динамическое provisioning, просто добавьте поле storageClassName в определение вашего PVC:

Пример pvc-dynamic.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-dynamic-pvc
spec:
  storageClassName: standard # Замените 'standard' на фактическое имя StorageClass
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Когда вы примените этот PVC, Kubernetes найдет StorageClass с именем standard (или любым другим указанным вами именем) и укажет его провизионеру создать новый PV размером 5Gi и привязать его к этому PVC.

Советы и лучшие практики

  • Выберите правильный режим доступа: Тщательно продумайте режим доступа, необходимый вашему приложению. ReadWriteOnce распространен для баз данных с одной репликой, в то время как ReadWriteMany необходим для общих файловых систем, используемых несколькими Pod'ами.
  • Понимайте производительность хранилища: Разные поставщики хранилищ и StorageClasses предлагают различные характеристики производительности (IOPS, пропускная способность). Выберите StorageClass, который соответствует требованиям производительности вашего приложения.
  • Стратегия резервного копирования: Постоянное хранилище не означает автоматическое резервное копирование. Реализуйте надежную стратегию резервного копирования для ваших постоянных томов, особенно для критически важных данных.
  • Политика возврата PV: PV имеют persistentVolumeReclaimPolicy, обычно Delete или Retain. Динамически подготовленные тома часто используют политику возврата, определенную их StorageClass. Устаревшая политика Recycle устарела и не должна использоваться для новых настроек.
  • Учет пространств имен: PVC ограничены пространствами имен. Убедитесь, что ваш Pod и PVC находятся в одном пространстве имен для привязки.

Вывод

Постоянное хранилище в Kubernetes начинается с PVC, монтирования в Pod и StorageClass, соответствующего вашей рабочей нагрузке. Для базы данных с одной репликой начните с запроса ReadWriteOnce, убедитесь, что он достиг состояния Bound, смонтируйте его в контейнер и сделайте резервное копирование частью дизайна с первого дня.