Какие типичные ошибки возникают при создании StatefulSet в Kubernetes?

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

Ответ

StatefulSet — это сложный ресурс для stateful-приложений (базы данных, очереди). Вот ошибки, которые я научился избегать на практике:

  1. Отсутствие Headless Service: StatefulSet полагается на headless-сервис (clusterIP: None) для создания стабильных DNS-записей вида <pod-name>.<svc-name>.<namespace>.svc.cluster.local. Без него pods не смогут находить друг друга по стабильным именам.

    # Обязательный сервис для StatefulSet
    apiVersion: v1
    kind: Service
    metadata:
      name: cassandra-svc
    spec:
      clusterIP: None # Это headless-сервис
      selector:
        app: cassandra
  2. Некорректный volumeClaimTemplate: Самая критичная часть. Ошибка в storageClassName или accessModes (например, ReadWriteOnce для пода, которому нужно общее хранилище) приведёт к тому, что поды не запустятся. В моём проекте с Cassandra мы использовали fast SSD.

    volumeClaimTemplates:
    - metadata:
        name: cassandra-data
      spec:
        accessModes: [ "ReadWriteOnce" ]
        storageClassName: "fast-ssd"
        resources:
          requests:
            storage: 100Gi
  3. Игнорирование podManagementPolicy: По умолчанию используется OrderedReady — поды создаются и удаляются по одному в строгом порядке. Для приложений, которые могут запускаться параллельно (например, некоторые кэши), это излишне медленно. Можно установить Parallel.

    apiVersion: apps/v1
    kind: StatefulSet
    spec:
      podManagementPolicy: Parallel # Ускоряет развёртывание
  4. Забыть про terminationGracePeriodSeconds: Stateful-приложениям (как PostgreSQL или Kafka) нужно время для graceful shutdown — завершить транзакции, слить данные на диск. Слишком маленький grace period может привести к повреждению данных.

    spec:
      template:
        spec:
          terminationGracePeriodSeconds: 300 # 5 минут на graceful shutdown
  5. Предположение, что все поды всегда доступны: Приложения в StatefulSet должны быть спроектированы с учётом того, что реплики могут быть недоступны (например, во время обновления). Жёсткие зависимости в коде приложения (ожидание, что pod-0 всегда онлайн) приведут к сбоям.