Вернуться к главной странице, списку всех тем
8. Контроль состояния приложений, обнаружение проблем с ними и отслеживание их взаимосвязей
Что ты узнаешь: как понимать, что происходит внутри системы, по её внешним сигналам — метрикам, логам и трейсам; как ставить осмысленные цели надёжности и не тонуть в бесполезных алертах
Что нужно знать заранее: темы 4 и 5 (контейнеры и Kubernetes), тема 2 (HTTP-коды — на них строится половина метрик)
Сколько времени займёт: 4 часа теории + 8–10 часов практики
Твой шаг в сквозном проекте: научишь «Заметки» отдавать метрики, соберёшь их Prometheus’ом, построишь дашборд и настроишь алерт, который сработает, когда ты специально всё сломаешь
Представь, что у тебя есть большая фабрика с сотнями станков. Каждый станок что-то делает, между ними по конвейерам ездят детали, а в конце получаются готовые телефоны. Если завтра один станок сломается — заметишь ли ты это сразу? А через час?
Точно так же современное приложение — это не одна программа, а десятки или сотни маленьких сервисов, общающихся друг с другом. У тебя может быть отдельный сервис для авторизации, отдельный для каталога товаров, отдельный для оплаты, отдельный для уведомлений. Когда пользователь жмёт «купить», запрос проходит через 10 разных сервисов. Если один из них сломается или начнёт тормозить — без правильных инструментов ты узнаешь об этом из жалоб клиентов, а не от системы.
Observability (наблюдаемость) — это способность по выходным сигналам системы понимать, что происходит внутри неё. На русский часто переводят как «наблюдаемость», но термин «observability» уже устойчиво прижился. Это не то же самое, что мониторинг — это его эволюция.
Три кита observability
Современная наблюдаемость стоит на трёх «китах» — три типа данных, которые мы собираем с системы:
- Метрики (Metrics) — числовые показатели во времени. «Сейчас 12 запросов в секунду», «средняя задержка 50 мс», «использовано 70% CPU». Дёшево хранить, легко агрегировать. Отвечают на вопрос «что происходит?».
- Логи (Logs) — текстовые записи событий с временной меткой. «
2026-04-15 10:23:01 ERROR: connection to db timeout». Дорого хранить (много данных), но содержат подробности. Отвечают на вопрос «почему это произошло?». - Трейсы (Traces) — путь одного запроса через все сервисы системы. «Запрос пришёл в API Gateway → ушёл в auth-service (5 мс) → ушёл в catalog-service (45 мс — вот где тормоз!) → вернулся пользователю». Отвечают на вопрос «где это произошло?».
В современных системах к ним часто добавляют четвёртый «кит» — события (Events) и профили (Continuous Profiling) — но базовая модель остаётся.
Метрики и Prometheus
Prometheus — самый популярный движок мониторинга, де-факто стандарт в облачных и Kubernetes-системах. Это open-source проект под управлением CNCF (Cloud Native Computing Foundation). В ноябре 2024 года вышел Prometheus 3.0 с большими улучшениями: нативные гистограммы, поддержка OTLP, UTF-8 в названиях метрик.
Как работает Prometheus
- Pull-модель — Prometheus сам ходит по приложениям и забирает метрики с эндпоинта
/metrics. Это противоположно push-модели, где приложение само отправляет данные. Pull удобнее для service discovery в Kubernetes и для отладки. - Time-series database — данные хранятся как временные ряды:
metric_name{label1="value1", label2="value2"} value @timestamp. - PromQL — мощный язык запросов, на котором строятся графики, recording rules и алерты.
- Service discovery — Prometheus сам находит, какие приложения и поды нужно опрашивать (через Kubernetes API, файлы, Consul, etc.).
Основные типы метрик
- Counter — счётчик, только растёт (или сбрасывается в 0 при рестарте). Примеры:
http_requests_total,errors_total. Из них считают rate. - Gauge — значение, которое может расти и падать. Примеры:
memory_usage_bytes,current_connections,queue_size. - Histogram — распределение значений по бакетам. Например, сколько запросов уложились в 100 мс, сколько в 500 мс, сколько в 1 секунду. Из него считают перцентили (P50, P95, P99).
- Summary — похож на гистограмму, но перцентили считаются на стороне приложения. Используется реже.
В Prometheus 3.0 появились native histograms — компактнее и точнее, чем классические бакеты, но пока поддерживаются не всеми клиентскими библиотеками.
Примеры PromQL-запросов
# Запросов в секунду за последние 5 минут
sum(rate(http_requests_total[5m]))
# По коду ответа
sum by (status) (rate(http_requests_total[5m]))
# Процент ошибок (5xx) от всех запросов
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m]))
# 95-й перцентиль времени отклика
histogram_quantile(0.95,
sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
# Использование памяти приложением, в % от лимита
container_memory_usage_bytes{pod=~"my-app-.*"}
/ container_spec_memory_limit_bytes{pod=~"my-app-.*"} * 100
Grafana — визуализация
Grafana — самый популярный инструмент для построения дашбордов. Подключается ко множеству источников: Prometheus, Loki, Tempo, Elasticsearch, PostgreSQL, ClickHouse. В 2026 году актуальна версия Grafana 11.
Возможности Grafana:
- Дашборды — наборы графиков, доступных команде через браузер.
- Alerting — встроенная система алертов (Unified Alerting, заменила старую legacy).
- Annotations — отметки на графиках (релизы, инциденты).
- Provisioning as code — все дашборды и алерты можно описывать в YAML/JSON и хранить в Git.
- Plugin ecosystem — сотни плагинов под разные источники данных.
Любители готового могут пользоваться Grafana Cloud — SaaS-версией со встроенным Prometheus, Loki, Tempo и хранилищем «из коробки». Бесплатный tier позволяет хранить метрики 14 дней.
Логирование: Loki и ELK
Логи — это второй кит. Их собирают со всех серверов, контейнеров, приложений в одно центральное место, чтобы можно было искать по тексту и фильтровать.
Loki — «Prometheus для логов»
Grafana Loki — современный движок логов от той же команды, что делает Grafana. Главная идея: индексировать только метаданные (лейблы), а не полный текст логов. Это делает Loki в 10–100 раз дешевле в хранении, чем Elasticsearch.
Архитектура Loki:
- Promtail / Grafana Alloy — агент, который собирает логи на узлах и отправляет в Loki. Grafana Alloy (универсальный коллектор) заменяет Promtail с 2024 года.
- Loki — движок хранения. Хранит данные в Object Storage (S3, Yandex Object Storage).
- Grafana — интерфейс для поиска и анализа.
Язык запросов LogQL очень похож на PromQL:
# Логи приложения my-app с уровнем error
{app="my-app", level="error"}
# Поиск по тексту
{app="my-app"} |= "connection timeout"
# Только за последние 5 минут с регуляркой
{app="my-app"} |~ "user_id=\\d+" | json
# Rate ошибок
rate({app="my-app", level="error"}[5m])
ELK / Elastic Stack
Elasticsearch + Logstash + Kibana — классический стек, более старый, но всё ещё популярный. Полнотекстовый поиск работает лучше Loki, но в разы дороже из-за полной индексации.
- Elasticsearch — поисковый движок и хранилище логов.
- Logstash — pipeline для парсинга и трансформации логов.
- Kibana — UI для поиска и дашбордов.
- Filebeat / Fluent Bit — лёгкие агенты сбора логов с серверов.
⚠️ В 2021 году Elasticsearch сменил лицензию на SSPL, что было воспринято как «closed source». В ответ AWS форкнул проект и создал OpenSearch — полностью open-source версию. Сейчас OpenSearch активно развивается и для многих случаев — оптимальная замена.
Что выбрать: Loki или ELK?
| Критерий | Loki | ELK / OpenSearch |
|---|---|---|
| Стоимость хранения | Низкая | Высокая |
| Поиск по тексту | Простой | Мощный |
| Аналитика, агрегации | Базовая | Очень богатая |
| Интеграция с Prometheus/Grafana | Идеальная | Нужны плагины |
| Сложность эксплуатации | Низкая | Средняя–высокая |
| Подходит для | Большинства DevOps-сценариев | Search-кейсы, SIEM, аудит |
В 2026 году для нового стека observability обычно начинают с Loki. ELK/OpenSearch остаётся для случаев, где нужен мощный поиск (например, безопасность, SIEM, аудит-логи финтеха).
Трейсинг: путь запроса через систему
Когда у тебя 50 микросервисов, и пользователь жалуется на медленную страницу, единственный способ понять, где именно тормозит — посмотреть трейс (распределённую трассировку). Трейс — это дерево вызовов: главный запрос → подзапросы → их подзапросы и т. д.
OpenTelemetry — единый стандарт 2026 года
OpenTelemetry (часто сокращают до OTel) — это единый открытый стандарт для всех типов телеметрии (трейсы, метрики, логи), под управлением CNCF. К 2026 году OpenTelemetry стал безусловным стандартом — все новые приложения должны инструментироваться через него, а не через специфичные SDK конкретных движков.
Структура OpenTelemetry:
- API — то, что вызывает приложение в коде (
tracer.start_span(...)). - SDK — реализация API в конкретном языке (Python, Go, Java, .NET, Node.js — поддерживаются все основные).
- Collector — отдельный демон, который принимает данные, преобразует и отправляет в одно или несколько хранилищ.
- OTLP — протокол передачи телеметрии (
OpenTelemetry Protocol). Поддерживается Prometheus 3.0, Jaeger, Tempo и др.
Главные преимущества: один SDK подходит ко всем хранилищам. Перешёл с Jaeger на Tempo? Не нужно переписывать приложение, достаточно поменять конфиг Collector’а.
Хранилища трейсов
- Jaeger — классический open-source трейсер от Uber. Прост, надёжен, но плохо масштабируется на сотни миллионов спанов в сутки.
- Grafana Tempo — современный движок от Grafana Labs. Хранит данные в Object Storage (как Loki), масштабируется почти бесконечно, дёшев. В 2026 году — основной выбор для новых стеков.
- Yandex Cloud Tracing — managed-сервис в Yandex Cloud, OTLP-совместимый.
- Zipkin — самый старый из живых, но используется всё реже.
Что показывает трейс
Один трейс — это «дерево» спанов (span — единица работы). Например, для HTTP-запроса:
Span 1: GET /api/order/123 250 ms
├── Span 2: auth.verify_token 15 ms
├── Span 3: order_service.get_order 180 ms
│ ├── Span 4: postgres.SELECT * FROM orders 12 ms
│ ├── Span 5: redis.GET order:123 1 ms
│ └── Span 6: kafka.publish order.viewed 3 ms
└── Span 7: response.serialize 5 ms
Видно: 72% времени съел сам order_service.get_order, в нём чистая БД — 12 мс, остальное — что-то ещё. Дальше можно копать дальше.
Service Mesh: Istio, Linkerd, Cilium
В микросервисной архитектуре service mesh берёт на себя сетевое общение между сервисами: маршрутизацию, шифрование (mTLS), retry, rate limiting, observability «из коробки».
Istio
Самый мощный и самый сложный service mesh. Состоит из:
- Control plane (
istiod) — управляет конфигурацией. - Data plane — раньше это были sidecar-контейнеры Envoy в каждом поде. С версии 1.24 (ноябрь 2024, GA) Istio поддерживает Ambient mode — без сайдкаров, что радикально снижает накладные расходы.
Что умеет Istio:
- Автоматический mTLS между всеми сервисами (шифрование внутри кластера).
- Маршрутизация: A/B-тесты, канареечные релизы, blue-green.
- Retry, circuit breaker, timeout — без изменений кода приложений.
- Метрики (Prometheus-формат), трейсы (OpenTelemetry).
Linkerd
Более простая и легковесная альтернатива Istio. Не такая богатая функциональность, но проще в эксплуатации, меньше потребляет ресурсов.
Cilium
В 2026 году Cilium — это уже не только CNI (сетевой плагин для Kubernetes), но и полноценный service mesh, построенный на технологии eBPF. eBPF позволяет запускать программы прямо в ядре Linux, что даёт огромную производительность и минимальные накладные расходы. Cilium умеет:
- Полностью заменять
kube-proxy(используется в Google GKE Dataplane V2 и многих managed Kubernetes). - Делать sidecar-less service mesh с mTLS.
- Глубокую сетевую observability через Hubble — видно, кто с кем общается, на каких портах, по каким протоколам.
В 2026 году выбор обычно такой:
- Хочешь максимум возможностей и не боишься сложности → Istio Ambient.
- Хочешь простоту → Linkerd.
- Уже используешь Cilium как CNI и нужна базовая mesh-функциональность → Cilium Service Mesh.
eBPF-based observability
eBPF — революционная технология ядра Linux, позволяющая прозрачно собирать метрики, логи и трейсы прямо с уровня ядра, не модифицируя приложения. К 2026 году появилось целое поколение eBPF-инструментов:
- Pixie (был куплен New Relic, потом отдан в CNCF) — нулевая интрументация, мгновенная видимость сервисов в Kubernetes.
- Coroot — open-source платформа, собирает все три кита (метрики, логи, трейсы) и автоматически рисует карту сервисов, обнаруживает аномалии. Изучать рекомендуется через demo: https://demo.coroot.com
- Cilium Hubble — наблюдаемость для сети Kubernetes через eBPF.
- Parca — continuous profiling через eBPF (видно, какие функции в коде едят больше всего CPU).
Это направление активно растёт и постепенно дополняет (а иногда вытесняет) классический Prometheus + ручную инструментацию.
Золотые сигналы и методы мониторинга
Four Golden Signals (Google SRE)
Четыре сигнала, которые нужно мониторить для любого пользовательского сервиса:
- Latency (Задержка) — сколько времени занимает запрос. Отдельно успешные и неуспешные.
- Traffic (Трафик) — сколько запросов идёт. RPS, QPS, MB/s, в зависимости от типа сервиса.
- Errors (Ошибки) — какой процент запросов завершается ошибкой.
- Saturation (Насыщение) — насколько забиты ресурсы. CPU, память, диск, очереди.
RED method (для сервисов)
Усечённая версия Golden Signals от Tom Wilkie (Grafana Labs), применимая к любому сервису:
- Rate — запросов в секунду.
- Errors — процент ошибок.
- Duration — длительность запросов.
USE method (для ресурсов)
От Brendan Gregg, применим к любому ресурсу (CPU, диск, сеть):
- Utilization — занятость.
- Saturation — насколько перегружен.
- Errors — ошибки.
SLO, SLI, Error Budget — фундамент SRE
SLI (Service Level Indicator) — измеримый показатель качества сервиса. Например, «доля успешных HTTP-запросов».
SLO (Service Level Objective) — целевое значение SLI. Например, «99.9% запросов должны быть успешными за rolling 30-day window».
SLA (Service Level Agreement) — контрактное обязательство перед клиентом. Обычно слабее SLO (если SLO = 99.9%, SLA = 99.5%, чтобы был запас).
Error Budget — допустимое количество ошибок, чтобы оставаться в SLO. Если SLO = 99.9% за 30 дней, error budget = 0.1% × 43200 минут = 43.2 минуты downtime в месяц. Пока бюджет не израсходован — можно катить рисковые релизы. Если израсходован — заморозка релизов, фокус на стабильности.
Burn Rate — скорость сжигания error budget. Multi-window burn rate alerts (5-минутное окно + 1-часовое) — золотой стандарт для алертов 2026 года.
Алерты — правильно и неправильно
Хорошие алерты:
- Срочные (page) — только то, что требует немедленного вмешательства человека в любое время суток (например, основной сервис лёг, error budget сжигается за час).
- Несрочные (ticket) — для разбора в рабочее время (медленный диск, рост ошибок не на критичных эндпоинтах).
- Symptom-based — на симптомы, видимые пользователю (latency, error rate), а не на причины (CPU 100%, который мог даже не сказаться на пользователях).
- Actionable — с конкретным runbook: «делай 1, 2, 3».
Плохие алерты:
- На любой пик CPU/RAM («железо живёт своей жизнью»).
- Без ясного действия — «что мне с этим делать?»
- Слишком чувствительные — будят инженера каждые 5 минут.
- Без приоритизации — всё «critical».
Хороший on-call: за смену 0–1 настоящих алерта. Если будят чаще — нужно срочно чинить алерты и причины, иначе выгорание гарантировано.
Теоретические вопросы
-
Что такое observability и чем отличается от мониторинга? Ответ: Мониторинг — наблюдение за заранее известными показателями (CPU, RAM, error rate). Observability — способность ответить на любой новый вопрос о системе по её внешним сигналам, даже на тот, который не был предусмотрен заранее. Для observability нужны три кита: метрики, логи, трейсы.
-
Перечисли три (или четыре) кита observability и приведи примеры инструментов. Ответ: Метрики (Prometheus, VictoriaMetrics), логи (Loki, Elasticsearch/OpenSearch), трейсы (Tempo, Jaeger). Иногда добавляют непрерывное профилирование (Parca, Pyroscope) как четвёртый кит.
-
Pull vs Push в мониторинге — в чём разница? Ответ: Pull — система мониторинга сама ходит и забирает метрики (Prometheus). Push — приложение само отправляет метрики (StatsD, Graphite). Pull удобнее для service discovery и отладки (приложение всегда отдаёт
/metrics), push — для систем с динамическими/короткоживущими процессами (CronJob, Lambda) или когда приложение за NAT. -
Что такое Counter, Gauge, Histogram в Prometheus? Ответ: Counter — только растущий счётчик (запросы, ошибки). Gauge — может расти и падать (CPU, память, очередь). Histogram — распределение значений по бакетам, нужен для перцентилей задержки.
-
Что такое PromQL? Приведи пример rate-запроса. Ответ: Язык запросов Prometheus.
rate(http_requests_total[5m])— скорость роста счётчика за последние 5 минут, то есть RPS. -
Что такое recording rule и зачем оно нужно? Ответ: Заранее вычисляемое выражение, которое сохраняется как новая метрика. Используется для тяжёлых вычислений, которые применяются часто (на дашбордах, в алертах). Снижает нагрузку на Prometheus, ускоряет дашборды, делает алерты надёжнее.
-
Чем отличается Loki от Elasticsearch? Ответ: Loki индексирует только лейблы, а не полный текст логов — дешевле в 10–100 раз, но поиск по тексту менее гибкий. Elasticsearch индексирует всё — дорого, но мощный полнотекстовый поиск и аналитика. Loki — для большинства DevOps-сценариев, Elasticsearch/OpenSearch — для SIEM, аудит-логов, мощного поиска.
-
Что такое OpenTelemetry и почему он стал стандартом? Ответ: Единый открытый стандарт CNCF для всех типов телеметрии (трейсы, метрики, логи). Стандартизировал API, SDK и протокол передачи (OTLP). Раньше каждый трейсер (Jaeger, Zipkin, Datadog) имел свой SDK — переход с одного на другой был болью. OpenTelemetry эту проблему решил: переключение хранилища — это конфиг, не код.
-
Что такое distributed trace и span? Ответ: Trace — полный путь запроса через систему (дерево). Span — одна единица работы внутри trace: HTTP-вызов, запрос к БД, обработка функцией. Каждый span имеет ID, parent_id (формирует дерево), время начала и длительность.
-
Что такое Service Mesh? Какую проблему он решает? Ответ: Слой сетевой инфраструктуры между микросервисами. Берёт на себя: mTLS-шифрование, retry, timeout, circuit breaker, load balancing, observability — без изменения кода приложений. Главные представители: Istio, Linkerd, Cilium.
-
Что такое Istio Ambient mode и чем он лучше классического Istio? Ответ: Архитектура Istio без sidecar-контейнеров в каждом поде. Стабильна с Istio 1.24 (ноябрь 2024). Преимущества: меньше потребляет CPU/RAM (нет сайдкара на каждый под), проще rollout (не нужно перезапускать поды для обновления mesh), безопаснее (меньше attack surface). Недостатки: пока менее богатая функциональность чем классический режим.
-
Что такое eBPF и какую роль он играет в observability 2026 года? Ответ: Технология ядра Linux, позволяющая запускать программы внутри ядра без модификации ядра. Позволяет прозрачно собирать метрики, логи, трейсы прямо с уровня kernel space, без инструментации приложений. Лежит в основе современных observability-инструментов (Cilium Hubble, Pixie, Coroot, Parca).
-
Что такое SLI, SLO, SLA? Ответ: SLI — измеримый показатель (например, % успешных запросов). SLO — целевое значение SLI (например, 99.9%). SLA — внешнее контрактное обязательство (обычно слабее SLO, чтобы был запас).
-
Что такое Error Budget? Ответ: Допустимое количество «плохих» событий, чтобы оставаться в SLO. SLO 99.9% за 30 дней = error budget 43.2 минуты downtime. Пока бюджет есть — релизы катим, как только израсходован — заморозка и фокус на надёжности.
-
Что такое burn rate и multi-window burn rate alert? Ответ: Burn rate — текущая скорость сжигания error budget. Multi-window — алерт срабатывает, когда одновременно два временных окна (короткое и длинное) показывают высокий burn rate. Это снижает ложные срабатывания и позволяет ловить как «быстрые катастрофы», так и «медленные деградации».
-
Назови Four Golden Signals и приведи метрику для каждого. Ответ: Latency (
histogram_quantile(0.95, ...)), Traffic (rate(requests_total)), Errors (rate(errors_total) / rate(requests_total)), Saturation (cpu_usage / cpu_limit). -
Что такое cardinality и почему он критичен для Prometheus? Ответ: Количество уникальных комбинаций лейблов у метрики. Метрика
http_requests_total{path="/api/users/123"}с user_id в пути создаст миллионы рядов и убьёт Prometheus. Правило: лейблы должны быть с конечным небольшим набором значений (status, method, route, но не user_id и не request_id). -
Зачем алерты сначала идут в Alertmanager, а не в Slack/Telegram напрямую? Ответ: Alertmanager делает дедупликацию (одно событие — один алерт, а не сто), группировку (схожие алерты вместе), маршрутизацию (critical → on-call, warning → ticket), ингибицию (если упал хост — не шуметь про сервисы на нём), silence (на время плановых работ).
-
Что такое RED-метод и для чего он применяется? Ответ: Rate, Errors, Duration — три метрики, которые надо мониторить для каждого сервиса (от Tom Wilkie). Универсальный подход для микросервисов.
-
Назови минимальный observability-стек для нового проекта в 2026 году. Ответ: Метрики — Prometheus + Grafana, логи — Loki + Promtail/Alloy, трейсы — Tempo, инструментация приложений — OpenTelemetry SDK + Collector, алерты — Alertmanager. Для Kubernetes-кластера установить
kube-prometheus-stack(Helm-чарт), и это всё через 30 минут.
Вопросы с собеседований
-
Что нужно сделать в приложении, чтобы его трейсы появились в Jaeger? Ответ: Подключить SDK OpenTelemetry, настроить экспортёр на адрес коллектора по протоколу OTLP и добиться передачи контекста трассировки между сервисами — заголовок
traceparentдолжен пробрасываться во все исходящие запросы. Для популярных фреймворков есть автоматическая инструментация, покрывающая HTTP-клиенты и запросы к базе без правки кода. Без проброса контекста трейсы получатся, но развалятся на отдельные несвязанные куски -
Как выглядит правило алерта в Prometheus и что означает поле
for? Ответ:- alert: HostOutOfMemory expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10 for: 2m # условие должно держаться 2 минуты подряд labels: severity: warning annotations: description: "На {{ $labels.instance }} осталось менее 10% памяти"forзащищает от ложных срабатываний на кратковременных всплесках: при0mалерт сработает от единичного выброса -
Что такое золотые сигналы и как они соотносятся с методом RED? Ответ: Четыре золотых сигнала Google SRE: задержка, трафик, ошибки, насыщенность. RED — упрощение до трёх (Rate, Errors, Duration), удобное для микросервисов. USE — взгляд со стороны ресурсов: утилизация, насыщенность, ошибки. На практике RED применяют к сервисам, USE — к железу
- Как правильно писать логи приложения, чтобы с ними было удобно работать?
Ответ: Структурированно, в формате JSON, в стандартный вывод. Вместо строки
18:45:02 error: failed to start— объект с полями:{"time": "2026-08-01T18:45:02Z", "level": "ERROR", "service": "notes", "message": "failed to start", "trace_id": "abc123"}Так по логам можно фильтровать и агрегировать, а
trace_idсвязывает запись с конкретным трейсом. Писать в файл внутри контейнера не нужно — сборщик логов читает стандартный вывод -
Где в Kubernetes лежат логи контейнеров и что будет, если под удалить? Ответ: На ноде, в
/var/log/pods/и/var/log/containers/, с ротацией средствами kubelet. При удалении пода логи исчезают вместе с ним, аkubectl logsпоказывает только текущий и предыдущий запуск. Поэтому логи собирают агентом (Promtail, Fluent Bit, Filebeat) в отдельное хранилище — иначе разбирать ночную аварию будет не по чему - С чего начать мониторинг нового Kubernetes-кластера?
Ответ: Поставить
kube-prometheus-stack— это Helm-чарт, который разворачивает Prometheus Operator, Grafana, Alertmanager, node-exporter, kube-state-metrics и набор готовых дашбордов и правил. Базовое покрытие получается за полчаса, дальше добавляют метрики своих приложений
Сервисная сетка (service mesh)
-
Из чего состоит service mesh? Ответ: Из двух частей. Data plane — прокси, через которые реально идёт трафик: Envoy в Istio, собственный лёгкий прокси на Rust в Linkerd. Control plane — управляющий компонент (
istiodу Istio), который раздаёт прокси конфигурацию, выдаёт сертификаты и собирает телеметрию. Приложение при этом не меняется: трафик заворачивают в прокси прозрачно -
Почему у service mesh метрики появляются сами, без правки приложения? Ответ: Весь трафик проходит через прокси, а он видит каждый запрос: метод, путь, код ответа, длительность. Отсюда RED-метрики для всех сервисов сразу и автоматическая карта зависимостей — кто к кому ходит. Это и есть главная причина, по которой mesh ставят ради observability, даже если управление трафиком не нужно
-
Что такое mTLS и что он даёт? Ответ: Взаимный TLS: не только клиент проверяет сервер, но и сервер проверяет клиента. Каждому сервису mesh выдаёт собственный сертификат-удостоверение и сам их ротирует. В результате трафик внутри кластера шифруется, а сервис может авторизовать вызовы по имени вызывающего, а не по IP-адресу, который в Kubernetes ничего не значит
-
Чем sidecar-режим отличается от ambient? Ответ: В sidecar-режиме прокси добавляется контейнером в каждый под: расход памяти и CPU умножается на число подов, а обновление mesh требует перезапуска всех подов. В ambient прокси вынесен из подов: на каждой ноде работает
ztunnelдля шифрования и маршрутизации на транспортном уровне, а разбор HTTP при необходимости берёт на себя отдельныйwaypoint-прокси. Платить за возможности уровня приложения приходится только там, где они действительно нужны -
Как в Istio настраивают маршрутизацию трафика? Ответ:
VirtualServiceописывает правила («90% в версию v1, 10% в v2» или «запросы с определённым заголовком — в v2»),DestinationRuleзадаёт подмножества версий, политику балансировки и отсечение сбойных экземпляров,Gateway— точку входа снаружи. Именно на разделении трафика по весам строится канареечный релиз из темы 9 -
Что такое circuit breaker и зачем он нужен? Ответ: Механизм, который перестаёт слать запросы к экземпляру, отвечающему ошибками, и временно выводит его из ротации. Смысл — не дать одному больному сервису обрушить всю систему: без него вызывающие копятся на таймаутах, исчерпывают пулы соединений и падают следом. Это называют каскадным отказом
-
Чем опасны автоматические повторы запросов? Ответ: Если сервис уже перегружен, повторы умножают нагрузку и добивают его — это шторм повторов. Правила: ограничивать число попыток и общий бюджет повторов, повторять только безопасные операции (иначе платёж пройдёт дважды), обязательно сочетать с таймаутом и добавлять случайную задержку между попытками
-
Чем Linkerd отличается от Istio, а Cilium — от обоих? Ответ: Linkerd проще и легче: свой минималистичный прокси, меньше возможностей, но и меньше накладных расходов и меньше способов выстрелить себе в ногу. Istio функциональнее и сложнее, стандарт для крупных установок. Cilium работает на eBPF в ядре: на транспортном уровне прокси не нужен вовсе, а Envoy подключается по одному на ноду для разбора HTTP — заодно Cilium закрывает и задачу сетевого плагина кластера
-
Когда service mesh не нужен? Ответ: Когда сервисов мало и связей между ними немного; когда команда не готова эксплуатировать ещё один сложный компонент; когда критична задержка — каждый прокси добавляет её. Часть задач решается дешевле: mTLS даёт и Cilium без полного mesh, повторы и таймауты умеет Ingress-контроллер, а трейсинг — OpenTelemetry в приложении. Правило: mesh внедряют, когда есть конкретная проблема, а не «чтобы было»
Метрики и хранение
-
Чем histogram отличается от summary в Prometheus? Ответ: Histogram распределяет значения по заранее заданным корзинам, а перцентиль считается уже при запросе через
histogram_quantile— поэтому его можно агрегировать по нескольким экземплярам приложения. Summary считает перцентили прямо в приложении, они точнее, но складывать их между экземплярами математически нельзя. На практике почти всегда берут histogram -
Зачем нужны recording rules? Ответ: Они заранее вычисляют тяжёлое выражение и сохраняют результат как новую метрику. Дашборд и алерт читают готовое значение вместо того, чтобы каждый раз пересчитывать агрегацию по тысячам рядов. Это ускоряет панели и, что важнее, делает алерты надёжными: сложный запрос может не успеть выполниться и алерт молча не сработает
-
Что такое staleness в Prometheus? Ответ: Если цель перестала отдавать метрику, Prometheus через некоторое время помечает её как устаревшую, и она пропадает из результатов вместо того, чтобы «застыть» на последнем значении. Отсюда практическое следствие: алерт вида
метрика > порогане сработает, если метрика вовсе исчезла. Пропажу ловят отдельно — черезup == 0или функциюabsent -
Prometheus не тянет объём данных. Какие есть варианты? Ответ: Сначала снизить кардинальность и увеличить интервал сбора — часто этого достаточно. Дальше — федерация или переход на решения для долгого хранения: Thanos, Mimir, VictoriaMetrics. Они принимают данные через remote write, хранят их в объектном хранилище и дают единый запрос по нескольким кластерам
-
Что такое кардинальность и как найти метрику, которая «взорвалась»? Ответ: Число уникальных сочетаний меток. Каждое сочетание — отдельный временной ряд в памяти. Виновника ищут запросом
topk(10, count by (__name__)({__name__=~".+"}))и на странице/status/tsdbв интерфейсе Prometheus. Причина почти всегда одна: в метку попало что-то с неограниченным набором значений — идентификатор пользователя, запроса или полный URL -
Чем pull-модель Prometheus удобнее push? Ответ: Проще обнаруживать цели и понимать, что цель жива: сам факт неудачного сбора даёт метрику
up == 0. Метрики приложения можно посмотреть глазами, открыв/metrics. Push нужен там, где pull невозможен: короткоживущие задачи (для них есть Pushgateway), процессы за NAT, бессерверные функции
Логи, трейсинг и дежурство
-
Почему у Loki другой подход к логам, чем у Elasticsearch? Ответ: Loki индексирует только метки (сервис, пространство имён, уровень), а само содержимое хранит сжатым и просматривает при запросе. Это в разы дешевле, но требует сначала сузить поиск метками. Elasticsearch индексирует весь текст: поиск мощнее, но хранение дороже кратно. Ошибка при работе с Loki — класть в метки то, что имеет много значений: это ломает его основное преимущество
-
Что такое сэмплирование трейсов и зачем оно? Ответ: Сохранение не всех трейсов, а части: хранить каждый запрос нагруженного сервиса невозможно по объёму. Простое сэмплирование берёт фиксированный процент. Умное (хвостовое) решает после завершения запроса и сохраняет все ошибочные и медленные, а из успешных — небольшую долю. Второе заметно полезнее: интересны как раз аномалии
-
Как связать лог, метрику и трейс? Ответ: Общим идентификатором трассировки: приложение пишет
trace_idв каждую строку лога, а метрики поддерживают exemplars — ссылки на конкретные трейсы. Тогда из всплеска на графике переходишь в трейс медленного запроса, а из него — в логи именно этого запроса. Это и отличает настоящую наблюдаемость от трёх независимых систем -
Что такое MTTD, MTTR и MTBF? Ответ: Среднее время до обнаружения, среднее время восстановления и среднее время между отказами. Мониторинг напрямую влияет на первое, а runbook и автоматизация — на второе. Инженеру важно понимать: снизить время обнаружения обычно дешевле и полезнее, чем героически сокращать время починки
-
Что такое усталость от алертов и как с ней бороться? Ответ: Состояние, когда алертов так много, что их перестают читать, — и настоящая авария теряется в шуме. Лечится так: будить человека только тем, что требует немедленного действия, остальное отправлять в задачи; убрать алерты без runbook; следить за симптомами, а не за причинами; настроить группировку и подавление в Alertmanager; регулярно пересматривать сработавшие алерты и удалять бесполезные
-
Что такое runbook и чем он отличается от постмортема? Ответ: Runbook — инструкция «что делать, когда сработал этот алерт»: как проверить, как починить, кому эскалировать. Пишется заранее, ссылка на него кладётся прямо в аннотацию алерта. Постмортем — разбор уже случившегося инцидента: хронология, причина, выводы. Хороший постмортем часто рождает новый runbook
-
Что такое разбор инцидента без поиска виноватых и зачем так? Ответ: Разбор, где причины формулируются через процессы и системы, а не через людей: не «Петя выкатил плохой конфиг», а «выкатка не требовала проверки и не имела быстрого отката». Смысл практический: если за ошибки наказывают, люди перестают о них сообщать, и организация теряет возможность учиться. Человеческая ошибка — это симптом, а не причина
Практическая часть
Задание 1. Развернуть полный стек на одной машине через Docker Compose
Цель: Получить рабочий monitoring-стек локально.
Шаги:
-
Создай папку и файл
compose.yml:services: prometheus: image: prom/prometheus:v3.1.0 ports: ["9090:9090"] volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prom_data:/prometheus command: - "--config.file=/etc/prometheus/prometheus.yml" - "--web.enable-lifecycle" - "--enable-feature=otlp-write-receiver" restart: unless-stopped grafana: image: grafana/grafana:11.4.0 ports: ["3000:3000"] environment: GF_SECURITY_ADMIN_PASSWORD: admin volumes: - grafana_data:/var/lib/grafana restart: unless-stopped loki: image: grafana/loki:3.3.0 ports: ["3100:3100"] command: -config.file=/etc/loki/local-config.yaml restart: unless-stopped alloy: image: grafana/alloy:v1.5.0 volumes: - ./alloy-config.river:/etc/alloy/config.river - /var/log:/var/log:ro command: - run - --server.http.listen-addr=0.0.0.0:12345 - /etc/alloy/config.river restart: unless-stopped node-exporter: image: prom/node-exporter:v1.8.2 ports: ["9100:9100"] pid: host volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro command: - "--path.procfs=/host/proc" - "--path.sysfs=/host/sys" restart: unless-stopped alertmanager: image: prom/alertmanager:v0.28.0 ports: ["9093:9093"] volumes: - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml restart: unless-stopped tempo: image: grafana/tempo:2.6.1 ports: ["3200:3200", "4317:4317"] command: ["-config.file=/etc/tempo.yaml"] volumes: - ./tempo.yaml:/etc/tempo.yaml restart: unless-stopped volumes: prom_data: grafana_data: -
Создай минимальный
prometheus.yml:global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: prometheus static_configs: [{ targets: ["prometheus:9090"] }] - job_name: node static_configs: [{ targets: ["node-exporter:9100"] }] - Запусти всё:
docker compose up -d docker compose ps - Открой:
- Prometheus: http://localhost:9090
- Grafana: http://localhost:3000 (admin / admin)
- Alertmanager: http://localhost:9093
- В Grafana добавь два data source: Prometheus (
http://prometheus:9090) и Loki (http://loki:3100).
Задание 2. Импортировать готовый дашборд
- В Grafana: Dashboards → New → Import.
- ID 1860 (Node Exporter Full) → загрузи.
- Изучи метрики: CPU, RAM, диск, сеть.
Задание 3. Написать свои PromQL-запросы
В Prometheus UI (http://localhost:9090) попробуй:
# Текущая загрузка CPU в %
100 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100
# Доступная память в гигабайтах
node_memory_MemAvailable_bytes / 1024 / 1024 / 1024
# Свободное место на диске /
node_filesystem_avail_bytes{mountpoint="/"} / 1024 / 1024 / 1024
# Запросов в секунду к самому Prometheus
sum(rate(prometheus_http_requests_total[5m]))
Задание 4. Настроить alert и проверить через Alertmanager
-
Добавь в Prometheus файл
alerts.yml:groups: - name: demo rules: - alert: HighCPUUsage expr: 100 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100 > 80 for: 2m labels: { severity: warning } annotations: summary: "Высокая загрузка CPU" description: "CPU > 80% уже 2 минуты" - Добавь его в
prometheus.yml: ```yaml rule_files:- /etc/prometheus/alerts.yml
alerting: alertmanagers: - static_configs: - targets: [“alertmanager:9093”] ```
-
Перезагрузи Prometheus:
curl -X POST http://localhost:9090/-/reload. - Создай искусственную нагрузку, чтобы алерт сработал:
yes > /dev/null & # съест одно ядро на 100% yes > /dev/null & # ещё одно -
Через 2 минуты алерт появится в Prometheus → Alerts и в Alertmanager.
- Останови нагрузку:
pkill yes.
Задание 5. Изучить eBPF observability через Coroot
Цель: Увидеть, как современные инструменты «из коробки» рисуют карту сервисов.
Шаги:
- Открой https://demo.coroot.com — там готовое демо со всеми тремя китами одновременно.
- Изучи Service Map — Coroot автоматически нарисовал граф взаимодействий между сервисами.
- Кликни на любой сервис → посмотри: RED-метрики, логи, трейсы, профайлинг.
- Изучи SLO — Coroot автоматически считает SLO для всех сервисов.
- Прочитай документацию: https://coroot.com/blog/engineering/getting-started-with-coroot-concepts-and-terminology/
Задание 6. Сквозной проект: «Заметки» под наблюдением
Цель: пройти весь путь целиком — научить своё приложение отдавать метрики, собрать их, увидеть на дашборде и получить алерт при поломке
Шаги:
-
Добавь в
app.pyсчётчики и эндпоинт/metrics. Никаких библиотек не нужно — формат Prometheus это обычный текст:# Счётчик запросов: ключ — код ответа, значение — сколько раз встретился REQUESTS = {}В методе
respondперед отправкой ответа добавь:REQUESTS[code] = REQUESTS.get(code, 0) + 1И новую ветку в
do_GET, рядом с/healthz:elif self.path == "/metrics": lines = [ # HELP и TYPE — обязательные служебные строки формата Prometheus "# HELP notes_requests_total Общее число HTTP-запросов", "# TYPE notes_requests_total counter", ] for status, count in sorted(REQUESTS.items()): # Код ответа — это метка (label), по ней потом фильтруют в PromQL lines.append(f'notes_requests_total{{status="{status}"}} {count}') lines.append("# HELP notes_up Приложение живо") lines.append("# TYPE notes_up gauge") lines.append("notes_up 1") self.respond(200, "\n".join(lines) + "\n")Обрати внимание на выбор типов:
counterтолько растёт (число запросов),gaugeможет расти и падать. Это ровно то различие, которое разбиралось в теории -
Проверь локально:
docker compose up -d --build curl http://localhost:8080/ >/dev/null curl http://localhost:8080/нет-такой-страницы >/dev/null curl http://localhost:8080/metricsОжидаемый вывод: строки
notes_requests_total{status="200"} 2иnotes_requests_total{status="404"} 1 -
Добавь приложение в цели Prometheus. В
prometheus.ymlиз задания 1:scrape_configs: - job_name: notes # Prometheus сам ходит за метриками — это pull-модель из теории static_configs: - targets: ["notes:8080"]Перезапусти Prometheus и открой
http://localhost:9090/targets— цельnotesдолжна быть в состоянииUP -
Задай в Prometheus несколько запросов и разберись, что показывает каждый:
notes_requests_total rate(notes_requests_total[5m]) sum(rate(notes_requests_total[5m])) by (status) sum(rate(notes_requests_total{status=~"5.."}[5m])) / sum(rate(notes_requests_total[5m])) -
Построй в Grafana дашборд с тремя панелями по методу RED: запросов в секунду (Rate), доля ошибок (Errors), а вместо Duration пока — доступность приложения (
notes_up) -
Настрой алерт. Создай
rules/notes.yml:groups: - name: notes rules: - alert: NotesDown expr: up{job="notes"} == 0 # Ждём минуту, чтобы не пугаться кратковременной перезагрузки for: 1m labels: severity: critical annotations: summary: "Сервис «Заметки» не отвечает" description: "Prometheus не может собрать метрики уже минуту. Проверь: docker compose ps, docker compose logs notes" - alert: NotesHighErrorRate expr: | sum(rate(notes_requests_total{status=~"5.."}[5m])) / sum(rate(notes_requests_total[5m])) > 0.05 for: 5m labels: severity: warning annotations: summary: "Более 5% запросов завершаются ошибкой"Подключи файл в
prometheus.ymlчерезrule_files:и перезапусти -
Сломай специально и дождись алерта:
docker compose stop notes # Открой http://localhost:9090/alerts — через минуту NotesDown станет Firing docker compose start notes -
Сравни с реальностью. Ответь письменно: за сколько минут ты узнал бы о падении без мониторинга? Кто узнал бы первым — ты или пользователь?
-
Закоммить:
git add app.py monitoring/ git commit -m "Добавить метрики, дашборд и алерты для «Заметок»" git push
Типичные ошибки:
- Цель в состоянии
DOWN— Prometheus в контейнере не видитlocalhost. Внутри Compose обращаться нужно по имени сервиса (notes:8080), как мы разбирали в теме 4 - Метрика с кодом ответа в имени (
notes_requests_200_total) вместо метки — так делать нельзя: в PromQL их не просуммировать. Различающиеся значения выносят в метки - Соблазн добавить в метку идентификатор запроса или пользователя. Это убьёт Prometheus — вспомни вопрос про кардинальность в теоретической части
rate()на слишком коротком окне выдаёт пустоту: интервал должен быть минимум вчетверо больше периода сбора метрик
Задание 7. SLO + Error Budget в проде
Цель: Спроектировать SLO для гипотетического сервиса.
Допустим, у тебя API-сервис payments. Опиши:
- SLI: какая метрика отражает «успешность» с точки зрения пользователя?
- Пример:
(rate(http_requests_total{status!~"5..", service="payments"}[5m]) / rate(http_requests_total{service="payments"}[5m]))
- Пример:
- SLO: какой процент успешных запросов целевой?
- 99.9% за rolling 30 дней.
- Error Budget: сколько минут downtime допускается в месяц?
- 0.1% × 30 × 24 × 60 = 43.2 минуты.
- Burn rate alerts (multi-window):
- Page: если за последние 5 минут И за последний час burn rate > 14.4 (это значит, что в текущем темпе бюджет кончится за ~2 часа).
- Ticket: если за час И за 6 часов burn rate > 3 (бюджет кончится за ~10 дней).
- Error Budget Policy (политика бюджета):
- Бюджет израсходован — заморозка фич, фокус на стабильности.
- Бюджет в норме — можно катить рисковые релизы.
Задание 8. Чек-лист observability на проде
- Все приложения экспортируют метрики в формате Prometheus (через
/metrics). - Все приложения отправляют структурированные логи (JSON) в Loki/ELK.
- Все межсервисные вызовы трейсируются через OpenTelemetry.
- У каждого сервиса есть дашборд RED (Rate, Errors, Duration).
- У каждого критичного сервиса есть SLO и алерты на burn rate.
- Алерты идут в Alertmanager, с группировкой и дедупликацией.
- Алерты actionable — есть runbook.
- On-call инженеры получают 0–1 настоящий алерт за смену, не больше.
- Каждый инцидент завершается blameless postmortem.
- Карта зависимостей сервисов автоматическая (Coroot / Pixie / Hubble / service mesh), не нарисованная вручную.
Проверь себя: тема освоена, если ты можешь
- Объяснить разницу между мониторингом и observability
- Сказать, какой из трёх «китов» нужен для ответа на вопрос «почему именно этот запрос тормозил»
- Написать PromQL-запрос для доли ошибок и для 95-го перцентиля задержки
- Объяснить, что такое кардинальность, и привести пример метки, которая убьёт Prometheus
- Добавить эндпоинт
/metricsв приложение и объяснить разницу между counter и gauge - Спроектировать SLO и посчитать error budget в минутах
- Объяснить, почему алерт на «CPU выше 80%» плохой, и предложить замену
- Показать алерт, который сработал на реально сломанном тобой сервисе