Мониторинг Kubernetes сервисов и приложений: лучшие практики 2026 | AdminWiki

Мониторинг Kubernetes сервисов и приложений: лучшие практики 2026

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

В 2026 году мониторинг сервисов и приложений в Kubernetes строится на связке Prometheus v3, Prometheus Operator, Grafana и Alertmanager. Этот стек закрывает три задачи: сбор метрик с сервисов и подов, автоматическое обнаружение новых целей, алертинг по SLO. Ниже разобраны рабочие ServiceMonitor, PodMonitor, правила бюджета ошибок и чек-лист для продакшена.

Главный принцип: Prometheus работает в pull-режиме и забирает метрики из эндпоинтов /metrics. Оператор управляет целями через CRD, поэтому менять prometheus.yml вручную не нужно. При добавлении сервиса с нужными labels оператор создает scrape-конфиг и Prometheus начинает собирать метрики без перезагрузки.

Материал рассчитан на DevOps-инженеров и администраторов кластеров Kubernetes 1.30+. Все примеры проверены на Prometheus Operator и kube-prometheus-stack.

Архитектура мониторинга Kubernetes-кластера в 2026

Стек выглядит так: Prometheus v3 хранит метрики и выполняет PromQL, Prometheus Operator преобразует ServiceMonitor/PodMonitor в scrape-конфиг, Alertmanager маршрутизирует уведомления, Grafana отображает дашборды. К этому добавляются kube-state-metrics и node-exporter.

Компоненты стека: Prometheus, Operator, Grafana, Alertmanager

Prometheus собирает и хранит временные ряды, не зависит от внешней БД. Operator следит за объектами Kubernetes и генерирует конфигурацию сбора. Grafana подключается к Prometheus как к источнику данных. Alertmanager принимает алерты, группирует, дедуплицирует и отправляет в Slack, Telegram, почту.

kube-state-metrics отдает состояние объектов: реплики Deployment, статусы Pod, ресурсы Job. node-exporter собирает CPU, память, диск и сеть с каждого узла. Эти два компонента закрывают уровень инфраструктуры, а ServiceMonitor/PodMonitor закрывают уровень сервисов и приложений. Настройка kube-state-metrics и node-exporter с готовыми PromQL-запросами разобрана в статье про сбор метрик CPU, памяти, диска и сети.

Почему ServiceMonitor и PodMonitor заменили статичный prometheus.yml

В статичном prometheus.yml цель описывалась вручную: адрес, порт, путь, интервал. При каждом изменении Service или Pod требовалась правка файла и reload Prometheus. В динамичной среде Kubernetes это не работает. ServiceMonitor и PodMonitor объявляют цели через Kubernetes API. Operator смотрит на labels и namespace, автоматически генерирует scrape-конфиг и перезапускает Prometheus при изменениях.

Результат: новый Deployment с label app: api и Service с нужным портом попадает в мониторинг без ручных действий. Это ключевое отличие от Prometheus вне Kubernetes.

Установка и подготовка Prometheus Operator

Установка kube-prometheus-stack в кластер

Рекомендуемый способ - Helm. Создайте namespace monitoring и установите chart:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
kubectl create namespace monitoring
helm install monitoring prometheus-community/kube-prometheus-stack -n monitoring --set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false --set prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues=false

Эти параметры включают подхват ServiceMonitor/PodMonitor во всех namespace. CRD ставятся вместе с chart, но при обновлении chart'а CRD лучше обновлять отдельно. Полная пошаговая установка с Grafana и Alertmanager описана в отдельном руководстве.

Если под рукой нет кластера, для проверки конфигураций подойдет managed Kubernetes в Timeweb Cloud. Для продакшена выделите отдельный namespace monitoring и ограничьте доступ.

Проверка CRD и доступности Prometheus

Проверьте, что CRD установлены:

kubectl get crd | grep monitoring.coreos.com
kubectl get pods -n monitoring
kubectl get servicemonitors,podmonitors -A

Откройте Prometheus UI через port-forward:

kubectl port-forward -n monitoring svc/prometheus-kube-prometheus-prometheus 9090:9090

В браузере http://localhost:9090 откройте Status > Targets, чтобы видеть цели. Если CRD не появились, проверьте версию chart'а и наличие прав на создание CRD в кластере.

Мониторинг Kubernetes-сервисов через ServiceMonitor

Создание ServiceMonitor для HTTP-сервиса

ServiceMonitor привязывается к Service по labels, а не к Pod напрямую. Для Service с меткой app: api и портом http манифест выглядит так:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: api
  namespace: backend
spec:
  selector:
    matchLabels:
      app: api
  endpoints:
  - port: http
    interval: 30s
    path: /metrics
    scheme: http

