Тот кто начинал работать с Kubernetes с большой долей вероятности хоть раз задумывался: "А норм будет, если я запущу базу данных в обычном Deployment и просто подключу к нему PersistentVolume?"
К сожалению, всё не так просто💀 Если так сделать, это приведет к легкому хаосу с данными и сетью при первом же рестарте или попытке масштабироваться. Сегодня разберемся почему и зачем для этого придумали StatefulSet и в чем фундаментальная разница
Deployment - контроллер для управления репликами приложений, которые не хранят локальное состояние
• Поды взаимозаменяемы, т.е. любой под может обработать любой запрос
• При создании пода генерируется имя с рандомным хэшем (например, api-deployment-7d89b8f-x9z2p)
• При увеличении реплик все новые поды создаются одновременно, а вот при уменьшении - удаляются произвольно
• Все поды находятся за одним Service (ClusterIP), который балансирует трафик между ними
StatefulSet - контроллер для управления приложениями, которым критически важны стабильность и порядок. Такой контроллер даёт три строгие гарантии, которых нет в Deployment
• Стабильный сетевой идентификатор
Поды получают предсказуемые имена по шаблону: <имя-statefulset>-<порядковый_индекс> (например, kafka-0, kafka-1, kafka-2). В паре с Headless Service это даёт стабильные DNS-записи: kafka-0.kafka-svc.default.svc.cluster.local
• Стабильное и постоянное хранилище
Используется volumeClaimTemplates. При создании StatefulSet для каждого пода автоматически создаётся уникальный PersistentVolumeClaim (PVC). Если под postgres-0 упадёт и пересоздастся на другой ноде, он заберёт свой же диск с данными. В Deployment такой привязки нет
• Упорядоченное, предсказуемое развертывание и масштабирование
Создание строго по порядку (0 → 1 → 2). Следующий под не начнёт создаваться, пока предыдущий не перейдёт в статус Running и Ready. Удаление/Даунскейл тоже строго в порядке, но уже обратном (2 → 1 → 0). Обновление, также идёт в обратном порядке, начиная с последней реплики
А по итогу, когда и что использовать🤔
Всё просто:
• Если приложение stateless (например, веб-серверы (Nginx), бэкенд-API, воркеры очередей, микросервисы, которые хранят всё состояние во внешней БД или кэше (Redis/Memcached)), то используем Deployment
• Если же приложение stateful и требует координации (реляционные и NoSQL базы данных (PostgreSQL, MongoDB, Cassandra), брокеры сообщений (Kafka, RabbitMQ), распределённые системы координации (Zookeeper, etcd)), то смело используем StatefulSet

