..

Проверки живучести сервиса: startup-, readiness-, lieveness-probe.

07 Feb 2025

Для развертывания приложений в ecom.tech мы используем Kubernetes. Для того чтобы Kubernetes мог понять, корректно ли работает сервис, используются healthcheck’и. Недавно наши DevOps сделали обязательным использование всех видов проверок: liveness, readiness и startup.

Зачем так много? Разве не достаточно одного /healthcheck? Давайте разбираться.

  1. Startup Probe — проверка, что сервис запущен
  2. Readiness Probe — проверка, что сервис готов принимать трафик.
  3. Liveness Probe — проверка, что сервис работает штатно.

Итак, когда у нас появляется новая версия сервиса и мы запускаем выкатке, все еще активна предыдущая версия сервиса, на которую идет трафик. Первым делом Kubernetes начинает проверять, удалось ли сервису запуститься с помощью startup probe. В случае успеха идем дальше.

Начинается запускать проверка Readiness, и только после успеха на этот под начинает направляться трафик.

Параллельно с этим начинается проверка Liveness, которая проверяет, жив ли сервис, и если проверка провалена, кубер перезапускает сервис.

Каждая из этих проверок предполагает настройки:

Что если не указывать?

Если не указать liveness, то сервис может сломаться, но Kubernetes об этом не узнает.

Если не указать readiness, то трафик на сервис будет направлен еще до того, как он готов его принимать. Это будет означать, что первые клиенты получат 502, а не хотелось бы.

А вот необходимость startup probe уже не так очевидна. В каких случаях может быть полезно отделить этот этап? 

Если запуск сервиса занимает длительное время, то нет смысла стучаться в него с проверками lieveness/readiness, пока он не запустился. Можно попытаться угадать примерное время, которое обычно уходит на запуск, и выставить initialDelaySeconds для проверок. Но это может привести к избыточному ожиданию.

Технически startup probe может дергать ту же ручке, что и readiness. Но при желании у нас есть возможность указать другие настройки: initialDelaySeconds, periodSeconds, failureThreshold, successThreshold. Если захотим.

А вот это оказалось для меня сюрпризом!

Оказывается, readiness probe запускается постоянно с интервалом periodSeconds даже после того, как сервис начал успешно обрабатывать трафик. Таким образом, сервис может сообщить, что временно не готов принимать трафик, например, если перегружен. При этом перезапуск не требуется, так как liveness успешен. Запустилось приложение можно проверять по системным файлам, логам или также по http-запросу.

Начиная с версии Rails 7.1 у нас в приложении идет метод GET /up, но, как мы видим, этого недостаточно.

Пример

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: my-image:latest
    startupProbe:
      httpGet:
        path: /ready
        port: 3000
      initialDelaySeconds: 45
      periodSeconds: 10
      failureThreshold: 12
    readinessProbe:
      httpGet:
        path: /ready
        port: 3000
      initialDelaySeconds: 90
      periodSeconds: 20
      timeoutSeconds: 5
      successThreshold: 1
      failureThreshold: 3
    livenessProbe:
      httpGet:
        path: /live
        port: 3000
      initialDelaySeconds: 120
      periodSeconds: 30
      timeoutSeconds: 5
      successThreshold: 1
      failureThreshold: 3

Подводя итоги

  1. Startup Probe: должна проверять, что инициализация процесса, загрузка плагинов, прогрев кэшей пройден.

  2. Readiness Probe: должна проверять, что приложение готово обрабатывать запросы и очередь запросов не переполнена.

  3. Liveness Probe: должна проверять, что приложение работает штатно и перезапуск не требуется для восстановления.