Probes: liveness, readiness, startup

Уровень: beginner ~50 мин Практика: Node-RED (Apache-2.0)

Что нужно знать перед уроком

  • M1.03 — Service и порты — readinessProbe напрямую влияет на Endpoints Service

Что нужно знать перед уроком

M1 урок 3 — Service направляет трафик только на Pod’ы, присутствующие в EndpointSlice. Probes — механизм, который решает, должен ли конкретный Pod там присутствовать и жив ли он вообще.

Теория

Три вида проб — принципиально разные последствия провала

Это самая частая точка путаницы у новичков — все три пробы проверяют «здоровье» контейнера, но реагируют по-разному:

ПробаПровал приводит кТипичное назначение
livenessProbeперезапуску контейнера kubelet’ом«процесс завис намертво (deadlock), перезапуск — единственное лечение»
readinessProbeисключению Pod’а из Endpoints Service, без перезапуска — трафик просто перестаёт идти«процесс жив, но временно не готов принимать трафик» (прогревается кэш, ждёт соединения с БД)
startupProbeблокирует запуск liveness/readiness до первого успеха«приложение долго стартует, не убивайте его как зависшее, пока оно легитимно грузится»
Ключевая ошибка новичков
Использовать только livenessProbe с короткими таймаутами для медленно стартующего приложения — kubelet будет считать не успевшее прогреться приложение «зависшим» и убивать его в бесконечном цикле перезапусков (CrashLoopBackOff), хотя оно просто ещё не закончило инициализацию. Решение — startupProbe с достаточным запасом попыток, который отложит начало проверок liveness/readiness до реальной готовности.

Четыре механизма проверки

1
2
3
4
5
6
7
8
9
livenessProbe:
  httpGet: { path: /health, port: 1880 }      # успех: код ответа 2xx или 3xx
readinessProbe:
  tcpSocket: { port: 1880 }                     # успех: TCP-порт открыт и принимает соединение
startupProbe:
  exec: { command: ["cat", "/tmp/ready"] }      # успех: команда вернула код 0
# grpc-вариант (для gRPC-сервисов, реализующих grpc.health.v1):
livenessProbe:
  grpc: { port: 9090 }                          # успех: ответ SERVING от health-check сервиса

Параметры таймингов

1
2
3
4
5
6
7
readinessProbe:
  httpGet: { path: /health, port: 1880 }
  initialDelaySeconds: 5 # сколько ждать после старта контейнера перед первой проверкой
  periodSeconds: 10 # как часто проверять
  timeoutSeconds: 3 # сколько ждать ответа на одну проверку
  successThreshold: 1 # сколько подряд успехов, чтобы считать «готов» (для readiness можно >1)
  failureThreshold: 3 # сколько подряд неудач, чтобы считать «не готов»/«мёртв»

Жёсткое правило API: successThreshold обязан быть 1 для livenessProbe и startupProbe — их семантика бинарна («жив/мёртв», «стартовал/не стартовал»), в отличие от readinessProbe, где иногда осмысленно требовать несколько подряд успехов перед возвратом в ротацию (защита от «дрожащего» здоровья сразу после восстановления).

terminationGracePeriodSeconds на уровне пробы

Начиная с Kubernetes 1.25 (стабильно) у пробы можно задать собственный terminationGracePeriodSeconds, который переопределяет значение на уровне Pod’а именно для случая завершения контейнера из-за провала livenessProbe:

1
2
3
livenessProbe:
  httpGet: { path: /health, port: 1880 }
  terminationGracePeriodSeconds: 5 # быстрее убить зависший процесс, чем ждать общий grace period Pod'а

Это полезно, когда обычное graceful-завершение Pod’а (например, 60 секунд для доработки текущих запросов) избыточно долго для случая, когда мы уже знаем, что процесс сломан и завис — тут быстрее просто прибить и перезапустить.

Частые ошибки и подводные камни

  • Один и тот же endpoint для liveness и readiness без разбора семантики. Если health-check проверяет доступность внешней БД и её временно нет — livenessProbe, ссылающийся на этот же endpoint, начнёт перезапускать Pod, хотя проблема не в самом контейнере, а во внешней зависимости; для внешних зависимостей правильнее использовать только readinessProbe.
  • Отсутствие startupProbe у приложений с долгим стартом. Приводит к ложным перезапускам во время легитимной инициализации.
  • successThreshold больше 1 у liveness/startup — попытка задать такое значение будет отклонена валидацией API.

