Что такое StatefulSet в Kubernetes?

«Что такое StatefulSet в Kubernetes?» — вопрос из категории Kubernetes, который задают на 33% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

StatefulSet — это контроллер рабочей нагрузки в Kubernetes, предназначенный для развертывания и управления stateful-приложениями, которым требуется сохранение состояния, стабильные сетевые идентификаторы и гарантированный порядок развертывания.

Ключевые отличия от Deployment:

  • Стабильные идентификаторы подов: Каждому поду присваивается предсказуемое и неизменяемое имя (например, app-0, app-1), которое сохраняется при перезапуске.
  • Стабильное сетевое имя: Каждый под получает DNS-имя по шаблону: $(pod-name).$(service-name).$(namespace).svc.cluster.local.
  • Упорядоченное развертывание и масштабирование: Поды создаются и удаляются последовательно (от 0 до N-1), что критично для кластерных приложений.
  • Устойчивое хранилище: Используя volumeClaimTemplates, каждому поду выделяется свой уникальный PersistentVolumeClaim (PVC). При пересоздании пода он подключается к тому же тому.

Типичные сценарии использования:

  • Кластеры баз данных (MySQL, PostgreSQL, MongoDB).
  • Системы обмена сообщениями (Kafka, RabbitMQ).
  • Кэши и хранилища данных (Redis, Elasticsearch, Cassandra).

Пример манифеста для StatefulSet с MySQL:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-hs # Обязательно указывается Headless Service
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
  volumeClaimTemplates: # Шаблон для создания PVC для каждого пода
  - metadata:
      name: mysql-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi