StatefulSet в Kubernetes: полное руководство с примерами для PostgreSQL/MySQL | Практика | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

StatefulSet в Kubernetes: полное руководство с примерами для PostgreSQL/MySQL | Практика

28 мая 2026 9 мин. чтения

Зачем нужен StatefulSet? Ключевые отличия от Deployment

StatefulSet - это специализированный контроллер Kubernetes для управления приложениями, которые хранят состояние. Он обеспечивает стабильные идентификаторы подов, упорядоченное развертывание и гарантированное постоянное хранилище данных. Это критически важно для баз данных, систем очередей сообщений и кластерных хранилищ. Использование стандартного Deployment для таких задач приводит к потере данных при пересоздании подов и нарушению сетевой идентичности.

Выбор между Deployment и StatefulSet определяет надежность и корректность работы вашего приложения в кластере. Это фундаментальное архитектурное решение. Чтобы избежать ошибок, стоит рассмотреть сравнение основных контроллеров Kubernetes, включая DaemonSet и Job, в практическом руководстве по выбору контроллера.

Stateless vs Stateful: в чем принципиальная разница для Kubernetes?

Stateless-приложение не хранит уникальные данные внутри своего экземпляра. Веб-сервер или API-микросервис обрабатывает запросы независимо от предыдущих. Сессии и данные хранятся во внешнем хранилище, например Redis. Любой под идентичен другому, их можно создавать и удалять произвольно. Это «безликие солдаты», которые выполняют одинаковую работу.

Stateful-приложение хранит уникальное состояние. Каждый экземпляр базы данных PostgreSQL или узла Kafka содержит данные, которые не могут быть потеряны или перемещены на другой под без специальных процедур. Эти приложения требуют стабильных сетевых идентификаторов и предсказуемого порядка операций. Они работают как «специалисты с именем и ролью»: pod-0 может быть мастером, pod-1 и pod-2 - репликами.

Сравнительная таблица: Deployment vs StatefulSet

Характеристика Deployment StatefulSet
Имя пода Генерируется случайно: pod-{random-string} Стабильное, с порядковым номером: statefulset-name-{0,1,2}
Порядок запуска и обновления Произвольный или параллельный Строгий порядок по порядковым номерам (ordinals): 0, затем 1, затем 2
Хранилище Общее или временное. При пересоздании пода данные могут потеряться. Уникальный PersistentVolumeClaim (PVC) для каждого пода. PVC сохраняется при удалении пода и повторно подключается.
Сетевая идентичность Динамический ClusterIP сервис. Поды получают случайные IP. Стабильный DNS через Headless Service: pod-0.statefulset-service.namespace.svc.cluster.local
Сценарии использования Веб-приложения, API, микросервисы без уникального состояния. Базы данных (MySQL, PostgreSQL), очереди сообщений (Kafka), кластерные хранилища (etcd).

StatefulSet обязателен для приложений, где важен порядок операций, например при формировании кластера БД, или где каждый экземпляр хранит уникальные данные. Использование Deployment для таких задач приводит к потере данных при пересоздании пода и нарушению репликации.

Архитектура StatefulSet: Pod, Ordinals и стабильное хранилище

Механизм StatefulSet построен на трех ключевых концепциях: порядковые номера подов (ordinals), стабильные сетевые идентификаторы и шаблоны запросов на постоянное хранилище (VolumeClaimTemplates). Эта архитектура гарантирует предсказуемое поведение, необходимое для stateful-сервисов.

Стабильные идентификаторы Pod: основа предсказуемости

StatefulSet присваивает подам уникальные и неизменные порядковые номера: 0, 1, 2 и так далее. Имя пода формируется как statefulset-name-{ordinal}, например postgresql-cluster-0. Этот идентификатор сохраняется на протяжении всего жизненного цикла пода, даже при его ресхедуле на другой узёл кластера.

Для обеспечения стабильной сетевой идентификации используется Headless Service (сервис без ClusterIP). Он создает DNS-записи для каждого пода: postgresql-cluster-0.postgresql-service.default.svc.cluster.local. Это позволяет другим компонентам системы, например репликам базы данных, постоянно обращаться к мастеру по известному имени. Конфигурация репликации PostgreSQL может жестко ссылаться на postgresql-cluster-0 как на мастер. Правильное именование подов, особенно в сложных сценариях с версиями приложений, требует внимания. Рекомендации и шаблоны для 2026 года собраны в руководстве по именованию подов Kubernetes.

VolumeClaimTemplates: как обеспечить каждому Pod свое постоянное хранилище

Ключевой механизм привязки хранилища в StatefulSet - секция volumeClaimTemplates в манифесте. Это шаблон для создания PersistentVolumeClaims (PVC). При создании каждого нового пода StatefulSet автоматически генерирует для него уникальный PVC по этому шаблону. PVC получает имя data-statefulset-name-{ordinal}.

