Если кратко: probes — это встроенные проверки состояния контейнера, которыми kubelet и контроллеры (Deployment/ReplicaSet) пользуются, чтобы принимать решения: давать ли Pod трафик, перезапускать ли контейнер и как пережить «долгий старт» приложения без ложных рестартов. На практике правильно настроенные probes — один из самых дешёвых способов повысить стабильность раскаток без усложнения архитектуры.
Три проверки — три разных решения
Kubernetes предоставляет три вида probes:
- readiness — «можно ли направлять трафик в этот Pod прямо сейчас?»
- liveness — «жив ли процесс/контейнер, или его пора перезапустить?»
- startup probe — «контейнер ещё стартует; пока не закончится — не применяйте к нему liveness/readiness»
Главная ошибка новичков — считать, что это одно и то же «healthcheck». На самом деле эти проверки отвечают на разные вопросы и должны быть построены по разным принципам.
Ментальная модель простая: readiness управляет трафиком, liveness управляет рестартами, startup защищает долгий старт от ложных рестартов.
Как Kubernetes реально использует probes
Важно понимать роли компонентов:
- kubelet на ноде запускает проверки и принимает решение перезапустить контейнер при провале
livenessProbe(и при провалеstartupProbe). - Endpoints/EndpointSlice и Service учитывают
readinessProbe: неготовые Pod исключаются из балансировки. - Deployment во время rollout опирается на готовность Pod (через readiness): если новые Pod не становятся Ready, раскатка замирает или откатывается согласно вашей политике.
Отсюда следствие: readiness — это не «мониторинг», это часть маршрутизации. А liveness — не «проверка HTTP 200», а условие для принудительного самоисцеления через рестарт.

Readiness probe: выключатель трафика
readiness должен отвечать строго на вопрос: способно ли приложение обслужить запросы корректно сейчас. Если ответ «нет», Pod должен стать NotReady, чтобы Service перестал отправлять на него трафик.
Что проверять в readiness
Хорошие критерии:
- приложение подняло listener и принимает соединения;
- готовы зависимости, без которых запросы всё равно упадут (например, подключение к БД или завершение критичных миграций, если вы делаете их на старте);
- прогрет критичный кеш или загружена конфигурация;
- воркеры/очереди не в «panic» состоянии, если это веб+воркеры в одном контейнере.
Плохие критерии:
- «проверим, что внешняя БД отвечает вообще всегда» — при временной деградации БД readiness может массово убрать все Pod из трафика и усилить инцидент;
- тяжёлые проверки, которые ходят в несколько сервисов: это увеличивает латентность probe и риск флаппинга.
Типичная схема для HTTP
Для HTTP-приложений удобен отдельный endpoint вроде /readyz, который проверяет минимум: «сервер принимает запрос и способен отдать простой ответ».
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
spec:
replicas: 2
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
containers:
- name: app
image: example/app:1.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /readyz
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
Здесь Pod будет исключён из трафика после трёх подряд провалов readiness. Это часто лучше, чем «сразу выключить»: кратковременный GC-пауз или всплеск CPU не должен мгновенно ронять готовность.
Liveness probe: предохранитель от зависаний
liveness отвечает на вопрос: «контейнер в таком состоянии, что сам не восстановится, и проще его перезапустить». Это защита от deadlock, зависшего event-loop, утечек ресурсов, когда процесс формально жив, но запросы не обслуживаются.
Главное правило liveness
Не делайте liveness слишком умным. Чем умнее liveness, тем выше шанс перезапускать рабочий контейнер из-за проблем вне приложения (сеть, зависимость, короткий всплеск задержек). Лучше пусть liveness отражает «процесс жив и способен отвечать на минимальную проверку».
Типовые варианты:
- tcpSocket — проверяет, что порт слушается (минимальный, но иногда слишком слабый сигнал);
- httpGet — отвечает ли приложение быстро на лёгкий endpoint;
- exec — локальная команда внутри контейнера (например, проверка файла/сокета).
Пример liveness с более «мягкими» порогами
Часто liveness делают менее чувствительным, чем readiness: пусть Pod сначала выйдет из трафика, а перезапуск случится только если проблема длится дольше.
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 6
При таких параметрах перезапуск произойдёт примерно через минуту стабильных провалов. За это время readiness успеет убрать Pod из балансировки, а система — пережить кратковременные проблемы без рестарта.
Startup probe: когда приложение стартует долго
startup probe закрывает распространённую боль: приложения, которые «долго поднимаются» (прогрев JIT, миграции, загрузка больших моделей, компиляция шаблонов), проваливают liveness в первые секунды или минуты и уходят в бесконечный цикл рестартов.
Механика простая: пока startupProbe не успешна, Kubernetes не считает контейнер «запущенным» и не применяет к нему liveness; readiness при этом не даст трафик, пока приложение реально не готово. Это позволяет честно дать время на инициализацию.
startupProbe:
httpGet:
path: /startupz
port: 8080
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 30
Здесь Kubernetes даст контейнеру до 150 секунд на старт (5 секунд × 30 попыток). После успеха startup начинают действовать readiness и liveness.
Кому startup probe нужен почти всегда
- Java/Spring, .NET, крупные Node.js приложения с миграциями на старте;
- приложения, которые на старте проверяют внешние ресурсы и «раскачиваются»;
- контейнеры, где первый запрос разогревает кеши/компиляцию.
Выбор типа проверки: HTTP, TCP или exec
Короткие практические рекомендации:
- HTTP — лучший вариант для веб-приложений, если можете сделать лёгкий endpoint. Важно, чтобы он был быстрым и не делал тяжёлых запросов.
- TCP — подходит для простых сервисов, где факт listening уже многое значит (например, прокси). Но TCP не отличит «порт слушается, а внутри всё умерло».
- exec — полезен, когда нет HTTP, или нужно проверить локальный ресурс (например, наличие сокета). Минус: exec сложнее стандартизировать и тестировать, и он зависит от утилит внутри образа.
Тайминги: как не устроить флаппинг и лишние рестарты
Параметры, которые чаще всего ломают стабильность:
timeoutSeconds— слишком маленький таймаут даёт ложные провалы под нагрузкой;periodSeconds— слишком частые проверки усиливают нагрузку и шанс поймать кратковременный лаг;failureThreshold— слишком маленький порог создаёт «дёрганую» готовность и лишние перезапуски.
Практический подход:
- Для readiness начните с
periodSeconds5–10 иfailureThreshold3–5. - Для liveness делайте проверку реже или порог выше, чем у readiness, чтобы сначала убрать Pod из трафика, а потом уже перезапускать.
- Если старт «плавает» (то 10 секунд, то 60 секунд) — добавьте
startupProbeи выбирайте окно с запасом по p95/p99 времени старта.
Нормальный порядок самовосстановления: Pod стал NotReady, нагрузка ушла; и только если не помогло — liveness перезапускает контейнер.
Как probes влияют на rollout и стабильность Deployment
На стабильность Deployment probes влияют напрямую:
- Если readiness слишком строгий или нестабильный, новые Pod долго не становятся Ready, rollout «зависает».
- Если liveness слишком агрессивный, Pod будут уходить в рестарты прямо во время раскатки, что выглядит как «Deployment не поднимается».
- Startup probe часто является разницей между «всё катится» и «CrashLoopBackOff после каждого деплоя» для тяжёлых приложений.
Отдельно помните про terminationGracePeriodSeconds: при обновлениях и даунскейле Pod завершаются. Если приложение не умеет корректно закрывать соединения, readiness можно использовать как «быстро убрать из трафика», а дальше спокойно завершить воркеры. Практики аккуратного завершения и снятия готовности на stop-сигнале удобно реализовывать на уровне systemd/entrypoint; см. также материал про graceful readiness: как правильно снимать готовность при остановке сервиса.

