Представьте контейнер, который запущен, но ещё не готов обслуживать запросы. Как оркестратору отличить временную неготовность приложения от его зависания?
Для этого используют разные проверки: readiness определяет, можно ли направлять на контейнер пользовательский трафик, а liveness показывает, способен ли процесс продолжать работу. Временная неготовность должна исключать экземпляр из балансировки, но не перезапускать его; зависание процесса, напротив, может требовать перезапуска.
В ранних моделях развёртывания запуск процесса часто считался достаточным признаком готовности сервиса. На практике приложение могло уже иметь работающий процесс, но ещё загружать кэш, устанавливать соединения с зависимостями или выполнять миграцию.
Оркестрация добавила отдельные механизмы контроля состояния, чтобы отделить управление трафиком от восстановления экземпляров. Это решает две разные задачи: не отправлять запросы незрелому экземпляру и автоматически заменять действительно неисправный экземпляр.
Если использовать одну проверку для обеих целей, временный сбой или долгий запуск может вызвать преждевременный перезапуск. Перезапуск уничтожит текущий прогресс и иногда усилит проблему: например, несколько экземпляров начнут одновременно загружать данные или восстанавливать соединения.
Обратная ошибка тоже опасна. Если проверять только доступность процесса, зависший контейнер останется в балансировке и будет получать запросы, хотя не способен их обрабатывать. В результате растут таймауты, очереди и нагрузка на вызывающие сервисы.
Readiness-проверка отвечает на вопрос: можно ли сейчас отправлять этому экземпляру рабочие запросы. При её отрицательном результате оркестратор обычно убирает экземпляр из набора адресатов сервиса, но оставляет контейнер запущенным для восстановления.
Liveness-проверка отвечает на другой вопрос: не застрял ли процесс в состоянии, из которого он не может восстановиться самостоятельно. При последовательном провале такой проверки оркестратор может перезапустить контейнер согласно своей политике восстановления.
Проверка должна отражать состояние самого приложения, а не только факт существования процесса. Простая проверка открытого порта не гарантирует, что приложение обрабатывает запросы, а глубокая проверка всех внешних зависимостей может сделать сервис недоступным из-за временной неисправности второстепенной системы.
Для медленно запускающихся приложений применяют отдельную startup-проверку или эквивалентную задержку начального контроля. Она не позволяет liveness-проверке считать процесс зависшим до завершения нормального запуска.
Есть важные ограничения. Проверки не исправляют архитектурные проблемы, а перезапуск не помогает при постоянной ошибке конфигурации, нехватке ресурсов или несовместимости версии. Слишком частые проверки создают дополнительную нагрузку, а слишком мягкие пороги увеличивают время обнаружения неисправности.
Сервис после запуска восстанавливает локальный индекс в течение нескольких минут. Если liveness-проверка начиналась сразу, контейнер перезапускался до завершения восстановления, поэтому каждый новый запуск снова начинал ту же операцию.
Рассматривались три варианта. Увеличить общий тайм-аут запуска было просто, но это замедляло обнаружение зависаний после запуска. Проверять только открытый порт было быстро, но такой вариант пропускал зависшие процессы. Убрать автоматические проверки решало проблему перезапусков, но лишало систему самовосстановления.
Выбрали отдельную startup-проверку для периода восстановления, readiness-проверку для управления трафиком и liveness-проверку для уже запущенного сервиса. В результате незрелый экземпляр не получал запросы, нормальный долгий запуск не прерывался, а зависания после запуска обнаруживались и исправлялись автоматически.
Потому что жизнеспособность и готовность имеют разные критерии. Процесс может отвечать на техническую проверку, но ещё не иметь загруженной конфигурации, прогретого кэша или доступного набора внутренних ресурсов. Объединение сигналов приводит либо к преждевременной маршрутизации запросов, либо к ненужным перезапускам.
Обычно нет, если временная недоступность базы не означает, что процесс безвозвратно завис. Иначе отказ общей зависимости может вызвать одновременный перезапуск множества экземпляров и усилить аварию. Доступность критичной зависимости иногда учитывают в readiness, если сервис действительно не способен обслуживать запросы без неё, но решение должно учитывать деградацию, кэширование и возможность частичной работы.
При коротких тайм-аутах и малом числе допустимых неудач кратковременная задержка превращается в перезапуск. Если проблема вызвана перегрузкой, новые экземпляры начинают запускаться одновременно и потребляют ещё больше CPU, памяти или подключений к зависимостям. Поэтому параметры проверок выбирают с учётом времени запуска, нормальных пиков нагрузки и способа восстановления приложения, а результат дополнительно контролируют по метрикам и событиям оркестратора.