Persistent Volumes в Kubernetes: настройка хранилища для баз данных и stateful-приложений | Руководство по CSI (TrueNAS, Ceph) | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Persistent Volumes в Kubernetes: настройка хранилища для баз данных и stateful-приложений | Руководство по CSI (TrueNAS, Ceph)

10 мая 2026 11 мин. чтения

Развертывание stateful-приложений, таких как базы данных PostgreSQL, кэши Redis или брокеры сообщений Kafka, в Kubernetes требует надежного и управляемого хранилища данных. В отличие от статичных серверов, контейнеры в кластере эфемерны и могут перемещаться между узлами. Это создает фундаментальное противоречие: как обеспечить постоянство данных в динамической среде.

Решение этой проблемы лежит в использовании механизмов оркестрации хранилища Kubernetes: Persistent Volumes (PV), Persistent Volume Claims (PVC), StorageClasses и CSI-драйверов. В этом руководстве вы получите пошаговые инструкции по настройке динамического выделения хранилища, выбору и развертыванию CSI-драйвера (TrueNAS или Ceph/Rook), а также готовые конфигурации для безопасного и отказоустойчивого хранения данных ваших приложений.

Почему управление хранилищем - критический вызов для современных stateful-приложений в Kubernetes

Архитектура современных приложений перешла от монолита к микросервисам и event-driven коммуникациям. Это повышает гибкость и скорость разработки, но увеличивает количество stateful-компонентов, работающих в контейнерах. Каждая база данных, кэш или очередь сообщений требует сохранения состояния между перезапусками подов.

Бизнес-требования к таким системам включают горизонтальное масштабирование под непредсказуемую нагрузку и быстрый выпуск обновлений через конвейеры CI/CD. Эфемерная природа контейнеров вступает в конфликт с необходимостью постоянного хранения данных. Классические подходы, такие как монтирование локальных дисков, не работают при миграции пода на другой узел кластера.

Для российского рынка добавляются регуляторные требования, такие как 152-ФЗ и рекомендации ФСТЭК, которые предъявляют строгие условия к безопасности и локализации данных. Эти требования накладывают дополнительные ограничения на выбор и конфигурацию систем хранения, исключая использование непроверенных или зарубежных облачных решений без должного уровня сертификации.

Ответом на эти вызовы становится оркестрация хранилища на уровне Kubernetes. Механизмы Persistent Volumes, StorageClass и CSI позволяют декларативно описывать требования к хранилищу и автоматически подключать его к подам, обеспечивая переносимость данных и интеграцию с внешними отказоустойчивыми системами хранения.

Архитектура хранения данных в Kubernetes: от PersistentVolume до CSI-драйвера

Чтобы эффективно управлять хранилищем в Kubernetes, нужно понимать роли ключевых абстракций. PersistentVolume (PV) представляет собой физический или логический ресурс хранения в кластере, например, диск NFS или блоковое устройство iSCSI. PersistentVolumeClaim (PVC) - это запрос пользователя (пода) на выделение ресурса из PV с определенными характеристиками: размером, режимом доступа (ReadWriteOnce, ReadWriteMany).

StorageClass (SC) определяет «меню» или класс хранилища с заданными параметрами производительности, отказоустойчивости и политиками. Когда Pod создает PVC, указывая нужный StorageClass, Kubernetes динамически (dynamic provisioning) создает новый PV, соответствующий этому классу. Это избавляет администратора от ручного создания томов (статический provisioning).

Стандарт Container Storage Interface (CSI) играет роль драйвера, который связывает Kubernetes с внешней системой хранения, такой как TrueNAS, Ceph, AWS EBS или Google Persistent Disk. CSI-драйвер реализует операции создания, удаления, подключения и создания снапшотов томов по запросу Kubernetes API.

Общая схема работы выглядит так:
1. Администратор развертывает CSI-драйвер для выбранной системы хранения и создает один или несколько StorageClass.
2. Разработчик в манифесте Pod или StatefulSet указывает PersistentVolumeClaim, ссылаясь на нужный StorageClass.
3. Контроллер в Kubernetes, увидев PVC, через CSI-драйвер отправляет запрос внешнему хранилищу на создание тома.
4. Созданный том привязывается к PersistentVolume, который, в свою очередь, связывается с PVC.
5. Kubelet на узле, где запланирован Pod, с помощью CSI-драйвера монтирует том в файловую систему контейнера.

StorageClass как декларация политик: производительность, отказоустойчивость и стоимость

