###### tags: `monitoring`
# Базовая система мониторинга серверов с помощью Grafana+Prometheus+Node Exporter. Alert Manager + Telegram
## Краткое описание:
**Prometheus** - центральный сервер, предназначенный для сбора и хранения данных. Данные постоянно изменяются во времени (например, уровень заполненности диска, трафик через сетевой интерфейс, время отклика сайта). Элементы данных называются метриками. Сервер Prometheus с заданной периодичностью считывает метрики и помещает полученные данные в Time Series DB. **Time Series DB** - это разновидность баз данных, предназначенная для хранения временных рядов (значений с привязкой ко времени). Кроме того, Prometheus предоставляет интерфейс для выполнения запросов и визуализации полученных данных. Язык запросов Prometheus называется PromQL. Prometheus работает по модели Pull, то есть он сам опрашивает **endpoints** с целью получения данных.
**Exporters** — процессы, обеспечивающие сбор и их передачу серверу Prometheus. Существует много разных exporters, например:
* Node Exporter - сбор системных метрик(процессор, память и т.п)
* Postgres Exporter - сбор метрик работы сервера PostgreSQL
* ClickHouse exporter - сбор метрик работы сервера Clickhouse
* PgBouncer exporter - сбор метрик connection pool PgBouncer
и т.п
После запуска exporter начинает сбор соответствующих метрик и ожидает запросов от сервера Prometheus по заданному порту. Данных передаются в формате http.
**Grafana** — удобный frontend для визуализации накопленных данных, может использоваться для работы с данными сервера Prometheus, предоставляет различные преднастроенные **Dashboard** для отображения данных.
Помимо функций сбора, анализа и визуализации данных, Prometheus и Grafana поддерживают настраиваемые оповещения. В Grafana этот механизм является встроенным, в Prometheus он реализуется отдельным компонентом (**Alert_manager**).
## Практика. Часть 1
В данной части мы научимся собирать метрики с сервера с помощью **Node Exporter** и **Prometheus**, а затем визуализируем их в **Grafana**
Для создания базовой системы мониторинга будем использовать **docker-compose**
*Схема нашей системы:*
![Uploading file..._w3zmbqviz]()
Наш docker-compose.yml будет состоять из трех контейнеров(сервисов):
* *grafana* - с пробросом портов 3000:3000
* *prometheus* - с пробросом портов 9090:9090
* *node-exporter* - с пробросом портов 9100:9100
Пример конечного docker-compose.yml:
```
version: "3.9"
services:
grafana:
container_name: grafana
image: grafana/grafana:latest
user: "0"
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
prometheus:
container_name: prometheus
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- 9090:9090
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
ports:
- "9100:9100"
volumes:
grafana-data:
prometheus-data:
```
Пояснение к docker-compose файлу:
1. Grafana. Тут все просто, запускаем сервис без дополнительных настроек, разве что добавляем вольюм для сохранения состояния после рестарта.
2. Prometheus. Для того, чтобы Prometheus начал собирать метрики с **экспортеров** нужно создать *config-file*. Его структуру мы рассмотрим позже.
3. Node Exporter. Данный контейнер является "примерным". Обычно node-exporter устанавливают в виде полноценного сервиса-демона на конечные сервера. Но так как мы "имитируем" инфраструктуру для мониторинга в виде одного docker-compose файла, то давайте условимся, что мы собираем метрики с какого-то удаленного сервера. Принцип работы остается неизменным. Данному сервису мы примонтируем каталоги */proc* и */sys* для сбора информации о процессах и оборудовании. А в аргументах запуска (*command*) скажем за какими каталогами начать следить нашему экспортеру. Грубо говоря - любое изменение нашего сервера с точки зрения загрузки файловой системы, процессора и т.п будет собираться.
Структура **prometheus.yml** файла:
```
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'node_exporter'
scrape_interval: 15s
static_configs:
- targets: ['node-exporter:9100']
```
*global - глобальные настройки*:
* scrape_interval - раз в какое время выполняется HTTP-запрос к цели. В ответ получаются метрики в своём формате, которые сохраняются в базу(Prometheus)
* evaluation_interval - раз в какое время должны отрабатывать правила, на основании которых отправляются, например, алерты или записываются данные в базу.
*scrape_configs - настройки поиска целей для мониторинга*:
* job_name - имя нашего сервиса. В данном случае это 'node_exporter'. Название можно поставить любое
* scrape_interval - как часто собирать данные. Данную директиву можно опустить, так как она совпадает с тем, что прописано в *global*. Однако оставим тут для наглядности, что это можно настраивать отдельно для каждого сервиса.
* static_configs - указание на то где находятся наши "цели". В нашем конфиге указано *node-exporter:9100*. То есть мы ссылаемся на наш "абстрактный сервер". В реальной жизни это был бы IP-адрес или хостнейм сервера, фактически мы тут и указали его, все же мы помним как работают DNS-имена в докере :)
Что у нас должно получиться:
* Node-exporter собирает данные с сервера и отображает их на порту :9100 по контексту */metrics*
* Prometheus раз в 15 секунд ходит за этими параметрами и записывает их к себе в базу
* Grafana отрисовывает то, что собрал Prometheus
Запустите наш docker-compose файл и почините все ошибки которые у вас могли возникнуть.
Теперь по вашему локальному адресу вы сможете увидеть:
* порт 9090 - интерфейс Prometheus
* порт 9100/metrics - метрики с вашего сервера в реальном времени
* порт 3000 - интерфейс Grafana
**Если вы все настроили правильно, то в интерфейсе Prometheus в разделе *Status -> Targets* мы увидим наш сервер в качестве *endpoint*.**
**Интерфейс Prometheus достаточно интуитивен. Постарайтесь разобраться как можно вывести любые метрики в виде графа и приложите к отчету**
Все бы ничего, но комьюнити решило, что одного интерфейса Prometheus недостаточно и нужно создать инструмент, который будет "красиво" рисовать различные типы графиков и диаграмм, а также сможет агрегировать и визуализировать в себе данные с различных источников. Этим инструментом стала Grafana.
**Зайдите на порт :3100 и пройдите стандартную процедуру аутентификации. Login/pass: admin:admin**
Сейчас наша Grafana пустая. Для того, чтобы визуализировать данные, которые собирает Prometheus нужно нажать:
***Settings* -> Data Sources -> Add Data Source**
Как мы видим, Grafana из коробки предлагает нам большой выбор источников данных. В данной работе нам нужен Prometheus.
**Заполните следующие поля:**
* URL
Самое время создать наш первый Dashboard - место, в котором будут находиться красивые графики, посвященные нашему сервису(в данном случае - метрикам сервера). Можно рисовать графики самому, однако многие стандартные вещи за нас создало комьюнити. Поэтому предлагаю вам пройти по ссылке: https://grafana.com/grafana/dashboards/1860-node-exporter-full/ и скопировать ID дэшборда.
**Теперь в Grafana нужно нажать *Dashboards -> Import* вставить наш скопированный ID и выбрать источником данных наш настроенный Prometheus.**
*Если все пройдет по маслу, то вы увидите исчерпывающий на предмет информации Dashboard за определенные промежутки времени.
В целом, минимальный мониторинг можно считать готовым.*
## Практика. Часть 2
Подняв нашу минимальную систему мониторинга мы смогли визуализировать то, что происходит на нашем сервере с точки зрения потребления ресурсов. Однако, не будем же мы нанимать человека, который будет 24/7 сидеть и смотреть в наши дэшборды на предмет утечки памяти или излишнего потребления CPU.
Для этого существуют **автоматизированные алерты**
**Алертом можно назвать действие, которое происходит в ответ на определенное событие.**
Предлагаю настроить алерты с помощью системы Prometheus Alert Manager.
В вопросах куда отправлять алерты - дело вкуса, однако с недавнего времени Prometheus официально представил плагин для интеграции с Telegram ботами, что не может не радовать.
Дополним наш docker-compose.yml сервисом **Alertmanager**:
```
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
volumes:
- ./alertmanager.yml:/etc/alertmanager/config.yml
command:
- '--config.file=/etc/alertmanager/config.yml'
- '--storage.path=/alertmanager'
restart: unless-stopped
ports:
- 9093:9093
```
Создадим файлик для настройки подключения к боту **alertmanager.yml**:
```
route:
receiver: 'bogdan'
receivers:
- name: 'bogdan'
telegram_configs:
- send_resolved: true
api_url: https://api.telegram.org
bot_token: ${BOT_TOKEN}
chat_id: ${CHAT_ID}
parse_mode: HTML
http_config:
follow_redirects: true
enable_http2: false
```
Моего бота зовут Богдан, он будет сообщать мне о всех трудностях моего сервера. Думаю составить своего бота в телеграм и чат в который будут приходить алерты у вас не составит трудности:)
*Навсякий случай гайд для получения ID чата [chat id](https://stackoverflow.com/questions/32423837/telegram-bot-how-to-get-a-group-chat-id)*
**Настроив соединение с Telegram-ботом мы забыли о самом главном - настройке правил для отправки этих самых алертов!**
Создайте файлик **alert.rules** и поместите его через volume в директорию /etc/prometheus для контейнера с Prometheus.
Пример готового файла, я о вас позаботился: [alert.rules](https://github.com/nocturnalq/vsfi2022/blob/master/roles/webservices/files/prometheus/alert.rules)
Дополните ваш **prometheus.yml**:
```
rule_files:
- "alert.rules"
alerting:
alertmanagers:
- scheme: http
static_configs:
- targets: ['alertmanager:9093']
```
В данном дополнении мы указали Prometheus по каким правилам ему следует отправлять алерты в **Alertmanager** расположенному на порту 9093, который далее перенаправит их в наш Telegram-чат.
**Запустите ваш обновленный docker-compose(кстати, у Alert Manager тоже есть UI). Теперь, предлагаю дать какую-то искуственную нагрузку или же поступить сильно проще - положить наш node-exporter, чтобы Prometheus создал алерт о том, что наш сервер недоступен.**