Learning Platform
Глоссарий Troubleshooting
Урок 13.03 · 22 мин
Средний
ProbestiminginitialDelaySecondsperiodSecondsfailureThresholdtuning

Timing параметры probes: tuning

Любой probe (liveness / readiness / startup) — это handler плюс пять параметров timing, которые управляют его поведением во времени. Не зная этих параметров наизусть, нельзя ни настроить production probes, ни решить CKAD-задачу про tuning. Все timing значения — integer-секунды, минимум 1 (где допустимо 0 — указано).


systemctl: управление сервисами в повседневной работе

Пять параметров

ПараметрDefaultМинимумЧто значит
initialDelaySeconds00Задержка перед первой пробой после старта контейнера
periodSeconds101Интервал между пробами
timeoutSeconds11Таймаут на выполнение одной пробы
successThreshold11Сколько подряд успешных проб для перехода в healthy
failureThreshold31Сколько подряд неуспешных проб для перехода в unhealthy
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 0
  periodSeconds: 10
  timeoutSeconds: 1
  successThreshold: 1
  failureThreshold: 3
WARNING

Для liveness и startup probes successThreshold ОБЯЗАН быть 1. API server отвергнет другое значение. Логика: liveness/startup управляют lifecycle контейнера, и «один success достаточно, чтобы считать живым» — единственная разумная семантика. Изменять successThreshold имеет смысл только в readiness.


Effective unhealthy time: главная формула

Сколько времени реально пройдёт от момента «что-то сломалось» до действия kubelet? Грубая формула:

Effective unhealthy time = initialDelaySeconds + (failureThreshold × periodSeconds)

С default значениями для liveness: 0 + (3 × 10) = 30 секунд от старта контейнера до возможного первого restart (если probe сразу fail-ит). От момента поломки в healthy контейнере — failureThreshold × periodSeconds = 30 секунд. Точнее, формула — (failureThreshold - 1) × periodSeconds + periodSeconds — есть нюансы по округлению, но 30 — нормальное приближение.

Timeline default liveness probe
t=0sКонтейнер стартует. initialDelaySeconds: 0 — первая проба может запускаться сразу. Если app ещё не открыл порт, первая проба fail (connection refused).
t=0s..10sПервая проба — может попасть на момент старта, ещё нет HTTP listener. Это причина, по которой исторически ставили initialDelaySeconds — но в Kubernetes 1.18+ предпочитают startupProbe, который не требует знания точного времени старта.
t=10speriodSeconds: 10. Вторая проба. Если первая fail, и эта тоже fail — счётчик failure = 2.
t=20sТретья проба. Если все три fail — failureThreshold: 3 достигнут. kubelet начинает kill контейнера.
t=30s+kubelet отправил SIGTERM, ждёт terminationGracePeriodSeconds (default 30s), потом SIGKILL. Затем новый контейнер стартует. Полное время от старта до повторного старта может быть 30-60+ секунд.

tuning сценариев

Slow-starting app (Java, миграции БД)

Вместо initialDelaySeconds на liveness — startupProbe с большим failureThreshold:

startupProbe:
  httpGet:
    path: /healthz
    port: 8080
  failureThreshold: 30
  periodSeconds: 10
  # max startup time = 30 × 10s = 5 minutes

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  periodSeconds: 10
  failureThreshold: 3
  # after startup PASS, default aggressive liveness: 30s to restart

Идея: startupProbe защищает первую фазу (до 5 минут на startup), потом liveness агрессивно следит за зависаниями. Без startup пришлось бы поставить initialDelaySeconds: 300 на liveness — но тогда первые 5 минут зависший контейнер живёт без присмотра.

High-traffic readiness

Для readinessProbe на горячем path хочется быстрее реагировать на degradation:

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  periodSeconds: 3       # чаще проверять
  failureThreshold: 2    # быстрее выводить из ротации
  successThreshold: 2    # но не флапать обратно

successThreshold: 2 (два подряд PASS, чтобы вернуть в Endpoints) — анти-flapping. Без этого: одна успешная проба возвращает Pod, следующая снова fail-ит, snap из Endpoints — Service постоянно дёргает контроллера Endpoints.

NOTE

periodSeconds: 1 теоретически возможен, но создаёт реальный overhead: на каждый exec — fork() в контейнере, на каждый httpGet — TCP-соединение и HTTP-парсинг от kubelet. На больших кластерах (тысячи Pods × три probes × 1Hz) это нагрузка на kubelet и на dataplane. Не уходите ниже periodSeconds: 5 без явной причины.

Cascading restart avoidance

В multi-container Pod (или в большом Deployment) все контейнеры с одинаковыми timing просыпаются синхронно — periodic spike нагрузки на app каждые periodSeconds. Сдвиньте periodSeconds на разных контейнерах (или используйте легкий handler), чтобы probes не били app одновременно.


timeoutSeconds: подводный камень

Default timeoutSeconds: 1. Это значит, что если app не отвечает за секунду — probe FAIL.

На loaded app, особенно с GC pauses (Java) или event-loop blocking (Node.js), 1-секундный timeout даёт false-positives. Probe видит app как мёртвого, при том что он просто секунду занят. Restart loop под нагрузкой — типовая авария.

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  timeoutSeconds: 3      # не 1 — даём app дышать
  periodSeconds: 10
  failureThreshold: 3
WARNING

До Kubernetes 1.20 timeoutSeconds для exec probe игнорировался kubelet-ом — probe мог висеть вечно. С 1.20 эта бага исправлена, теперь exec тоже соблюдает timeout. Если у вас старая конфигурация (наследие 1.18-) — проверьте, что timeout adequate для команды.


CKAD: типовое задание про tuning

Формулировка: «Deployment X на slow-starting app зацикливается на restart-ах. Tune probes так, чтобы дать ему 4 минуты на startup, но после этого быстро ловить зависание.»

Канонический ответ:

spec:
  containers:
  - name: app
    image: ...
    startupProbe:
      httpGet:
        path: /healthz
        port: 8080
      failureThreshold: 24   # 24 × 10s = 4 minutes
      periodSeconds: 10
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      periodSeconds: 10
      failureThreshold: 3    # 30s on real hang
      timeoutSeconds: 2      # not too aggressive
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      periodSeconds: 5
      failureThreshold: 3

Главное: startupProbe даёт запас, livenessProbe агрессивно сторожит после startup, readinessProbe независимо рулит трафиком.


Проверка знанийKnowledge check
Default timing для livenessProbe: periodSeconds: 10, failureThreshold: 3, initialDelaySeconds: 0. Сколько секунд от старта контейнера до возможного первого restart, если probe всегда fail-ит?
ОтветAnswer
Примерно 30 секунд: 0 + 3 × 10. Первая проба может запуститься сразу (initialDelaySeconds: 0), последующие — раз в 10 секунд. После трёх подряд fail (failureThreshold: 3) kubelet начинает kill контейнера. Точное значение может быть 20-30 секунд в зависимости от того, когда стартовала первая проба относительно старта контейнера.
Проверка знанийKnowledge check
Можно ли установить successThreshold: 2 для livenessProbe?
ОтветAnswer
Нет. API server отвергнет: для liveness и startup probes successThreshold обязан быть 1. Логика: liveness/startup управляют lifecycle, требовать многократного подтверждения 'живой' не имеет смысла. successThreshold имеет смысл только в readinessProbe (anti-flapping).
Проверка знанийKnowledge check
Production Java app, обычный startup 30 секунд, но иногда — до 3 минут (cold start). Как настроить probes?
ОтветAnswer
startupProbe с failureThreshold большим запасом: например, 20 × 10s = 200 секунд > 3 минут. После того как startup PASS — livenessProbe с failureThreshold: 3, periodSeconds: 10 (30 секунд до restart на реальном зависании). НЕ использовать initialDelaySeconds: 200 на liveness — это плохой паттерн, оставляет первые 200 секунд без присмотра, и в долгосрочной перспективе сложнее тьюнить.
Проверка знанийKnowledge check
Probe иногда fail-ит из-за GC pause (Java) длиной 1.5 секунды. Default timeoutSeconds: 1. Что произойдёт и как исправить?
ОтветAnswer
При GC pause длиной > 1 секунды probe не успевает завершиться → timeout → failure counter. Несколько таких подряд (failureThreshold: 3) — kubelet kill контейнер, при том что приложение здорово, просто занято GC. Исправление: увеличить timeoutSeconds (например, 3-5 секунд). Дополнительно: tuning JVM (G1GC / ZGC для коротких pauses), и убедиться, что probe endpoint не выделяет память (чтобы сам не провоцировал GC).

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

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. Default значения livenessProbe: periodSeconds: 10, failureThreshold: 3, initialDelaySeconds: 0. Сколько примерно секунд от старта контейнера до restart, если probe всегда fail?

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

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

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

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