Health Check и мониторинг: ранняя диагностика отказов сервисов | AdminWiki

Health Check и мониторинг: ранняя диагностика отказов сервисов

19 августа 2026 10 мин. чтения
Содержание статьи

Отказ сервиса почти никогда не происходит мгновенно. Перед полной остановкой приложение обычно проходит через стадии деградации: рост времени ответа, накопление ошибок, потеря связи с зависимостями. Health check и мониторинг позволяют зафиксировать эти стадии и принять меры до того, как проблема коснется пользователей. В этом руководстве разобраны три типа проверок состояния - liveness, readiness и startup - и пошаговая настройка сбора метрик с алертами в Prometheus и Grafana. Материал ориентирован на DevOps-инженеров и системных администраторов, которым нужны рабочие конфигурации, а не пересказ документации.

Практика показывает: внедрение проверок состояния сокращает среднее время восстановления (MTTR) в разы. Вместо ручного поиска зависшего процесса оркестратор сам перезапускает контейнер, а балансировщик исключает неготовый под из ротации. Дальше - конкретика по каждому типу проверок и настройке мониторинга.

Зачем нужны health check: предотвращение отказов до того, как они повлияют на пользователей

Сервис может выглядеть работающим, но не отвечать на запросы. Процесс запущен, порт открыт, однако приложение зависло в deadlock или исчерпало пул соединений. Без автоматических проверок такая ситуация обнаруживается только через жалобы пользователей или алерты внешнего мониторинга, которые срабатывают с задержкой.

Health check решает три задачи:

  • Обнаружение зависаний. Периодический запрос к endpoint проверяет, отвечает ли приложение за разумное время.
  • Управление трафиком. Балансировщик отправляет запросы только на готовые экземпляры.
  • Автоматическое восстановление. Оркестратор перезапускает контейнер при провале liveness-проверки.

Типичный сценарий: бэкенд на Node.js теряет соединение с Redis и перестает отвечать на часть запросов. Без readiness-проверки балансировщик продолжает слать трафик на этот инстанс, клиенты получают ошибки 502. С настроенной проверкой под исключается из ротации в течение секунд, пока соединение не восстановится.

Подробнее о том, как health check встраивается в общую систему наблюдаемости распределенных систем, читайте в руководстве по мониторингу SLA сервисов.

Три кита health check: liveness, readiness и startup проверки

В Kubernetes и Docker есть три типа проверок, каждый со своей задачей. Путаница между ними приводит к каскадным авариям: liveness убивает контейнер, который просто долго стартует, а readiness не исключает под из балансировки, потому что настроена неправильно.

Liveness: как определить, что сервис завис и его нужно перезапустить

Liveness-проверка отвечает на вопрос: «Процесс жив?». Оркестратор периодически выполняет проверку, и если она проваливается заданное количество раз подряд, контейнер перезапускается. Это грубый, но эффективный механизм восстановления после deadlock, утечки памяти, зависших потоков.

Механика проста: kubelet отправляет HTTP-запрос, открывает TCP-соединение или выполняет команду внутри контейнера. Ответ с кодом 2xx или 3xx считается успехом. Любой другой код или таймаут - провал.

Пример HTTP-проверки для веб-приложения:

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 15
  periodSeconds: 10
  timeoutSeconds: 3
  failureThreshold: 3

Здесь kubelet ждет 15 секунд после старта, затем каждые 10 секунд запрашивает /healthz. Три последовательных провала приводят к перезапуску. Важно: liveness не должен проверять внешние зависимости. Если проверка обращается к базе данных, то при недоступности БД контейнер будет перезапускаться без необходимости, создавая дополнительную нагрузку.

Readiness: когда сервис готов принимать трафик

Readiness-проверка отвечает на вопрос: «Может ли сервис обрабатывать запросы прямо сейчас?». Она не перезапускает контейнер. Она управляет тем, попадает ли под в Service и получает ли трафик от балансировщика.

Сценарий: приложение стартует, но ему нужно загрузить кэш из базы данных или прогреть JIT-компилятор. Процесс жив, но запросы обрабатывать не готов. Readiness-проверка возвращает 503, и kubelet исключает под из эндпоинтов Service. Когда проверка начинает возвращать 200, под автоматически возвращается в ротацию.

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5
  timeoutSeconds: 2
  failureThreshold: 3
  successThreshold: 1

Ключевое отличие от liveness: readiness не приводит к перезапуску. Контейнер остается запущенным, но не получает трафик, пока не станет готовым.

Startup: защита медленно стартующих приложений

Startup-проверка решает проблему приложений с длительной инициализацией. Java-сервисы, legacy-монолиты, приложения с миграциями БД могут стартовать 60-120 секунд. Если liveness настроена с initialDelaySeconds: 15 и failureThreshold: 3, контейнер будет убит на 45-й секунде, до завершения инициализации.

Startup-проверка выполняется первой. Пока она не завершится успехом, liveness и readiness отключены. Это дает приложению необходимое время на запуск без риска ложного перезапуска.