Порт http должен совпадать с именем порта в Service. Не указывайте номер порта как число, поскольку Operator сопоставляет endpoint по имени порта. ServiceMonitor должен находиться в namespace, который разрешен в serviceMonitorNamespaceSelector объекта Prometheus.

Привязка ServiceMonitor к Prometheus: serviceMonitorSelector и namespaceSelector

ServiceMonitor не подхватывается автоматически. Prometheus CR указывает, какие ServiceMonitor и из каких namespace брать:

apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: k8s
  namespace: monitoring
spec:
  serviceAccountName: prometheus-k8s
  serviceMonitorSelector:
    matchLabels:
      team: backend
  serviceMonitorNamespaceSelector:
    matchNames:
    - backend

Если нужно собирать все ServiceMonitor во всех namespace, установите пустые селекторы: serviceMonitorSelector: {} и serviceMonitorNamespaceSelector: {}. Это удобно на старте, но в большом кластере приводит к массовому сбору нецелевых метрик. Лучше сразу использовать matchLabels.

В kube-prometheus-stack эти параметры можно задать через values.

Настройка TLS, аутентификации и базового relabeling

Для HTTPS-эндпоинта с клиентским сертификатом, токеном или basic auth используйте блок tlsConfig, bearerTokenSecret или basicAuth:

endpoints:
- port: https
  interval: 30s
  scheme: https
  tlsConfig:
    ca:
      secret:
        name: api-ca
        key: ca.crt
    insecureSkipVerify: false
  bearerTokenSecret:
    name: api-token
    key: token
  relabelings:
  - sourceLabels: [__meta_kubernetes_namespace]
    targetLabel: namespace
  - sourceLabels: [__meta_kubernetes_service_name]
    targetLabel: service

insecureSkipVerify: false оставляйте в продакшене. Секреты должны лежать в namespace ServiceMonitor'а. relabelings добавляют постоянные метки namespace и service, чтобы не полагаться на служебные __meta_*.

Типовые ошибки при настройке ServiceMonitor

  • Label Service не совпадает с selector.matchLabels. Проверьте kubectl get svc -n backend --show-labels.
  • В port указан номер порта вместо имени. Используйте имя порта из Service.
  • ServiceMonitor создан в namespace, который не разрешен. Проверьте serviceMonitorNamespaceSelector.
  • Нет прав RBAC у Prometheus на чтение Service/Pod. Смотрите логи operator'а и события.
  • Target down из-за TLS: сертификат не подписан вашим CA или CN не совпадает.

Быстрый признак: в Prometheus UI цель находится в состоянии DOWN с ошибкой скрейпинга. Текст ошибки указывает на причину.

PodMonitor: сбор метрик с подов напрямую

Когда PodMonitor предпочтительнее ServiceMonitor

ServiceMonitor балансирует запросы через Service и зависит от эндпоинтов. PodMonitor скрейпит каждый Pod напрямую по IP. Выбирайте PodMonitor, если Service не создан, метрики отдают отдельные pod'ы stateful-нагрузок, или в поде несколько контейнеров и метрики лежат в sidecar. При наличии стабильного Service чаще используют ServiceMonitor.

Пример PodMonitor для приложения с sidecar-метриками

apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: worker-sidecar
  namespace: backend
spec:
  selector:
    matchLabels:
      app: worker
  namespaceSelector:
    matchNames: [backend]
  podMetricsEndpoints:
  - port: metrics
    interval: 15s
    path: /metrics
    relabelings:
    - sourceLabels: [__meta_kubernetes_pod_name]
      targetLabel: pod
    - sourceLabels: [__meta_kubernetes_namespace]
      targetLabel: namespace

Prometheus скрейпит каждый под с label app: worker и портом metrics. Если порт открыт только в sidecar-контейнере, Operator все равно найдет endpoint по имени порта. Один PodMonitor может собирать метрики со всех подов приложения, а relabeling добавляет имена pod и namespace.

Автоматическое обнаружение сервисов и подов в Kubernetes

Селекторы и namespaceSelector: управление автодобавлением целей

Оператор через Kubernetes API находит объекты, которые подходят под selectors. Для автоматического включения только нужных сервисов используйте matchLabels или matchExpressions. Пример для Prometheus CR, который берет только namespace production и сервисы с меткой monitoring: enabled:

serviceMonitorSelector:
  matchLabels:
    monitoring: enabled
serviceMonitorNamespaceSelector:
  matchNames:
  - production

Исключить системные namespace можно с помощью matchExpressions с operator NotIn. При таком подходе новый сервис попадает в Prometheus после установки двух меток: monitoring: enabled на ServiceMonitor и namespace production.

Совместимость с аннотациями prometheus.io/scrape

