StatefulSet, Stateless vs Stateful и Headless Service
1. Stateless vs Stateful: В чем разница?
- Stateless (Без состояния):
- Примеры: Веб-серверы (Nginx), микросервисы.
- Суть: Любой под можно удалить и заменить новым, ничего не потеряв. Данные сессии обычно хранятся во внешнем хранилище (Redis).
- Объект в K8s:
Deployment. - Хранилище: Все реплики могут использовать один и тот же PV/PVC (общая папка).
- Stateful (С состоянием):
- Примеры: Базы данных (PostgreSQL, MySQL), брокеры сообщений (Kafka, RabbitMQ).
- Суть: Каждому поду нужны его собственные уникальные данные. Если
pod-0упал, он должен подняться именно какpod-0и подключиться к своему старому диску. - Объект в K8s:
StatefulSet.
2. Особенности StatefulSet
- Стабильные имена: Поды получают индексы:
web-0,web-1,web-2. При перезагрузке имя сохраняется. - Порядок запуска/удаления: Поды запускаются по очереди (0 -> 1 -> 2) и удаляются в обратном порядке (2 -> 1 -> 0). Это критично для кластеров БД (сначала Master, потом Replica).
- Volume Claim Templates: Вместо одного общего PVC, в StatefulSet описывается шаблон. K8s автоматически создает отдельный PVC для каждой реплики.
- Пример: Для
web-0будет созданdata-web-0, дляweb-1—data-web-1.
- Пример: Для
3. Headless Service (Сервис без IP)
Для баз данных (например, Master-Slave) нам нужно обращаться не к "любому" поду через балансировщик, а к конкретному (например, только к Master для записи).
- Настройка: В манифесте Service указывается
clusterIP: None. - Результат: Сервис не получает виртуальный IP. Вместо этого DNS-запрос к сервису возвращает список IP-адресов всех подов.
- DNS-имя пода: Становится возможным обратиться напрямую к поду по адресу:
<pod-name>.<service-name>.- Пример:
mysql-0.mysql-service.
- Пример:
4. Жизненный цикл и Graceful Shutdown (Мягкое завершение)
Когда K8s удаляет под, он посылает сигнал SIGTERM. По умолчанию у пода есть 30 секунд (terminationGracePeriodSeconds), чтобы закончить работу.
- Проблема: База данных может закрывать транзакции дольше 30 секунд.
- Решение — PreStop Hook: Это команда, которая выполняется перед тем, как под начнет удаляться.
- Пример: Скрипт, который переключает Master на другую ноду или корректно завершает сессии.
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 60"] # Даем приложению время доработать
5. Практический пример: Кластер PostgreSQL
Для создания полноценного кластера БД в K8s требуется связка:
- ConfigMap: Скрипты инициализации и настройки репликации.
- Secret: Пароли для суперпользователя и репликации.
- Headless Service: Для связи между узлами (Master видит Slave-ов).
- Standard Service: Для чтения (Read-only балансировщик между всеми узлами).
- StatefulSet: Сами поды с БД и
volumeClaimTemplatesдля дисков.
Главные выводы урока:
- Используйте StatefulSet, если приложению важна идентичность (имя и диск).
- Headless Service необходим для того, чтобы компоненты кластера (например, узлы MySQL) знали адреса друг друга напрямую.
- PreStop Hooks — обязательная настройка для баз данных, чтобы избежать повреждения данных при перезагрузке нод или обновлении кластера.