###### 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 создал алерт о том, что наш сервер недоступен.**