Liveness, readiness и startup-пробы в Kubernetes: как настроить
Практика3 минРедакция Innovialabs
Коротко
Liveness перезапускает зависший контейнер, readiness снимает под с трафика, пока он не готов, а startup даёт медленному приложению время запуститься — liveness должна быть простой и никогда не зависеть от базы данных.
Коротко
В Kubernetes три пробы, и каждая отвечает за своё действие:
| Проба | Какой вопрос задаёт | Что происходит при провале |
|---|---|---|
| Liveness | Процесс завис безнадёжно? | kubelet перезапускает контейнер |
| Readiness | Может ли под сейчас обслуживать запросы? | Под исключается из endpoints сервиса, без перезапуска |
| Startup | Приложение закончило запуск? | Liveness и readiness ждут; если проба так и не прошла, контейнер перезапускается |
Без проб Kubernetes знает только, что процесс запущен. Сервер в дедлоке или приложение, которое ещё прогревает кэш, продолжат получать трафик.
Три способа проверки
HTTP — самый частый вариант для веб-сервисов. Успехом считается любой статус от 200 до 399.
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
failureThreshold: 3
TCP — проверяет только, что порт принимает соединения. Подходит для баз данных, брокеров и не-HTTP сервисов.
livenessProbe:
tcpSocket:
port: 5432
periodSeconds: 10
Exec — выполняет команду в контейнере; код выхода 0 означает «здоров».
livenessProbe:
exec:
command: ["sh", "-c", "test -f /tmp/healthy"]
periodSeconds: 10
Есть и gRPC-пробы для сервисов со стандартным gRPC health-протоколом. Exec-проба запускает процесс при каждой проверке, поэтому команда должна быть лёгкой.
Разумная полная настройка
containers:
- name: api
image: registry.example.com/api:2.1.0
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 5
failureThreshold: 30
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 2
Здесь startup-проба даёт на запуск до 30 × 5 = 150 секунд. После её успеха работу продолжают liveness и readiness.
Что должен проверять каждый эндпоинт
- /healthz (liveness): только сам процесс. Отвечает ли он вообще, жив ли основной цикл. Никаких внешних вызовов.
- /ready (readiness): может ли этот экземпляр делать полезную работу: прогрет, не в процессе остановки, критичные локальные ресурсы доступны. Проверять зависимость здесь допустимо, если без неё под действительно бесполезен, но продумайте, что будет, когда провалятся все поды сразу.
- Startup: часто тот же эндпоинт, что и liveness, только с большим запасом попыток.
Как подобрать задержки и пороги
Основные поля:
periodSeconds— как часто проверять.timeoutSeconds— сколько ждать ответа. Значение по умолчанию небольшое, и медленный эндпоинт начнёт проваливаться под нагрузкой.failureThreshold— сколько провалов подряд до действия.successThreshold— сколько успехов подряд для восстановления (для liveness и startup только 1).initialDelaySeconds— пауза перед первой проверкой. При наличии startup-пробы обычно не нужна.
Примерное время реакции — periodSeconds × failureThreshold. Liveness делайте терпимой (перезапуск дорог), readiness — быстрой (снять трафик дёшево и обратимо).
Частые ошибки
- Проверка базы данных в liveness. При кратком сбое БД все поды проваливают пробу и перезапускаются одновременно. Перезапуск не чинит базу и добавляет нагрузку, когда она поднимется.
- Один эндпоинт и одинаковые пороги для liveness и readiness. Теряется разница между «не шли трафик» и «перезапусти меня».
- Огромный
initialDelaySecondsвместо startup-пробы. Он замедляет каждый перезапуск, а не только первый старт. - Слишком жёсткие таймауты: занятый, но здоровый под убивают в пик нагрузки, и нагрузка на остальные растёт.
- Тяжёлые health-обработчики, которые опрашивают много сервисов или выделяют много памяти.
- Нет readiness вообще: при rolling update новые поды получают трафик раньше, чем готовы.