StorageClass - это центральный объект для управления качеством хранилища. Через его параметры (parameters) решаются конкретные бизнес-задачи.

  • Тип диска и производительность: Параметры вроде type: ssd или iopsLimit: 5000 позволяют выделять быстрые SSD-тома для баз данных и медленные, но емкие HDD - для архивов или логов.
  • Политики репликации и отказоустойчивости: Для TrueNAS можно указать уровень RAID-Z (zfs:compression=zstd, zfs:dedup=on). Для Ceph/Rook определяется схема репликации (replicated) или кодирования стиранием (erasure coded).
  • Файловая система: Параметр fsType определяет, будет ли том отформатирован в ext4, xfs или останется в родной для хранилища файловой системе (например, ZFS).
  • Расширение томов: Опция allowVolumeExpansion: true позволяет в будунии увеличить размер PVC без потери данных.

Пример создания StorageClass для быстрого SSD-хранилища в TrueNAS:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: truenas-iscsi-ssd
provisioner: csi.truenas.com
parameters:
  datasetParent: "k8s-pool/volumes"
  fsType: "ext4"
  disksize: "" # Размер указывается в PVC
  apiEndpoint: "https://truenas.local"
  apiKey: ""
  disableDelete: "false"
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate

Для мониторинга производительности таких томов используются метрики IOPS (операций ввода-вывода в секунду) и latency (задержка), которые можно собирать с помощью Prometheus и визуализировать в Grafana.

Выбор и развертывание CSI-драйвера: сравнительный анализ TrueNAS и Ceph/Rook

Выбор CSI-драйвера определяет всю архитектуру хранения. Два популярных решения для on-premise сред - это TrueNAS (централизованное NAS/SAN) и Ceph/Rook (распределенное программно-определяемое хранилище).

TrueNAS (SCALE):
Идеально подходит, когда в инфраструктуре уже есть выделенный NAS-сервер или требуется глубокая интеграция с возможностями ZFS: снапшоты, клонирование, компрессия, дедупликация. Архитектура централизованная: все данные хранятся на одном или нескольких серверах TrueNAS, которые предоставляют тома по протоколам iSCSI или NFS. Настройка проще, администрирование знакомо системным администраторам. Это хороший выбор для сред, где важна предсказуемая производительность и есть бюджет на выделенное железо.

Ceph/Rook:
Это решение для полностью программно-определяемого, горизонтально масштабируемого хранилища, работающего внутри самого Kubernetes-кластера. Rook - это оператор, который управляет развертыванием и жизненным циклом кластера Ceph на дисках, подключенных к рабочим узлам Kubernetes. Ceph обеспечивает отказоустойчивость за счет репликации или кодирования стиранием данных между многими узлами. Порог входа выше, требуется больше ресурсов CPU и RAM, но система получается крайне гибкой и масштабируемой.

Таблица для выбора:

  • Выбирайте TrueNAS, если: у вас есть выделенный сервер хранения, вы цените простоту администрирования и мощь ZFS, нуждаетесь в интеграции с другими системами (виртуализация через iSCSI).
  • Выбирайте Ceph/Rook, если: вы строите cloud-native платформу, хотите максимальной отказоустойчивости и горизонтального масштабирования хранилища вместе с кластером K8s, готовы выделить под хранение часть ресурсов рабочих узлов.

Оба варианта позволяют обеспечить локализацию данных, что критично для соответствия требованиям 152-ФЗ.

Пошаговое развертывание CSI-драйвера для TrueNAS SCALE

1. Предварительные требования: Настроенный кластер TrueNAS SCALE с созданным ZFS pool (например, k8s-pool) и dataset внутри него (например, k8s-pool/volumes). Включенный API доступ с созданным ключом.

2. Установка драйвера: Самый простой способ - установка через Helm chart. Добавьте репозиторий и установите релиз.

helm repo add truenas https://truenas.github.io/charts
helm repo update
helm install truenas-csi truenas/truenas-csi --namespace kube-system

3. Конфигурация Secret: Создайте Secret с данными для подключения к TrueNAS API. Никогда не храните эти данные в открытом виде в манифестах.

apiVersion: v1
kind: Secret
metadata:
  name: truenas-csi-secret
  namespace: kube-system
type: Opaque
stringData:
  url: "https://truenas.local"
  apiKey: "ваш-секретный-ключ-api"

4. Проверка установки: Убедитесь, что драйвер зарегистрирован.

kubectl get csidrivers.storage.k8s.io

После этого можно создавать StorageClass, как показано в предыдущем разделе.

Пошаговое развертывание распределенного хранилища с Rook Ceph

