Initial commit: interview prep repo (resume, legend, stack cases, Kubernetes course)
This commit is contained in:
142
stack/monitoring/CASE.md
Normal file
142
stack/monitoring/CASE.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Кейс: стек мониторинга (Prometheus + Grafana + Mimir)
|
||||
|
||||
Связь с легендой: [../../legend/LEGEND.md](../../legend/LEGEND.md) — раздел «АО ТНИИС». Задача инженера сопровождения — собирать метрики, визуализировать их и держать масштабируемое хранилище для истории метрик.
|
||||
|
||||
## Что нужно реально сделать (домашний стенд)
|
||||
|
||||
Разворачиваем локально Prometheus + Mimir + Grafana + node-exporter через Docker Compose. Цель — своими руками пройти путь «метрика с хоста → Prometheus → remote_write в Mimir → дашборд в Grafana», чтобы честно говорить об этом на собеседовании.
|
||||
|
||||
### 1. Структура стенда
|
||||
|
||||
```
|
||||
monitoring-lab/
|
||||
├── docker-compose.yml
|
||||
├── prometheus/
|
||||
│ └── prometheus.yml
|
||||
├── mimir/
|
||||
│ └── mimir.yml
|
||||
└── grafana/
|
||||
└── provisioning/
|
||||
└── datasources/
|
||||
└── datasource.yml
|
||||
```
|
||||
|
||||
### 2. docker-compose.yml
|
||||
|
||||
```yaml
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
node-exporter:
|
||||
image: prom/node-exporter:latest
|
||||
container_name: node-exporter
|
||||
ports:
|
||||
- "9100:9100"
|
||||
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
container_name: prometheus
|
||||
volumes:
|
||||
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
command:
|
||||
- "--config.file=/etc/prometheus/prometheus.yml"
|
||||
ports:
|
||||
- "9090:9090"
|
||||
depends_on:
|
||||
- node-exporter
|
||||
|
||||
mimir:
|
||||
image: grafana/mimir:latest
|
||||
container_name: mimir
|
||||
command: ["-config.file=/etc/mimir/mimir.yml"]
|
||||
volumes:
|
||||
- ./mimir/mimir.yml:/etc/mimir/mimir.yml
|
||||
ports:
|
||||
- "9009:9009"
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: grafana
|
||||
volumes:
|
||||
- ./grafana/provisioning:/etc/grafana/provisioning
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- mimir
|
||||
- prometheus
|
||||
```
|
||||
|
||||
### 3. prometheus/prometheus.yml
|
||||
|
||||
```yaml
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: "node"
|
||||
static_configs:
|
||||
- targets: ["node-exporter:9100"]
|
||||
|
||||
remote_write:
|
||||
- url: "http://mimir:9009/api/v1/push"
|
||||
```
|
||||
|
||||
### 4. mimir/mimir.yml (минимальный single-binary конфиг для лабы)
|
||||
|
||||
```yaml
|
||||
target: all
|
||||
|
||||
blocks_storage:
|
||||
backend: filesystem
|
||||
filesystem:
|
||||
dir: /data/blocks
|
||||
bucket_store:
|
||||
sync_dir: /data/tsdb-sync
|
||||
|
||||
compactor:
|
||||
data_dir: /data/compactor
|
||||
|
||||
ingester:
|
||||
ring:
|
||||
replication_factor: 1
|
||||
|
||||
limits:
|
||||
ingestion_rate: 100000
|
||||
```
|
||||
|
||||
### 5. grafana/provisioning/datasources/datasource.yml
|
||||
|
||||
```yaml
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Mimir
|
||||
type: prometheus
|
||||
access: proxy
|
||||
url: http://mimir:9009/prometheus
|
||||
isDefault: true
|
||||
```
|
||||
|
||||
### 6. Шаги воспроизведения
|
||||
|
||||
1. `docker compose up -d` — поднять весь стенд.
|
||||
2. Открыть Prometheus UI (`localhost:9090/targets`) — убедиться, что target `node` в статусе `UP`.
|
||||
3. Открыть Grafana (`localhost:3000`, admin/admin), проверить, что источник данных `Mimir` отвечает (Explore → запрос `up`).
|
||||
4. Создать дашборд вручную: панель CPU (`rate(node_cpu_seconds_total{mode="idle"}[5m])`), панель памяти (`node_memory_MemAvailable_bytes`), панель дисков.
|
||||
5. Настроить alert rule в Grafana (например, «CPU idle < 20% в течение 5 минут») и проверить, что алерт срабатывает при нагрузке (`stress` внутри контейнера или на хосте).
|
||||
6. Остановить `node-exporter` и убедиться, что Prometheus помечает target как `DOWN`, а в Grafana это видно на дашборде (пропуск данных) — так на практике выглядит инцидент.
|
||||
|
||||
### 7. Что это даёт в разговоре с интервьюером
|
||||
|
||||
- Понимание разницы **Prometheus vs Mimir**: Prometheus — сбор + локальное краткосрочное хранение + alerting-движок; Mimir — горизонтально масштабируемое долгосрочное хранилище метрик, совместимое с PromQL, принимает данные через `remote_write`.
|
||||
- Понимание модели pull (Prometheus сам ходит в `/metrics`) в отличие от push-систем.
|
||||
- Практическое понимание, что такое target, job, scrape_interval, label.
|
||||
- Опыт настройки datasource и дашборда в Grafana руками, а не только просмотр готовых.
|
||||
|
||||
## Нагрузка и цифры
|
||||
|
||||
Один node-exporter — не показатель нагрузки; честная оценка масштаба и вопросы про «как мониторить 300 000 серверов» разобраны в [../../legend/CAPACITY.md](../../legend/CAPACITY.md). На этом стенде можно замерить число активных series (`curl localhost:9090/api/v1/status/tsdb`) и вписать результат в таблицу лабных замеров там же.
|
||||
|
||||
## Как это ложится в легенду
|
||||
|
||||
В реальной работе (АО ТНИИС) — 50 дашбордов в Grafana и настройка Mimir для масштабирования, унификация метрик из разных источников. Домашний кейс воспроизводит тот же путь данных в миниатюре: один источник (node-exporter) вместо десятков, но тот же принцип — Prometheus scrape → remote_write → Mimir → Grafana dashboard.
|
||||
67
stack/monitoring/QUESTIONS.md
Normal file
67
stack/monitoring/QUESTIONS.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Вопросы: мониторинг (Prometheus / Grafana / Mimir)
|
||||
|
||||
Опираются на кейс: [CASE.md](CASE.md).
|
||||
|
||||
### Чем Prometheus отличается от Zabbix/Nagios?
|
||||
|
||||
Prometheus тянет метрики сам (pull-модель) с эндпоинта `/metrics` у сервиса, хранит их как временные ряды с лейблами и даёт мощный язык запросов PromQL. Классические Zabbix/Nagios исторически больше про push-агентов и чек-скрипты с бинарным статусом «ок/не ок». Я поднимал у себя стенд с node-exporter — Prometheus сам ходит и забирает метрики по расписанию (`scrape_interval`), это и есть pull.
|
||||
|
||||
### Что такое target, job, label в Prometheus?
|
||||
|
||||
Target — конкретный адрес, откуда собираются метрики (например, `node-exporter:9100`). Job — логическая группа таргетов одного типа (в моём конфиге — job `node`). Label — пара ключ-значение, которая добавляется к метрике и позволяет фильтровать/группировать в PromQL (`instance`, `job`, и кастомные).
|
||||
|
||||
### Зачем нужен remote_write и чем Mimir отличается от обычного Prometheus?
|
||||
|
||||
Prometheus по умолчанию хранит данные локально и недолго (по умолчанию TSDB держит порядка 15 дней). Если нужно долгосрочное хранение и горизонтальное масштабирование под много Prometheus-инстансов, метрики отправляют через `remote_write` во внешнее хранилище — у меня это Mimir. Mimir совместим с PromQL, поэтому Grafana обращается к нему так же, как к обычному Prometheus-источнику, но данные хранятся отдельно и масштабируемо (у меня — на файловой системе, в проде обычно объектное хранилище типа S3).
|
||||
|
||||
### Как устроен путь метрики от хоста до дашборда?
|
||||
|
||||
node-exporter отдаёт метрики на `/metrics` → Prometheus по scrape_interval их забирает → одновременно пушит их через remote_write в Mimir → Grafana ходит в Mimir как в datasource и рисует панели через PromQL-запросы.
|
||||
|
||||
### Что делать, если target в Prometheus в статусе DOWN?
|
||||
|
||||
Проверить: доступен ли хост/порт сетевым способом (в моём случае — контейнер node-exporter упал или сеть Docker недоступна), отдаёт ли эндпоинт `/metrics` корректный ответ, не изменился ли путь/порт в конфиге scrape_config. Я специально гасил node-exporter в стенде и смотрел, как это отражается в Prometheus targets и на дашборде (пропуски данных).
|
||||
|
||||
### Как написать alert rule и куда он «стреляет»?
|
||||
|
||||
Alert rule — это условие на PromQL-выражение с длительностью (например, «CPU idle < 20% в течение 5 минут» → алерт). В Grafana я настраивал такое правило на дашборде; в проде алерты обычно уходят дальше в Alertmanager/мессенджеры — этого в лабе я не поднимал, но принцип понятен: правило проверяется на интервале evaluation_interval, и если условие держится дольше `for`, алерт переходит из pending в firing.
|
||||
|
||||
### Чем отличается rate() от irate() в PromQL?
|
||||
|
||||
Обе функции считают скорость роста counter-метрики, но `rate()` усредняет по всему интервалу окна (более гладкий график, подходит для алертов и дашбордов), а `irate()` считает по двум последним точкам (более «дёрганый», подходит для быстрого реагирования на всплески). В своих запросах CPU я использовал `rate()`, потому что нужен был сглаженный тренд, а не мгновенный всплеск.
|
||||
|
||||
### Зачем нужна унификация форматов метрик, если данные идут из разных источников?
|
||||
|
||||
Если разные экспортеры называют одну и ту же сущность по-разному (разные названия лейблов, разные единицы измерения), дашборды и алерты становится сложно переиспользовать и сравнивать между сервисами. Унификация — это соглашение об именовании метрик и лейблов, чтобы один и тот же дашборд можно было применить к разным сервисам без переделки запросов.
|
||||
|
||||
### Как организовать доступ к дашбордам для команды?
|
||||
|
||||
В Grafana это роли и права на уровне организации/папок дашбордов плюс подключение аутентификации (LDAP/OAuth/встроенные пользователи). Права разграничиваются так, чтобы просмотр был у всех, а редактирование — у ограниченного круга, чтобы не ломали чужие дашборды.
|
||||
|
||||
### В чём разница между метриками и логами и почему нужны оба?
|
||||
|
||||
Метрики — агрегированные числовые ряды во времени (быстро смотреть тренды, ставить алерты по порогам). Логи — детальные текстовые события конкретного момента (нужны, чтобы понять, что именно произошло внутри инцидента). Метрика в Grafana покажет, что вырос p99 задержки, но причину чаще всего покажут логи — поэтому мониторинг обычно закрывается связкой метрики (Prometheus/Mimir) + логи (ELK, см. [../elk/](../elk/)).
|
||||
|
||||
### Как задеплоил бы мониторинг архитектурно для очень большого парка серверов (например, 300 000)?
|
||||
|
||||
Grafana + Prometheus + Mimir + объектное хранилище (MinIO/S3) под блоки Mimir. Один Prometheus не рассчитан на такой масштаб (публичный ориентир — до ~1–2 млн активных series на инстанс, см. [../../legend/CAPACITY.md](../../legend/CAPACITY.md)), поэтому схема — множество Prometheus-инстансов, шардированных по группам серверов/сервисов (например, по датацентру или по команде), каждый scrape'ит свою часть парка и отправляет данные через `remote_write` в Mimir. Mimir горизонтально масштабируется (ingester/distributor/querier как отдельные компоненты) и хранит блоки в объектном хранилище — это снимает ограничение на объём долгосрочного хранения метрик с одного диска. Grafana обращается к Mimir как к единому PromQL-совместимому источнику, не зная о шардировании снизу. У себя в лабе я воспроизвёл этот же принцип в миниатюре — Prometheus → remote_write → Mimir → Grafana (см. [CASE.md](CASE.md)), просто с одним источником вместо тысяч, и в кластере — [../kubernetes/CASE.md](../kubernetes/CASE.md), где тот же стек развёрнут Helm-чартом `kube-prometheus-stack`.
|
||||
|
||||
### У тебя есть 300 000 метрик от кастомных агентов в формате JSON — как будешь их собирать?
|
||||
|
||||
Раз агенты сами по себе пушат данные и их формат (JSON) нельзя поменять, два реалистичных варианта: (1) pull-модель — написать текстовый файл-адаптер для `node_exporter` через его textfile collector: отдельный процесс парсит входящие JSON (`jq` или скрипт на Python) и периодически перезаписывает `.prom`-файл в формате метрик Prometheus, который `node_exporter` дальше просто отдаёт по scrape; (2) push-модель — если агенты сами инициируют отправку, а не ждут scrape, использовать Pushgateway: агент (или обвязка вокруг него) конвертирует JSON в формат Prometheus и пушит через HTTP API Pushgateway, откуда данные уже забирает Prometheus обычным scrape. Выбор между вариантами зависит от того, кто инициирует передачу — если агенты только отдают данные по запросу, то pull через textfile collector; если сами шлют данные без внешнего опроса — Pushgateway.
|
||||
|
||||
### К тебе пришёл разработчик с жалобой на HTTP 400/500 — как будешь мониторить и почему?
|
||||
|
||||
Начал бы с метрик — они быстрее покажут масштаб и динамику проблемы: в Grafana смотрю долю 4xx/5xx от общего числа запросов во времени (`rate` по статус-коду, если это есть в лейблах метрики — например, у nginx через `nginx-prometheus-exporter` или у самого приложения) — это отвечает на вопросы «когда началось», «это массово или единичный случай», «на каком именно сервисе». Дальше для выяснения точной причины конкретных ошибок — логи (ELK): по временному окну, где метрики показали всплеск, ищу в логах конкретные запросы с этим статус-кодом и смотрю стектрейс/сообщение об ошибке. То есть метрики — для обнаружения и оценки масштаба, логи — для диагностики конкретной причины; в стенде [../nginx/CASE.md](../nginx/CASE.md) я специально проверял, как выглядит 503 от `limit_req` в логах nginx и как это же отразилось бы на метрике доли ошибочных ответов.
|
||||
|
||||
### Работал с Zabbix? Чем он отличается от Prometheus и что такое зонтичный мониторинг?
|
||||
|
||||
Практического опыта с Zabbix у меня нет, но принцип понимаю: Zabbix — классическая push/агентская модель мониторинга с центральным сервером, который получает данные от агентов на хостах (или сам их опрашивает по SNMP/скриптам), и с готовым UI из коробки, включая triggers/actions для алертинга — исторически более «всё в одном», чем связка Prometheus+Grafana, которая собирается из отдельных модульных компонентов. Зонтичный мониторинг — верхнеуровневая система, агрегирующая сигналы (алерты/статусы) от нескольких нижележащих систем мониторинга разных команд/доменов в единую панель для дежурных/руководства — не подменяет специализированные системы мониторинга конкретных сервисов, а сводит их в общую картину состояния на уровне всей организации.
|
||||
|
||||
### Что такое Monq?
|
||||
|
||||
Российская платформа для зонтичного (umbrella) мониторинга и AIOps — агрегирует события/алерты из нижележащих систем мониторинга разных команд (включая Zabbix, Prometheus и другие источники) в единую панель, с возможностью писать сценарии обработки событий (корреляция, автоматические действия по алертам). Личного опыта работы с конкретно Monq у меня нет — знаю его как класс продукта (зонтичный мониторинг, см. вопрос про Zabbix выше) по описанию вакансии, а не по практике; на собеседовании честно обозначил бы это и попросил рассказать подробнее о том, как именно он используется в их процессах.
|
||||
|
||||
### Что такое переменные в Grafana?
|
||||
|
||||
Параметры дашборда, которые можно менять через выпадающий список сверху (например, `$instance`, `$job`, `$datacenter`), не редактируя сами запросы панелей — сами PromQL-запросы ссылаются на переменную (`up{instance="$instance"}`), и при смене значения в выпадающем списке весь дашборд пересчитывается под выбранный контекст. Это то, что позволяет держать один шаблонный дашборд вместо копии на каждый сервис/инстанс — прямое продолжение темы унификации метрик, которая уже разбиралась выше.
|
||||
Reference in New Issue
Block a user