Когда под удаляется или перемещается, его PVC сохраняется в кластере. При создании нового пода с тем же порядковым номером StatefulSet подключает к нему тот же PVC, гарантируя сохранность данных. Это критически важно для баз данных. PVC не удаляется автоматически при удалении StatefulSet, что защищает данные от случайной очистки. Правильный выбор StorageClass в шаблоне определяет производительность и надежность хранилища. Для БД рекомендуется использовать классы, предоставляющие быстрые диски, такие как SSD или NVMe.

Практика: развертывание PostgreSQL с StatefulSet (готовый пример)

Развертывание PostgreSQL в кластере Kubernetes с использованием StatefulSet обеспечивает стабильную работу, сохранность данных и возможность масштабирования. Ниже представлен готовый, проверенный YAML-манифест для запуска одного мастер-пода с постоянным хранилищем.

Разбор YAML-манифеста: ключевые секции и их настройка

Манифест состоит из трех основных объектов: Headless Service для сетевой идентификации, StatefulSet для управления подами и обычного Service для внешнего подключения.

# Headless Service для стабильных DNS-имен подов
apiVersion: v1
kind: Service
metadata:
  name: postgresql-service
spec:
  clusterIP: None # Headless Service
  selector:
    app: postgresql
---
# StatefulSet для управления подами PostgreSQL
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgresql-cluster
spec:
  serviceName: postgresql-service
  replicas: 1
  selector:
    matchLabels:
      app: postgresql
  template:
    metadata:
      labels:
        app: postgresql
    spec:
      containers:
      - name: postgresql
        image: postgres:15
        ports:
        - containerPort: 5432
        env:
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: postgresql-secret
              key: password
        volumeMounts:
        - name: postgresql-data
          mountPath: /var/lib/postgresql/data
        resources:
          requests:
            memory: "2Gi"
            cpu: "500m"
          limits:
            memory: "4Gi"
            cpu: "1"
        readinessProbe:
          tcpSocket:
            port: 5432
          initialDelaySeconds: 30
          periodSeconds: 10
  volumeClaimTemplates:
  - metadata:
      name: postgresql-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "ssd" # Используйте существующий StorageClass
      resources:
        requests:
          storage: 10Gi
---
# Service для внешнего подключения к PostgreSQL
apiVersion: v1
kind: Service
metadata:
  name: postgresql-external
spec:
  type: NodePort
  selector:
    app: postgresql
  ports:
  - port: 5432
    targetPort: 5432
    nodePort: 30432

Ключевые секции и их параметры:

  1. Headless Service: spec.clusterIP: None создает DNS-записи для каждого пода, но не назначает ClusterIP.
  2. StatefulSet:
    • serviceName указывает на Headless Service.
    • replicas: 1 определяет количество подов. Для масштабирования кластера БД это значение можно увеличить.
    • В секции контейнера задается образ postgres:15, порт и переменная окружения POSTGRES_PASSWORD, которая должна быть взята из предварительно созданного Secret.
    • volumeMounts монтирует PVC в директорию данных PostgreSQL.
    • resources ограничивает потребление памяти и CPU. Для стабильной работы PostgreSQL рекомендуется выделять от 2 до 4 ГБ оперативной памяти.
    • readinessProbe проверяет готовность БД принимать соединения.
  3. volumeClaimTemplates:
    • accessModes: [ "ReadWriteOnce" ] - режим доступа, позволяющий монтировать том только на один под.
    • storageClassName: "ssd" - класс хранилища. Для production-БД рекомендуется использовать быстрые NVMe-накопители.
    • storage: 10Gi - размер дискового пространства.

Для применения манифеста используйте команду kubectl apply -f postgresql-statefulset.yaml. Убедитесь, что в кластере существует StorageClass с именем "ssd" и Secret с паролем. Для более глубокого понимания работы контроллеров Kubernetes, включая их внутренние механизмы взаимодействия, можно обратиться к разбору архитектуры контроллеров Kubernetes.

Первоначальная проверка и подключение к базе данных

После применения манифеста проверьте состояние созданных объектов:

kubectl get statefulset
kubectl get pods
kubectl get pvc
kubectl get services

Ожидаемый вывод: StatefulSet должен быть готов, поды в статусе Running, PVC в статусе Bound, сервисы созданы.

Для подключения к базе данных изнутри кластера можно использовать команду:

kubectl exec -it postgresql-cluster-0 -- psql -U postgres

Для подключения снаружи, используя NodePort сервис, обратитесь к любому узлу кластера по порту 30432. Создайте тестовую таблицу для проверки:

CREATE TABLE test (id SERIAL PRIMARY KEY, name VARCHAR(50));
INSERT INTO test (name) VALUES ('StatefulSet test');
SELECT * FROM test;

Эта проверка подтверждает успешное развертывание и работоспособность базы данных.

Управление жизненным циклом: обновление, масштабирование и удаление

Операции с работающим StatefulSet требуют понимания его предсказуемого поведения, основанного на порядковых номерах. Обновление, масштабирование и удаление должны выполняться с учетом сохранности данных.

Стратегии обновления: RollingUpdate vs OnDelete

