Отказ сервиса почти никогда не происходит мгновенно. Перед полной остановкой приложение обычно проходит через стадии деградации: рост времени ответа, накопление ошибок, потеря связи с зависимостями. 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 с гибким масштабированием ресурсов. Оценку эффективности после внедрения мониторинга проводите по методике из руководства по метрикам инфраструктуры.