Learning Platform
Глоссарий Troubleshooting
Урок 13.01 · 20 мин
Средний
ProbeslivenessProbereadinessProbestartupProbekubeletEndpoints

Probes: liveness, readiness, startup

Probes — это механизм, через который kubelet периодически проверяет состояние контейнера. В Kubernetes есть три типа probes, и они отвечают на разные вопросы. Перепутать их — главная причина restart loops в production и провальных задач на CKAD. Все три probes задаются в spec.containers[].livenessProbe / readinessProbe / startupProbe и выполняются kubelet-ом на узле, где запущен Pod — не из control plane, не из Service.


HEALTHCHECK в Dockerfile: проверка живости контейнера

Три probes — три разных вопроса

  • livenessProbe отвечает на вопрос «жив ли процесс, или его надо рестартануть». При failure kubelet убивает контейнер и применяет restartPolicy (по умолчанию Always для Deployment-ов). Use case — детект deadlock, hung process, in-memory corruption. Это последняя инстанция, а не первая линия защиты.
  • readinessProbe отвечает на вопрос «можно ли направлять трафик в этот Pod». При failure kubelet убирает Pod IP из Endpoints соответствующих Services. Контейнер при этом продолжает работать. Use case — temporary unavailability: соединение с БД упало, кэш прогревается, idle-после-deploy.
  • startupProbe (GA с v1.20) отвечает на вопрос «закончился ли начальный warm-up». Пока startup не PASS — kubelet не запускает liveness и readiness probes. После первого success — startup отключается навсегда (для этого экземпляра контейнера), и начинают работать остальные. Use case — slow-starting apps (Java с JIT warmup, миграции БД на старте).
Что делает kubelet при failure каждого probe
livenessProbe FAILkubelet отправляет SIGTERM в контейнер, ждёт terminationGracePeriodSeconds, затем SIGKILL. Дальше создаёт новый контейнер по restartPolicy. Pod остаётся тот же — рестартуется только контейнер внутри Pod, IP и volume сохраняются.
readinessProbe FAILkubelet обновляет Pod.status.conditions[Ready]=False. Endpoint controller убирает PodIP из Endpoints / EndpointSlices для всех Services, чей selector matches. Контейнер живой, kubectl get pod показывает Running 1/1, но трафик не приходит.
startupProbe FAILПока startup не PASS — liveness/readiness вообще не запускаются. Если startup fail-ит дольше чем failureThreshold * periodSeconds — контейнер убивается так же, как при liveness fail. После первого success startup больше не выполняется.

Discovery vs health: ключевая ментальная модель

readiness — это про маршрутизацию трафика. liveness — это про восстановление контейнера. Это разные слои:

  • Service routing смотрит на Endpoints. Endpoints контролируется readinessProbe. Контейнер может быть жив (liveness PASS), но временно не готов принимать трафик (readiness FAIL) — Service вырезает его, остальные replicas принимают нагрузку. Когда зависимость восстановится — readiness PASS, Pod возвращается в Endpoints. Никаких рестартов.
  • Lifecycle контейнера смотрит на liveness. Контейнер может быть в Endpoints (readiness PASS), но если процесс залип (event loop deadlock, например) — liveness FAIL, kubelet убивает его. Новый контейнер стартует — при наличии startupProbe он сначала пройдёт warm-up, readiness probe вернёт его в Endpoints.
NOTE

Если Pod должен быть рестартован, когда зависимость недоступна — это почти всегда ошибка дизайна. Зависимость может быть down минуты или часы, и рестарт никак не помогает. Helps только readinessProbe — Pod снимается из трафика, остальные replicas (если они есть) обслуживают запросы.


startupProbe: зачем он нужен отдельно

До v1.20 единственным способом дать app медленно стартовать был initialDelaySeconds на livenessProbe. Это плохо работало: если приложение обычно стартует за 30 секунд, но иногда — за 90 (cold JVM, медленный диск), initialDelaySeconds: 30 не помогал — после 30 секунд начиналась проба, она fail-ила, contаiner убивался, новый стартовал — restart loop.

