Развертывание 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. Проверка здоровья:
После настройки StorageClass работа с хранилищем становится декларативной. Вместо ручных операций вы описываете желаемое состояние в YAML. Создайте PersistentVolumeClaim, который запросит том размером 10Gi из класса Подключите этот PVC к Pod в спецификации контейнера: Для stateful-приложений, где каждому поду нужен уникальный том, используйте StatefulSet с Проверьте состояние PVC и подключение: Для более сложных сценариев развертывания приложений, таких как обновления и стратегии масштабирования, изучите наше руководство по Kubernetes Deployment, где вы найдете готовые примеры YAML-манифестов. Безопасность данных в томах Kubernetes требует настройки на нескольких уровнях. Основная проблема - несоответствие UID/GID пользователя внутри контейнера и прав на файлы в смонтированном томе. Используйте Параметр В средах с включенным SELinux (например, Red Hat OpenShift, некоторые дистрибутивы Kubernetes) необходимо настроить правильный контекст безопасности для томов. По умолчанию контейнеры работают с типом Для изоляции данных между разными командами или проектами используйте пространства имен 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-драйверы поддерживают создание снапшотов через объекты Миграция томов между узлами кластера происходит автоматически при использовании StatefulSet. Если Pod StatefulSet перезапускается на другом узле, Kubelet на новом узле через CSI-драйвер запросит подключение того же тома (по его уникальному идентификатору). Для этого том должен быть доступен с любого узла кластера (что обеспечивается сетью хранения, например, iSCSI или распределенной файловой системой Ceph). Резервное копирование данных требует комплексного подхода. Можно использовать инструменты уровня Kubernetes, такие как Velero, которые умеют создавать бэкапы PVC вместе с метаданными и восстанавливать их в другом кластере. Альтернатива - использовать встроенные механизмы хранилища: периодические снапшоты ZFS в TrueNAS с отправкой на удаленный сервер или экспорт снапшотов Ceph RBD. Для приложений в TrueNAS SCALE существует отдельное руководство по резервному копированию Kubernetes-приложений. План действий при эвакуации узла (drain): Внедрение новой системы хранения в production - это рискованный процесс. Следуйте поэтапному плану, чтобы минимизировать вероятность сбоев. Этап 1: Развертывание в dev/stage среде. Этап 2: Нагрузочное тестирование. Этап 3: Пилотное внедрение в prod. Контрольные точки и мониторинг: Инструкция по откату: Управление хранилищем - сложная, но решаемая задача в Kubernetes. Используя CSI-драйверы, такие как для TrueNAS или Ceph, и следуя декларативной модели Kubernetes, вы можете построить отказоустойчивую, масштабируемую и безопасную инфраструктуру для любых stateful-приложений. Для более глубокого понимания работы с постоянными данными в распределенных системах рекомендуем также ознакомиться со сравнением подходов в статье про Docker Swarm и Kubernetes. Если ваша работа связана с интеграцией различных AI-моделей и вам нужен единый API-интерфейс для доступа к GPT, Gemini, Claude и другим нейросетям без необходимости настройки VPN и с оплатой в рублях, обратите внимание на сервис AiTunnel. Этот агрегатор может упростить разработку приложений с использованием искусственного интеллекта.Снапшоты томов
Встроенные снапшоты ZFS, интеграция с системой репликации TrueNAS
Интеграция с Ceph Snapshots, возможность клонирования
Соответствие 152-ФЗ/ФСТЭК
Локализация данных на территории РФ, возможность использования сертифицированного ПО
Локализация данных, развертывание на отечественном железе
Создание и использование томов: от манифеста PVC до подключения в Pod
truenas-iscsi-ssd:apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data-pvc
spec:
storageClassName: truenas-iscsi-ssd
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
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
volumeClaimTemplates. Это автоматически создаст PVC с уникальными именами для каждого экземпляра пода (postgres-0, postgres-1 и т.д.).kubectl get pvc
kubectl describe pod postgres-pod # Ищем секцию Volumes
kubectl exec -it postgres-pod -- df -h /var/lib/postgresql/data
Безопасный доступ к данным: SecurityContext, SELinux и разграничение прав
securityContext в спецификации Pod или Container, чтобы задать пользователя, от имени которого будет работать процесс:securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroup особенно важен. При монтировании тома Kubelet изменяет групповое владение корневой директорией тома и всех файлов на указанный GID, обеспечивая контейнеру права на запись.svirt_sandbox_file_t. Если ваш том находится на узле с другим контекстом, монтирование не удастся. Решение - использовать опцию seLinuxOptions в securityContext или настроить правильную политику SELinux для директории хранения данных на узле.Обеспечение отказоустойчивости и жизненный цикл данных: репликация, снапшоты, миграция
VolumeSnapshotClass и VolumeSnapshot. Восстановление из снапшота создает новый том с данными на момент создания копии.
1. Пометить узел как недоступный для планирования: kubectl cordon <node-name>.
2. Аккуратно завершить работу всех подов на узле: kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data.
3. Stateful-поды будут перезапущены на других узлах, их тома будут переподключены автоматически.
4. После обслуживания узла вернуть его в строй: kubectl uncordon <node-name>.План безопасного внедрения в продакшен: от тестового стенда до production
Разверните CSI-драйвер и создайте тестовый StorageClass в не-продакшен кластере или отдельном неймспейсе. Протестируйте полный цикл: создание PVC, подключение к простому Pod (например, с busybox), запись и чтение данных. Имитируйте сбои: удалите Pod, убедитесь, что данные сохранились при пересоздании. Отключите сетевой доступ к хранилищу (TrueNAS) или остановите один из узлов Ceph, наблюдая за поведением приложения.
Подключите хранилище к типовому stateful-приложению, например, PostgreSQL. Используйте инструмент pgbench для имитации нагрузки. Мониторьте ключевые метрики: использование дискового пространства, IOPS, latency на стороне Kubernetes (метрики CSI) и на стороне самого хранилища (панель управления TrueNAS, дашборды Ceph). Это поможет выявить узкие места и правильно выбрать параметры StorageClass для production.
Выберите одно некритичное stateful-приложение в production для миграции на новое хранилище. Например, внутренний сервис кэширования или очередь задач с низкой нагрузкой. Создайте для него новый PVC на основе настроенного StorageClass, перенесите данные (используя дамп/восстановление или утилиты копирования тома) и переключите приложение. Тщательно документируйте каждый шаг.
Настройте алертинг на ключевые метрики: заполнение тома более чем на 80%, резкий рост latency, ошибки монтирования в событиях Pod. Используйте Prometheus для сбора метрик csi (например, csi_sidecar_operations_seconds_bucket) и экспортеров для вашего хранилища.
Перед миграцией критического приложения обязательно создайте снапшот его текущего тома или полную резервную копию средствами старого хранилища. В случае проблем с новым хранилищем вы сможете быстро восстановить работу, подключив приложение к старому, проверенному тому, используя его идентификатор или восстановив из снапшота.