startupProbe:
  httpGet:
    path: /startup
    port: 8080
  initialDelaySeconds: 0
  periodSeconds: 5
  timeoutSeconds: 3
  failureThreshold: 30
  successThreshold: 1

Конфигурация выше дает приложению до 150 секунд на запуск (30 попыток с интервалом 5 секунд). После первого успеха startup-проверка больше не выполняется, и вступают в силу liveness и readiness. Для приложений с гарантированно быстрым стартом startup-проверка не нужна.

Настройка health check в Kubernetes: практические примеры

Перейдем к готовым манифестам. Параметры проверок одинаковы для всех типов, но их значения зависят от характера приложения.

Основные параметры:

  • initialDelaySeconds - задержка перед первой проверкой после старта контейнера.
  • periodSeconds - интервал между проверками.
  • timeoutSeconds - таймаут на ответ.
  • failureThreshold - количество последовательных провалов для признания проверки неуспешной.
  • successThreshold - количество последовательных успехов для признания проверки успешной (для readiness и startup).

Пример: HTTP health check для веб-приложения

Полный манифест для Nginx с liveness и readiness проверками:

apiVersion: v1
kind: Pod
metadata:
  name: web-app
spec:
  containers:
  - name: nginx
    image: nginx:1.27
    ports:
    - containerPort: 80
    livenessProbe:
      httpGet:
        path: /healthz
        port: 80
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 2
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 2
      failureThreshold: 3

Для Nginx эндпоинты /healthz и /ready нужно реализовать отдельно, например, через конфигурацию location с возвратом кода 200. В реальных приложениях эти эндпоинты обычно предоставляет сам фреймворк или библиотека health check.

Пример: проверка TCP-соединения для базы данных

Для PostgreSQL нет HTTP-интерфейса, поэтому используется TCP-проверка. Она устанавливает соединение с указанным портом и считает успехом любое успешное подключение.

apiVersion: v1
kind: Pod
metadata:
  name: postgres
spec:
  containers:
  - name: postgres
    image: postgres:16
    ports:
    - containerPort: 5432
    livenessProbe:
      tcpSocket:
        port: 5432
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 3
      failureThreshold: 3
    readinessProbe:
      tcpSocket:
        port: 5432
      initialDelaySeconds: 10
      periodSeconds: 5
      timeoutSeconds: 3
      failureThreshold: 3

TCP-проверка подтверждает, что порт открыт и сервер принимает соединения. Она не проверяет готовность БД выполнять запросы. Для более точной проверки используйте exec с командой pg_isready внутри контейнера.

Диагностика проблем с подами через метрики мониторинга подробно разобрана в руководстве по Kubernetes troubleshooting.

Мониторинг с Prometheus и Grafana: сбор метрик и настройка алертов

Health check обнаруживают проблемы на уровне отдельного контейнера. Prometheus и Grafana дают картину по всей инфраструктуре: тренды, аномалии, корреляции между метриками. Связка работает так: Prometheus собирает метрики с экспортеров и приложений, Grafana визуализирует данные и отправляет алерты через Alertmanager.

Настройка сбора метрик с сервисов

Для приложений используйте клиентские библиотеки Prometheus: prom-client для Node.js, prometheus_client для Python, micrometer для Java. Они экспортируют стандартные метрики HTTP-запросов, использования памяти, времени работы сборщика мусора.

Для сторонних сервисов используйте экспортеры:

  • node_exporter - метрики хоста: CPU, память, диски, сеть.
  • blackbox_exporter - проверка доступности HTTP, TCP, DNS, ICMP.
  • postgres_exporter - метрики PostgreSQL.

Конфигурация prometheus.yml для сбора метрик с node_exporter и приложения:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']

  - job_name: 'app'
    static_configs:
      - targets: ['app-server:8080']
    metrics_path: '/metrics'

Интервал сбора 15 секунд - разумный компромисс между свежестью данных и нагрузкой на Prometheus. Для высоконагруженных систем допустимо увеличить до 30 секунд.

Создание правил алертов: примеры для критичных метрик

Правила алертов описываются в файле alerts.yml и подключаются в конфигурации Prometheus:

groups:
  - name: infrastructure
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Высокая загрузка CPU на {{ $labels.instance }}"
          description: "CPU используется на {{ $value }}% более 10 минут"

      - alert: HighMemoryUsage
        expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Нехватка памяти на {{ $labels.instance }}"

Ключевой параметр - for. Он требует, чтобы условие выполнялось непрерывно в течение указанного времени. Это фильтрует кратковременные всплески и снижает количество ложных срабатываний.

Для веб-приложений критичны метрики времени ответа и ошибок:

- alert: HighErrorRate
  expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
  for: 5m
  labels:
    severity: critical
  annotations:
    summary: "Доля ошибок 5xx превышает 5% на {{ $labels.instance }}"

Настройка уведомлений в Grafana

