Короткий ответ
Для приложения с долгим и непредсказуемым стартом нужно добавить startup probe с достаточным суммарным временем ожидания (failureThreshold * periodSeconds), чтобы liveness и readiness не начинали действовать, пока startup не подтвердит готовность процесса — это предотвращает преждевременные перезапуски из-за "медленного" старта.
Как это работает подробнее
пока startup probe не завершится успехом, kubelet не выполняет ни liveness, ни readiness проверки вообще; после успеха startup probe управление переходит к обычным liveness/readiness с их собственными интервалами. Это решает проблему, когда единая liveness probe с коротким таймаутом убивает контейнер ещё до завершения инициализации (прогрев кэша, миграции схемы, подключение к зависимостям).
Пример кода
manifest.yaml
startupProbe:
httpGet: { path: /healthz, port: 8080 }
failureThreshold: 30
periodSeconds: 10
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
periodSeconds: 10
failureThreshold: 3Что использовать на практике
- Практика.
failureThresholdу startup probe стоит рассчитывать с запасом относительно p95/p99 времени старта по данным мониторинга, а не по "обычному" времени — иначе под будет случайно убиваться именно в моменты аномально медленного старта (например, при холодном кэше JVM). Readiness при этом может отдельно проверять готовность конкретно к приёму трафика (например, прогрета ли in-memory карта), даже после того как startup уже подтвердил сам факт живого процесса.
Подводные камни
- Риски. пытаться решить проблему медленного старта только за счёт увеличения
initialDelaySecondsу liveness — это фиксированная задержка, которая либо избыточна для быстрого старта, либо недостаточна для редкого медленного; не разделять startup и liveness, из-за чего приходится делать liveness слишком "мягкой" (большой таймаут), что замедляет обнаружение реальных зависаний уже после старта.