Решение в startupProbe:

  • На startup даётся большой запас (например, `failureThreshold: 30 + periodSeconds: 10 = 5 минут максимум**).
  • После первого success — startup отключается и начинает работать агрессивная liveness (`failureThreshold: 3 + periodSeconds: 10 = 30 секунд** до рестарта при настоящем зависании).

Без startupProbe приходится делать ужасный компромисс: либо liveness рестартует медленный, но здоровый процесс на старте, либо liveness настолько ленивая, что зависший контейнер живёт минуты.


Анти-паттерны на старте

1. Liveness too aggressive на slow-starting app. Java apps с 60+ секунд warmup, livenessProbe с initialDelaySeconds: 30, periodSeconds: 10, failureThreshold: 3 — через минуту контейнер убит. Лечится startupProbe.

2. readiness == liveness. Один и тот же endpoint /health используется в обоих probes — они ничего не различают. Когда /health fail-ит, Pod и убирается из Endpoints, и рестартуется. Цель readiness была — оставить контейнер живым, чтобы дать ему время восстановиться. Эффект противоположный.

3. Heavy probe. probe делает SELECT 1 к БД, или дергает downstream HTTP service, или вычисляет что-то тяжёлое. Каждые periodSeconds секунд — нагрузка на app и его dependencies. При большом числе replicas — самый натуральный self-DDoS.

WARNING

Probes — это не «healthcheck endpoints для дашборда». Это горячая обратная связь kubelet-у. Каждое решение здесь — стоит компромисса (рестарт, исключение из Endpoints). Не дергайте downstream-ы из probes без острой необходимости.


Проверка знанийKnowledge check
Контейнер запущен, livenessProbe PASS, но readinessProbe FAIL. Что происходит с трафиком и с самим контейнером?
ОтветAnswer
Контейнер продолжает работать (liveness PASS — kubelet не убивает). Но Pod снят из Endpoints всех Services, чей selector matches — никакого нового трафика по Service. Существующие keep-alive TCP соединения, если они есть, могут продолжаться до закрытия. Это и есть основной use case readiness: temporary unavailability без рестарта.
Проверка знанийKnowledge check
Slow Java app стартует 60 секунд. Без startupProbe настроен только livenessProbe с initialDelaySeconds: 30. Что будет?
ОтветAnswer
После 30 секунд liveness начинает пробить — app ещё в warmup, probe fail-ит. После failureThreshold подряд (default 3) — kubelet kill контейнер. Новый контейнер стартует — опять fail на 30+ секунде — restart loop. Лечение: startupProbe с большим failureThreshold (например, 30 * 10s = 5 минут до сдачи) и livenessProbe — без initialDelaySeconds, потому что startup защищает первую фазу.
Проверка знанийKnowledge check
После какого момента startupProbe перестаёт выполняться?
ОтветAnswer
После первого SUCCESS. Startup probe выполняется ровно до первого PASS, после этого kubelet навсегда (для этого экземпляра контейнера) отключает startup и активирует liveness и readiness. Если контейнер рестартуется (по любой причине) — startup probe начнётся снова для нового container instance.
Проверка знанийKnowledge check
Почему использовать один и тот же endpoint для liveness и readiness — анти-паттерн?
ОтветAnswer
Probes имеют принципиально разные действия при failure: liveness рестартует контейнер, readiness снимает его из Endpoints. Если оба смотрят на одно и то же — оба сработают одновременно. Цель readiness — оставить контейнер живым во время временной деградации (БД отвалилась) — теряется. Контейнер будет рестартован, что не лечит external dependency. Правильно: разные endpoints, liveness смотрит ТОЛЬКО на «процесс жив» (никаких зависимостей), readiness — на готовность обслуживать.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Что делает kubelet при failure livenessProbe?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5