1. Требования к узлам: На каждом узле Kubernetes, который будет использоваться для хранения, должны быть чистые диски или разделы без файловых систем. Rook займет их полностью.

2. Установка Rook Operator: Клонируйте репозиторий Rook и установите Common и Operator манифесты.

git clone --single-branch --branch v1.14.0 https://github.com/rook/rook.git
cd rook/deploy/examples
kubectl create -f crds.yaml -f common.yaml -f operator.yaml

3. Создание кластера Ceph: Отредактируйте файл cluster.yaml, указав узлы и диски, затем примените его.

kubectl create -f cluster.yaml

4. Создание StorageClass: Для блочных устройств (RBD) создайте StorageClass. Ceph также предоставляет файловое хранилище (CephFS), которое поддерживает режим доступа ReadWriteMany.

kubectl create -f csi/rbd/storageclass.yaml

5. Проверка здоровья: Снапшоты томов Встроенные снапшоты ZFS, интеграция с системой репликации TrueNAS Интеграция с Ceph Snapshots, возможность клонирования Соответствие 152-ФЗ/ФСТЭК Локализация данных на территории РФ, возможность использования сертифицированного ПО Локализация данных, развертывание на отечественном железе

Создание и использование томов: от манифеста PVC до подключения в Pod

После настройки StorageClass работа с хранилищем становится декларативной. Вместо ручных операций вы описываете желаемое состояние в YAML.

Создайте PersistentVolumeClaim, который запросит том размером 10Gi из класса truenas-iscsi-ssd:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data-pvc
spec:
  storageClassName: truenas-iscsi-ssd
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Подключите этот PVC к Pod в спецификации контейнера:

apiVersion: v1
kind: Pod
metadata:
  name: postgres-pod
spec:
  containers:
  - name: postgres
    image: postgres:15
    volumeMounts:
    - mountPath: /var/lib/postgresql/data
      name: data-volume
  volumes:
  - name: data-volume
    persistentVolumeClaim:
      claimName: postgres-data-pvc

Для stateful-приложений, где каждому поду нужен уникальный том, используйте StatefulSet с volumeClaimTemplates. Это автоматически создаст PVC с уникальными именами для каждого экземпляра пода (postgres-0, postgres-1 и т.д.).

Проверьте состояние PVC и подключение:

kubectl get pvc
kubectl describe pod postgres-pod # Ищем секцию Volumes
kubectl exec -it postgres-pod -- df -h /var/lib/postgresql/data

Для более сложных сценариев развертывания приложений, таких как обновления и стратегии масштабирования, изучите наше руководство по Kubernetes Deployment, где вы найдете готовые примеры YAML-манифестов.

Безопасный доступ к данным: SecurityContext, SELinux и разграничение прав

Безопасность данных в томах Kubernetes требует настройки на нескольких уровнях. Основная проблема - несоответствие UID/GID пользователя внутри контейнера и прав на файлы в смонтированном томе.

Используйте securityContext в спецификации Pod или Container, чтобы задать пользователя, от имени которого будет работать процесс:

securityContext:
  runAsUser: 1000
  runAsGroup: 1000
  fsGroup: 1000

Параметр fsGroup особенно важен. При монтировании тома Kubelet изменяет групповое владение корневой директорией тома и всех файлов на указанный GID, обеспечивая контейнеру права на запись.

В средах с включенным SELinux (например, Red Hat OpenShift, некоторые дистрибутивы Kubernetes) необходимо настроить правильный контекст безопасности для томов. По умолчанию контейнеры работают с типом svirt_sandbox_file_t. Если ваш том находится на узле с другим контекстом, монтирование не удастся. Решение - использовать опцию seLinuxOptions в securityContext или настроить правильную политику SELinux для директории хранения данных на узле.

Для изоляции данных между разными командами или проектами используйте пространства имен Kubernetes (Namespaces) и RBAC для ограничения доступа к ресурсам PersistentVolumeClaim в конкретных неймспейсах. Никогда не используйте один том с режимом ReadWriteMany для несвязанных приложений без дополнительных мер контроля доступа на уровне файловой системы.

Вопросы безопасного хранения секретов, таких как пароли БД или API-ключи, выходят за рамки управления томами. Для production-сред рекомендуем ознакомиться с обзором внешних решений в статье Kubernetes Secrets 2026.

Обеспечение отказоустойчивости и жизненный цикл данных: репликация, снапшоты, миграция