Prometheus Operator поддерживает legacy-аннотации на Service и Pod: prometheus.io/scrape: 'true', prometheus.io/port: '8080', prometheus.io/path: '/metrics'. Он конвертирует их в ServiceMonitor/PodMonitor. Это удобно при миграции с обычного Prometheus, но CRD дает больше контроля: TLS, интервалы, relabeling, отдельные namespace. Для новых проектов используйте CRD.

Relabeling: из метаданных Kubernetes в метки Prometheus

Prometheus при обнаружении целей получает служебные метки __meta_kubernetes_*. Их нужно превращать в постоянные метки или удалять. Основные действия: keep, drop, replace, labelmap, labeldrop.

relabelings:
- action: keep
  sourceLabels: [__meta_kubernetes_service_label_monitoring]
  regex: enabled
- action: labelmap
  regex: __meta_kubernetes_service_label_(.+)
- sourceLabels: [__meta_kubernetes_namespace]
  targetLabel: namespace
  action: replace
- regex: __meta_kubernetes_pod_label_pod_template_hash
  action: labeldrop

Правило keep оставляет только сервисы с меткой monitoring=enabled. labelmap переносит все service labels в обычные метки. labeldrop убирает ненужные служебные метки, чтобы не раздувать кардинальность.

Метрики приложений в Kubernetes: что собирать и как отдавать

Эндпоинт /metrics и клиентские библиотеки

Приложение должно открыть HTTP-эндпоинт /metrics и отдавать метрики в текстовом формате Prometheus. Пример строки:

request_duration_seconds_bucket{le='0.1'} 42
requests_total{code='200',method='get'} 1280

Для инструментирования используйте официальные клиентские библиотеки: client_golang для Go, prom-client для Node.js, Micrometer для Java, prometheus_client для Python. Счетчики (counter) подходят для числа запросов и ошибок, гистограммы - для длительности. Отделяйте gauge для текущей очереди, активных соединений, размера пула.

Метрики RED отвечают на вопросы: rate запросов, ошибки, длительность. Метрики USE показывают утилизацию, насыщение и ошибки ресурсов. Для HTTP-сервиса начинайте с RED.

Экспортеры для баз данных, очередей и внешних систем

PostgreSQL, Redis, Kafka не отдают метрики в формате Prometheus нативно. Запускайте экспортеры sidecar-контейнером или отдельным Deployment с Service. Популярные: postgres_exporter, redis_exporter, kafka_exporter. После запуска создайте ServiceMonitor для Service экспортера.

Для ресурсов узлов и состояния объектов уже используются node-exporter и kube-state-metrics. Настройка этих компонентов и готовые PromQL-запросы описаны в статье про сбор метрик CPU, памяти и диска.

OpenTelemetry и Prometheus: что выбрать

OpenTelemetry может передавать метрики в Prometheus через OTLP HTTP или через Prometheus exporter. Если кластер уже работает на Prometheus, используйте инструментирование, совместимое с /metrics, а OpenTelemetry вводите постепенно для трассировок. Резкий переход на OTLP без необходимости увеличивает число движущихся частей. Ценность OpenTelemetry заметна в распределенной трассировке, а для метрик Prometheus v3 остается основным хранилищем.

Алертинг на основе SLO: от метрик к надёжности сервисов

SLI и SLO: как выбрать показатели для сервиса

SLI - факт: процент успешных запросов за период, задержка 95-го перцентиля. SLO - цель: 99.9% доступности за 30 дней, 95% запросов быстрее 300 мс. SLA добавляет договор и штрафы. Для HTTP-сервиса базовые SLI: доступность (все запросы, кроме 5xx, от всех запросов), латентность (p95/p99), насыщение очереди.

Формулируйте SLO конкретно. Не используйте 100%, потому что каждая ошибка станет критичной. Начните с 99.9% для внешних API.

PromQL для бюджета ошибок и burn rate

Бюджет ошибок - допустимая доля неудачных запросов: 1 - SLO. Для SLO 99.9% бюджет равен 0.001. Burn rate показывает, как быстро расходуется этот бюджет. Формула для отношения ошибок за 5 минут:

sum(rate(requests_total{code=~'5..'}[5m]))
/
sum(rate(requests_total[5m]))

Чтобы получить burn rate, разделите ошибки на бюджет ошибок:

sum(rate(requests_total{code=~'5..'}[5m]))
/
sum(rate(requests_total[5m]))
/
0.001

Burn rate 1 означает, что бюджет расходуется ровно с допустимой скоростью. Burn rate 14.4 за час показывает, что за 1 час вы сожжете бюджет за 30 дней. Используйте rate() вместо increase() для корректной экстраполяции на коротких окнах.

Создание алерт-правил и связь с Alertmanager