Prometheus отправляет алерты в Alertmanager, который маршрутизирует их по каналам: email, Slack, Telegram, PagerDuty. Конфигурация Alertmanager:

route:
  receiver: 'slack'
  group_by: ['alertname']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h

receivers:
  - name: 'slack'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'
        channel: '#alerts'
        title: '{{ .GroupLabels.alertname }}'
        text: '{{ range .Alerts }}{{ .Annotations.summary }}\n{{ end }}'

Grafana также имеет встроенную систему алертов, которая работает с данными из Prometheus. Настройка каналов уведомлений выполняется в разделе Alerting → Contact points. Для дашбордов и алертов в Grafana используйте готовые шаблоны из руководства по наблюдаемости высоконагруженных систем.

Выбор оптимальных пороговых значений: как избежать ложных срабатываний

Ложные срабатывания - главная причина, по которой команды отключают алерты. Слишком чувствительные пороги генерируют шум, важные уведомления теряются в потоке, и в итоге реальный инцидент пропускается. Слишком высокие пороги приводят к тому, что проблема обнаруживается после того, как пользователи уже пострадали.

Как определить базовые значения метрик

Базовые значения - это нормальное поведение сервиса под типичной нагрузкой. Собирайте метрики минимум неделю, включая пиковые периоды. Анализируйте распределение значений, а не только средние.

Используйте 95-й процентиль как отправную точку для порога. Если 95% времени загрузка CPU ниже 70%, установите алерт на 85% с for: 15m. Это отсечет кратковременные всплески, но поймает устойчивую аномалию.

В Grafana стройте графики с percentile-агрегацией: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])). Это покажет реальную картину времени ответа, а не среднее, которое скрывает выбросы.

Настройка задержек и повторных проверок для снижения шума

Параметр for в правилах Prometheus - основной фильтр ложных срабатываний. Для метрик с высокой волатильностью (сетевой трафик, количество запросов) устанавливайте for: 10m и более. Для стабильных метрик (использование диска) достаточно for: 5m.

В health check аналогичную роль играют failureThreshold и periodSeconds. Три провала с интервалом 10 секунд означают, что проблема наблюдается минимум 20 секунд. Для приложений с периодическими подвисаниями увеличьте failureThreshold до 5.

Настройка алертов на основе логов - отдельная тема, разобранная в руководстве по алертингу из логов.

Типичные ошибки при настройке health check и как их избежать

Разбор ошибок, которые встречаются в production-конфигурациях чаще всего.

Ошибка: использование liveness для проверки внешних зависимостей

Liveness-проверка, которая обращается к базе данных или внешнему API, создает каскадный эффект. При недоступности БД все контейнеры приложения начинают перезапускаться. Это увеличивает нагрузку на и без того проблемный сервис и не решает исходную проблему.

Правильный подход: liveness проверяет только внутреннее состояние процесса. Внешние зависимости проверяет readiness. Если БД недоступна, под исключается из балансировки, но не перезапускается. Когда БД восстанавливается, readiness снова возвращает 200, и под автоматически возвращается в ротацию.

Ошибка: отсутствие startup-проверки для медленных приложений

Java-приложения с Spring Boot, Python-сервисы с загрузкой моделей машинного обучения, Go-приложения с миграциями - все они могут стартовать дольше 30 секунд. Без startup-проверки liveness убивает контейнер до завершения инициализации. Контейнер перезапускается, снова не успевает стартовать, и цикл повторяется бесконечно.

Решение: добавьте startup-проверку с failureThreshold, умноженным на periodSeconds, дающим достаточное время на запуск. Для приложения со стартом 90 секунд: periodSeconds: 5 и failureThreshold: 24 дают 120 секунд запаса.

Дополнительные ошибки: отсутствие проверок вообще, использование одного типа проверки для всех случаев, слишком агрессивные пороги, игнорирование метрик самих проверок. Каждая из них увеличивает время обнаружения инцидента или создает ложные срабатывания.

Заключение: комплексный подход к ранней диагностике отказов

Health check и мониторинг - два уровня одной системы ранней диагностики. Health check работают на уровне контейнера: перезапускают зависшие процессы, управляют трафиком, защищают медленный старт. Prometheus и Grafana дают уровень инфраструктуры: тренды, корреляции, прогнозирование проблем до их возникновения.

Внедряйте проверки последовательно. Начните с readiness для всех HTTP-сервисов. Добавьте liveness для приложений с известными проблемами зависаний. Настройте startup для медленно стартующих компонентов. Затем подключите сбор метрик и базовые алерты на CPU, память, ошибки 5xx. Пороги подбирайте на основе недельных данных, а не интуиции.

Для развертывания инфраструктуры мониторинга и тестовых стендов можно использовать облачные серверы Timeweb Cloud с гибким масштабированием ресурсов. Оценку эффективности после внедрения мониторинга проводите по методике из руководства по метрикам инфраструктуры.

Поделиться:
Сохранить гайд? В закладки браузера