Kubernetes liveness и readiness probes: не убивай поды зря
liveness, readiness и startup probes в Kubernetes. Разница между ними, когда что использовать. Типичные ошибки: liveness
Всем привет. Если вы когда-нибудь видели, как ваш под в Kubernetes уходит в бесконечный цикл перезапусков (CrashLoopBackOff) или трафик внезапно перестаёт приходить на здоровое приложение — скорее всего, проблема в неправильно настроенных пробах. Это один из тех инструментов, который, будучи настроенным «на коленке», создаёт больше проблем, чем решает. Давайте разберёмся, как настроить liveness, readiness и startup probes правильно, чтобы они работали на вас, а не против вас.
Три кита здоровья пода
Kubernetes даёт нам три типа проб, и каждый решает свою задачу.
Liveness Probe отвечает на вопрос «Жив ли процесс?». Если проба падает, kubelet убивает контейнер и перезапускает его. Это лекарство от ситуаций, когда процесс «завис» (например, deadlock в приложении), но продолжает висеть в памяти. Используйте её для реанимации «мёртвого» состояния.
Readiness Probe отвечает на вопрос «Готов ли контейнер принимать трафик?». Если проба падает, под удаляется из эндпоинтов Service. Это критически важно для плавного запуска, graceful shutdown и ситуаций, когда вашему приложению нужно на время отказаться от нагрузки (например, при высокой загрузке БД или кэша).
Startup Probe — специальный «охранник» для медленно стартующих приложений. Пока startup проба не станет успешной, liveness и readiness пробы не активируются. Это спасает от ситуации, когда liveness убивает под ещё на фазе старта.
Практическая настройка: от общего к частному
Рассмотрим конфигурацию для условного веб-приложения на Go, которое при старте подключается к БД и кэшу, и может долго инициализироваться.
apiVersion: v1
kind: Pod
metadata:
name: example-app
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /health/startup
port: 8080
failureThreshold: 30 # Даём 30 попыток
periodSeconds: 5 # Проверяем каждые 5 секунд
# Итого: 30 * 5 = 150 секунд на старт
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
failureThreshold: 3
# Пода удалится из Service после 3 неудачных проверок подряд (15 сек)
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30 # Ждём, пока пройдёт startup
periodSeconds: 10
failureThreshold: 1
# Одна неудача -> немедленный restart контейнера
Ключевые моменты:
- Эндпоинты должны быть лёгкими.
/health/readyможет проверять доступность внешних зависимостей (БД, кэш, очереди), а/health/live— только внутреннее состояние (например, не закончилась ли память). - failureThreshold для startup считайте по формуле:
failureThreshold * periodSeconds= максимальное время старта вашего приложения. - initialDelaySeconds для liveness должен быть больше времени успешного завершения startupProbe.
Типичные грабли, на которые лучше не наступать
1. Liveness убивает под на старте. Классическая ошибка. Без startupProbe вы вынуждены ставить большой initialDelaySeconds в livenessProbe, угадывая время инита. При следующем деплое, если приложение будет стартовать на секунду дольше, liveness убьёт его. Решение — всегда используйте startupProbe для приложений с временем инициализации > 30 секунд.
2. Readiness блокирует трафик при кратковременной нагрузке. Если ваша readiness проба делает тяжёлые проверки (сложный запрос к БД) и имеет failureThreshold: 1, то любой временный лаг в БД выбросит под из балансировщика. Это может вызвать каскадный сбой. Решение: увеличьте failureThreshold до 2-3, чтобы проба прощала кратковременные проблемы, и делайте проверки максимально быстрыми.
3. Liveness и readiness проверяют одно и то же. Это антипаттерн. Если они ходят на один эндпоинт, то при проблеме с внешней зависимостью (например, БД) liveness начнёт убивать поды, хотя проблема не в них. Liveness должна срабатывать только при неисправимом внутреннем сбое самого процесса.
4. Слишком частые проверки. Пробы с periodSeconds: 1 создают значительную нагрузку, особенно если проверка идёт в БД. Для большинства приложений достаточно интервала в 5-10 секунд.
Итог: пробы — это декларация жизненного цикла вашего приложения для оркестратора. Чётко разделяйте концепции «не готов» и «мёртв», давайте приложению достаточно времени на старт и избегайте хрупких проверок. Тогда перезапуски будут осмысленными, а трафик — стабильным.