Задайте PrometheusRule с критическим и предупреждающим уровнями:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: api-slo
  namespace: backend
spec:
  groups:
  - name: api-slo
    rules:
    - alert: APIBurnRateCritical
      expr: sum(rate(requests_total{code=~'5..'}[5m])) / sum(rate(requests_total[5m])) / 0.001 > 14.4
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: 'API burn rate критический'
        description: 'Бюджет ошибок расходуется слишком быстро: burn rate > 14.4 за 5 минут.'
    - alert: APIBurnRateWarning
      expr: sum(rate(requests_total{code=~'5..'}[5m])) / sum(rate(requests_total[5m])) / 0.001 > 3
      for: 10m
      labels:
        severity: warning
      annotations:
        summary: 'API burn rate повышен'

Alertmanager маршрутизирует их по severity: critical в Slack, warning в почту. Подробный разбор контроля SLA распределенных систем есть в руководстве по Prometheus и Grafana для контроля SLA.

Алерты используют метки, добавленные при сборе через relabeling. Если в PromQL нет метки service, группировка по сервису невозможна.

Лучшие практики 2026: производительность, безопасность и масштабирование

Контроль кардинальности и именование меток

Кардинальность - число уникальных временных рядов. Высокая кардинальность замедляет PromQL и увеличивает потребление памяти. Не добавляйте в метки userId, requestId, sessionId. Используйте exemplars для привязки трассировки к конкретному запросу. Договоритесь о метках namespace, service, pod. Кардинальность выше 1 млн рядов требует шардирования.

Recording rules и оптимизация запросов

Тяжелые запросы с агрегацией выполняйте заранее через recording rules:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: api-record
  namespace: backend
spec:
  groups:
  - name: api-rates
    rules:
    - record: job:requests:rate5m
      expr: sum(rate(requests_total[5m])) by (service)

Дашборды Grafana читают готовый ряд job:requests:rate5m, а не пересчитывают rate каждый раз. Это снижает нагрузку на Prometheus и ускоряет графики.

Безопасность сбора метрик: RBAC, TLS, NetworkPolicy

Ограничьте RBAC для Prometheus service account. Ему нужны права на чтение pods, services, endpoints, nodes. Не выдавайте cluster-admin. Для скрейпинга используйте tlsConfig в ServiceMonitor. Сетевую политику настройте так, чтобы только Prometheus подключался к портам метрик:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-prometheus-metrics
  namespace: backend
spec:
  podSelector:
    matchLabels:
      app: api
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - port: http

Замените port: http на порт метрик. NetworkPolicy добавляет второй рубеж после TLS.

Масштабирование: remote_write, Thanos, VictoriaMetrics

Для кластеров до 100 узлов одного Prometheus достаточно. При росте используйте remote_write для долгого хранения, федерацию для разделения нагрузки, Thanos для HA и объектного хранилища, VictoriaMetrics как совместимую альтернативу. Сначала контролируйте кардинальность и запросы, потом масштабируйте хранилище. Готовые дашборды и связку мониторинга с GitLab для SRE можно посмотреть в практике по наблюдаемости высоконагруженных систем.

Отладка и проверка мониторинга Kubernetes: чек-лист

Как проверить target в Prometheus

Откройте Prometheus UI: Status > Targets. Каждая цель имеет state UP/DOWN, endpoint и ошибку. Если target DOWN, читайте ошибку скрейпинга. Проверьте, что job соответствует ServiceMonitor/PodMonitor. Для поиска конкретного сервиса используйте фильтр по label service.

Диагностика ServiceMonitor и PodMonitor через логи Operator

kubectl describe servicemonitor api -n backend
kubectl get events -n monitoring --sort-by=.lastTimestamp
kubectl logs -n monitoring deploy/kube-prometheus-stack-operator

Частые причины отсутствия цели: label не совпал, endpoint port не существует в Service, у Prometheus нет прав, ServiceMonitor в неймспейсе вне selector'а. Оператор пишет в логи ошибки reconciliation.

Production-чек-лист внедрения

  • CRD мониторинга установлены и версия совместима с Operator.
  • Включены алерты критического уровня и проверена доставка в Alertmanager.
  • Для скрейпинга включен TLS, insecureSkipVerify: false.
  • Ограничены serviceMonitorSelector и namespaceSelector.
  • Настроен remote_write или локальное хранилище с retention.
  • Метрики приложений отдают /metrics, документация для команды есть.
  • Проверены цели в Prometheus UI после каждого деплоя.

Мониторинг живет рядом с приложением. Если ServiceMonitor лежит в другом namespace или использует жесткие label, он ломается при рефакторинге. Разбирайте ошибки через диагностику Pods и узлов по метрикам, если деградация сервиса уже произошла.

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