Диагностика: как понять, какая probe ломает жизнь
Когда начинаются «плавающие» проблемы, действуйте по шагам:
- Посмотрите события Pod: что именно падает — readiness или liveness, и с каким сообщением.
- Проверьте частоту рестартов контейнера и причины: часто видно, что liveness убивает контейнер раньше, чем тот успевает подняться.
- Временно увеличьте
timeoutSecondsиfailureThreshold, чтобы отличить «реальную поломку» от «тайминги слишком жёсткие». - Если проблема только на старте — добавьте
startupProbeи пересмотритеinitialDelaySeconds.
kubectl describe pod demo-xxxx
kubectl get pod demo-xxxx -o wide
kubectl logs demo-xxxx -c app --previous
Логи с --previous особенно полезны, когда контейнер перезапускается и вы не успеваете поймать момент.
Практические шаблоны: что ставить «по умолчанию»
Универсальных значений нет, но есть безопасные базовые шаблоны, от которых удобно плясать.
1) Быстрый веб-сервис (старт до 5–10 секунд)
readinessProbe:
httpGet:
path: /readyz
port: 8080
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 6
2) Тяжёлый старт (30–180 секунд)
startupProbe:
httpGet:
path: /startupz
port: 8080
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 36
readinessProbe:
httpGet:
path: /readyz
port: 8080
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 6
Ключевой момент: startup даёт до 180 секунд (5 × 36) «иммунитета» от liveness, а readiness не даст Pod получить трафик раньше времени.
Антипаттерны, которые часто встречаются
- Одинаковый endpoint и одинаковая логика для readiness и liveness. Это приводит к рестартам из-за временных проблем, которые лучше пережить без перезапуска.
- Readiness зависит от внешней сети. Например, «проверим сторонний API». При сбое сети вы потеряете готовность всех Pod.
- Слишком частые probes.
periodSeconds1 при неидеальном endpoint — прямой путь к лишней нагрузке и деградации. timeoutSeconds= 1 на перегруженных нодах. Чаще безопаснее дать 2–5 секунд и подобрать пороги.
Чеклист перед продакшеном
- Есть ли отдельные endpoints под
/readyz,/healthz,/startupz(или чётко разделённая логика)? - Readiness выключает трафик достаточно быстро, но не флапает на коротких пиках.
- Liveness не перезапускает контейнер при кратковременной деградации и не зависит от внешних сервисов.
- Для долгого старта добавлен
startupProbeс окном по p95/p99. - Параметры проверены на реальной нагрузке (хотя бы на стейджинге) и не создают заметной нагрузки на сам сервис.
Итоги
Правильные probes — это не формальность в манифесте, а инструмент управления жизненным циклом Pod и стабильностью раскаток. В большинстве случаев, когда «вроде всё работает, но Deployment постоянно флапает», корень проблемы — в смешивании ролей readiness и liveness или в отсутствии startup probe для долгого старта. Начните с простых проверок, подберите тайминги по наблюдениям и дайте системе шанс сначала убрать Pod из трафика, а уже потом лечить рестартом.
Если вы катаете Kubernetes на собственных серверах, следите за ресурсами нод: дефицит CPU/IO часто проявляется именно как «random timeouts» в probes. Для небольших и средних кластеров удобнее держать предсказуемые ресурсы на VDS, а для вспомогательных веб-панелей и внутренних сервисов иногда достаточно виртуального хостинга.