Практика в кластере

🧩 Практика урока: Node-RED · лицензия Apache-2.0

Node-RED — визуальный редактор потоков автоматизации на Node.js, заметно (несколько секунд) грузится при старте — хороший практический пример необходимости startupProbe.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
kubectl create namespace course-m1-probes
kubectl apply -n course-m1-probes -f - <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata: { name: node-red }
spec:
  replicas: 1
  selector: { matchLabels: { app: node-red } }
  template:
    metadata: { labels: { app: node-red } }
    spec:
      containers:
        - name: node-red
          image: nodered/node-red:latest
          ports: [{ containerPort: 1880 }]
          startupProbe:
            httpGet: { path: /, port: 1880 }
            failureThreshold: 30
            periodSeconds: 2       # до 60 секунд на легитимный старт
          readinessProbe:
            httpGet: { path: /, port: 1880 }
            periodSeconds: 5
            failureThreshold: 2
          livenessProbe:
            httpGet: { path: /, port: 1880 }
            periodSeconds: 10
            failureThreshold: 3
          resources:
            requests: { cpu: "100m", memory: "128Mi" }
            limits: { cpu: "500m", memory: "384Mi" }
EOF
  1. Наблюдайте состояние во время старта (заметьте, что readiness/liveness не начинают проверяться, пока не пройдёт startupProbe):
1
2
kubectl get pod -n course-m1-probes -w
kubectl describe pod -n course-m1-probes -l app=node-red   # секция Events покажет прохождение startup
  1. Смоделируйте провал readinessProbe (без перезапуска контейнера) — временно заблокируйте порт изнутри симуляцией через смену пути:
1
2
3
4
kubectl patch deployment node-red -n course-m1-probes --type=json \
  -p '[{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/httpGet/path","value":"/does-not-exist"}]'
kubectl get pod -n course-m1-probes -w    # READY становится 0/1, RESTARTS не растёт
kubectl get endpointslices -n course-m1-probes   # Pod исчез из Endpoints, хотя жив
  1. Верните путь обратно и убедитесь, что Pod возвращается в ротацию без перезапуска:
1
2
kubectl patch deployment node-red -n course-m1-probes --type=json \
  -p '[{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/httpGet/path","value":"/"}]'

Практика разработки

Используется официальный образ nodered/node-red; собственная сборка — в M3.

Шпаргалка команд урока

1
2
3
kubectl get pod -n <ns> -w
kubectl describe pod <name> -n <ns>       # секция Events для истории проб
kubectl get endpointslices -n <ns>

Вопросы для самопроверки

Какая проба приводит к перезапуску контейнера при провале?

Только провал livenessProbe заставляет kubelet перезапустить контейнер; readinessProbe только убирает Pod из Endpoints, startupProbe блокирует старт остальных проб.

Источник: Kubernetes — probes

Зачем нужен startupProbe у приложения с долгим стартом?

startupProbe блокирует выполнение liveness/readiness до своего первого успеха, устраняя ложные перезапуски во время долгой инициализации.

Источник: Kubernetes — probes

Какое значение successThreshold обязательно для livenessProbe?

API Kubernetes требует successThreshold: 1 для liveness и startup проб — их семантика бинарна.

Источник: Kubernetes — probes

Приложение временно не может достучаться до внешней БД. Какую пробу правильнее завязывать на этот health-check, чтобы не перезапускать здоровый контейнер?

Если проблема во внешней зависимости, а не в самом процессе, перезапуск контейнера (liveness) не поможет и может создать бесконечный цикл рестартов; readiness корректно временно убирает Pod из трафика.

Источник: Kubernetes — probes

Какой механизм проверки httpGet считает успешным ответом?

httpGet считается успешным при кодах ответа из диапазонов 2xx и 3xx.

Источник: Kubernetes — probes

Рекомендуемая литература

Официальная документация

Статьи и блоги

Книги

  • Marko Lukša. Kubernetes in Action. 2nd ed., 2022. ISBN 978-1617297618.
  • Kelsey Hightower, Brendan Burns, Joe Beda. Kubernetes: Up and Running. 3rd ed., 2022. ISBN 978-1098110201.
  • Michael Hausenblas, Stefan Schimanski. Programming Kubernetes. 2019. ISBN 978-1492047107.

Связанные материалы