Отказоустойчивость данных в Kubernetes обеспечивается не самим K8s, а выбранной системой хранения. При использовании TrueNAS с ZFS это настройка пула с RAID-Z2 или RAID-Z3 и репликация на второй сервер. В случае с Ceph - это репликация данных между 3 или более OSD (серверами хранения) или использование схемы erasure coding.

Снапшоты (snapshots) томов - мощный инструмент для создания point-in-time копий данных перед обновлением приложения или для быстрого восстановления после ошибки. Современные CSI-драйверы поддерживают создание снапшотов через объекты VolumeSnapshotClass и VolumeSnapshot. Восстановление из снапшота создает новый том с данными на момент создания копии.

Миграция томов между узлами кластера происходит автоматически при использовании StatefulSet. Если Pod StatefulSet перезапускается на другом узле, Kubelet на новом узле через CSI-драйвер запросит подключение того же тома (по его уникальному идентификатору). Для этого том должен быть доступен с любого узла кластера (что обеспечивается сетью хранения, например, iSCSI или распределенной файловой системой Ceph).

Резервное копирование данных требует комплексного подхода. Можно использовать инструменты уровня Kubernetes, такие как Velero, которые умеют создавать бэкапы PVC вместе с метаданными и восстанавливать их в другом кластере. Альтернатива - использовать встроенные механизмы хранилища: периодические снапшоты ZFS в TrueNAS с отправкой на удаленный сервер или экспорт снапшотов Ceph RBD. Для приложений в TrueNAS SCALE существует отдельное руководство по резервному копированию Kubernetes-приложений.

План действий при эвакуации узла (drain):
1. Пометить узел как недоступный для планирования: kubectl cordon <node-name>.
2. Аккуратно завершить работу всех подов на узле: kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data.
3. Stateful-поды будут перезапущены на других узлах, их тома будут переподключены автоматически.
4. После обслуживания узла вернуть его в строй: kubectl uncordon <node-name>.

План безопасного внедрения в продакшен: от тестового стенда до production

Внедрение новой системы хранения в production - это рискованный процесс. Следуйте поэтапному плану, чтобы минимизировать вероятность сбоев.

Этап 1: Развертывание в dev/stage среде.
Разверните CSI-драйвер и создайте тестовый StorageClass в не-продакшен кластере или отдельном неймспейсе. Протестируйте полный цикл: создание PVC, подключение к простому Pod (например, с busybox), запись и чтение данных. Имитируйте сбои: удалите Pod, убедитесь, что данные сохранились при пересоздании. Отключите сетевой доступ к хранилищу (TrueNAS) или остановите один из узлов Ceph, наблюдая за поведением приложения.

Этап 2: Нагрузочное тестирование.
Подключите хранилище к типовому stateful-приложению, например, PostgreSQL. Используйте инструмент pgbench для имитации нагрузки. Мониторьте ключевые метрики: использование дискового пространства, IOPS, latency на стороне Kubernetes (метрики CSI) и на стороне самого хранилища (панель управления TrueNAS, дашборды Ceph). Это поможет выявить узкие места и правильно выбрать параметры StorageClass для production.

Этап 3: Пилотное внедрение в prod.
Выберите одно некритичное stateful-приложение в production для миграции на новое хранилище. Например, внутренний сервис кэширования или очередь задач с низкой нагрузкой. Создайте для него новый PVC на основе настроенного StorageClass, перенесите данные (используя дамп/восстановление или утилиты копирования тома) и переключите приложение. Тщательно документируйте каждый шаг.

Контрольные точки и мониторинг:
Настройте алертинг на ключевые метрики: заполнение тома более чем на 80%, резкий рост latency, ошибки монтирования в событиях Pod. Используйте Prometheus для сбора метрик csi (например, csi_sidecar_operations_seconds_bucket) и экспортеров для вашего хранилища.

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

Управление хранилищем - сложная, но решаемая задача в Kubernetes. Используя CSI-драйверы, такие как для TrueNAS или Ceph, и следуя декларативной модели Kubernetes, вы можете построить отказоустойчивую, масштабируемую и безопасную инфраструктуру для любых stateful-приложений. Для более глубокого понимания работы с постоянными данными в распределенных системах рекомендуем также ознакомиться со сравнением подходов в статье про Docker Swarm и Kubernetes.

Если ваша работа связана с интеграцией различных AI-моделей и вам нужен единый API-интерфейс для доступа к GPT, Gemini, Claude и другим нейросетям без необходимости настройки VPN и с оплатой в рублях, обратите внимание на сервис AiTunnel. Этот агрегатор может упростить разработку приложений с использованием искусственного интеллекта.

Поделиться:
Сохранить гайд? В закладки браузера