StatefulSet поддерживает две стратегии обновления, задаваемые в поле .spec.updateStrategy.type.

RollingUpdate (по умолчанию): обновление происходит последовательно, в обратном порядке порядковых номеров. Сначала обновляется pod с наибольшим номером (например, pod-2), затем pod-1, и только потом pod-0. Контроллер ожидает, чтобы новый под стал готов (readinessProbe успешна), перед тем как остановить предыдущий. Эта стратегия подходит для приложений, поддерживающих параллельную работу разных версий, например некоторых систем очередей.

OnDelete: StatefulSet не начинает обновление автоматически после изменения манифеста. Обновление происходит только после ручного удаления каждого пода. Порядок действий: обновить манифест (например, изменить версию образа), затем вручную удалять пода по одному, начиная с наибольшего ordinal: kubectl delete pod postgresql-cluster-2. Эта стратегия предпочтительна для критических stateful-приложений, таких как базы данных, где требуется ручная проверка или миграция данных между версиями перед удалением старого пода.

Для инициирования обновления при любой стратегии необходимо изменить манифест (например, версию образа в spec.template) и выполнить команду kubectl apply -f postgresql-statefulset.yaml.

Безопасное масштабирование и удаление без потери данных

Масштабирование вверх: увеличение количества реплик выполняется командой kubectl scale statefulset postgresql-cluster --replicas=3. StatefulSet создаст новые пода с порядковыми номерами 1 и 2, а также автоматически создаст для них PVC по шаблону volumeClaimTemplates.

Масштабирование вниз: уменьшение реплик командой kubectl scale statefulset postgresql-cluster --replicas=1 удалит пода с наибольшими порядковыми номерами (pod-2, затем pod-1). PVC для удаленных подов НЕ удаляется автоматически. Они остаются в кластере и могут быть подключены позже, если масштабирование будет увеличено обратно.

Полное удаление StatefulSet с сохранением данных: для удаления контроллера без удаления подов и данных используется команда с каскадным режимом orphan:
kubectl delete statefulset postgresql-cluster --cascade=orphan
После этого StatefulSet удаляется, но пода и их PVC остаются. Поды можно удалить отдельно командой kubectl delete pod. PVC и данные сохраняются. Для полной очистки инфраструктуры PVC необходимо удалить вручную: kubectl delete pvc. Это гарантирует сохранность данных в production-среде.

Эти операции являются частью ежедневной работы DevOps инженера. Для получения других практических инструкций по управлению инфраструктурой можно обратиться к сборнику руководств по DevOps и Linux администрированию 2026.

Типичные проблемы и их решение

Работа с StatefulSet может сопровождаться специфическими проблемами, связанными с хранилищем, сетью или порядком операций. Системный подход к диагностике позволяет быстро найти и устранить причину.

Диагностика: как понять, что StatefulSet работает некорректно?

Последовательность команд для проверки состояния:

  1. kubectl get statefulset,pods,pvc -o wide - показывает общий статус объектов и их связь.
  2. kubectl describe statefulset <name> - выводит детальную информацию, включая события (Events). В событиях часто указываются причины ошибок, например невозможность создать PVC.
  3. kubectl describe pod <pod-name> - анализируйте секции Conditions и Events. Ошибка "pod has unbound immediate PersistentVolumeClaims" указывает на проблему с хранилищем.
  4. kubectl logs <pod-name> - просмотр логов контейнера помогает найти ошибки инициализации приложения, например неправильные настройки подключения к БД.

Анализ вывода позволяет локализовать проблему: невозможность примонтировать том, ошибки инициализации контейнера, сбои readinessProbe.

PVC в статусе Pending и другие проблемы с хранилищем

Статус Pending для PVC - самая распространенная проблема при работе с StatefulSet. Основные причины и решения:

  • Несуществующий или неправильно указанный storageClassName. Проверьте доступные классы хранилища в кластере: kubectl get storageclass. Убедитесь, что имя класса в volumeClaimTemplates соответствует одному из существующих. Для production-БД рекомендуется использовать классы, предоставляющие быстрые диски, например NVMe.
  • Отсутствие доступных PersistentVolumes в пуле провайдера. В облачных кластерах динамическое создание PV может быть ограничено квотами или проблемами провайдера. Проверьте логи соответствующего сервиса (например, Cloud Controller Manager).
  • Исчерпание квот на хранилище в namespace. Проверьте квоты: kubectl describe quota.

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

Другие частые проблемы:

  • Сбои readinessProbe: неправильные настройки порта или времени ожидания для БД. Увеличьте initialDelaySeconds, если приложение долго инициализируется.
  • Проблемы с правами доступа к директории данных: контейнер может не иметь прав на запись в примонтированный PVC. Используйте securityContext.fsGroup в спецификации пода для установки правильной группы.

Для автоматизации и управления подобными инфраструктурными задачами можно использовать специализированные сервисы, например AiTunnel, который предоставляет единый интерфейс для работы с более чем 200 моделями нейросетей, включая GPT и Claude, и может помочь в генерации конфигураций или скриптов для диагностики.

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