Введение в мониторинг с помощью Prometheus и Grafana
В современном быстро развивающемся мире цифровых технологий поддержание производительности и доступности приложений и инфраструктуры в целом имеет решающее значение. Эффективные системы мониторинга позволяют организациям заблаговременно выявлять и устранять проблемы, обеспечивая бесперебойную работу и оптимальное использование ресурсов. Сегодня на рынке представлены два мощных инструмента, которые стали основными в экосистеме мониторинга, - это Prometheus и Grafana. В этой статье мы поговорим о том, зачем вообще нужен мониторинг систем, а также рассмотрим, как настроить эти два инструмента для NodeJS.
Необходимые условия:
Прежде чем приступить к изучению содержания этого руководства, Вы должны иметь базовое представление о следующем:
- Docker (версия 23.0.1 или новее)
- Dockerfile
- Docker-compose
- NodeJS v21
В чем состоит важность мониторинга
Мониторинг помогает понять, что именно происходит в Вашем приложении. Мониторинг дает нам следующие преимущества:
- Анализ долгосрочных тенденций
Вы можете отслеживать то, как ведет себя Ваше приложение в долгосрочной перспективе. Насколько велика Вашая база данных и как быстро она растет? Как быстро растет число ежедневных активных пользователей и т.д.
- Сравнение по времени или экспериментальным группам
Допустим, Вы выпустили новую функцию для своего приложения. Теперь Вы можете сравнить производительность Вашего приложения до и после развертывания функции. Как работает Ваше приложение, когда Вы добавляете дополнительный узел?
- Оповещения
Если производительность Вашего приложения падает, Вам нужны системы, которые автоматически будут оповещать Вас об этом. Вы можете настроить оповещения, которые будут сообщать Вам, что система вот-вот даст сбой, чтобы Вы вовремя могли принять все необходимые меры.
- Проведение специального ретроспективного анализа
Допустим, производительность Вашей системы упала. Вам нужно знать, что именно произошло в это время.
4 золотых сигнала
4 золотых сигнала мониторинга: задержка, трафик, ошибки и сатурация. Если Вы можете измерить только четыре показателя Вашей системы, ориентированной на пользователя, сосредоточьтесь на именно на них.
Задержка
Время, необходимое для обработки запроса. Важно различать задержку успешных запросов и задержку неудачных запросов.
Трафик
Показатель того, насколько высока нагрузка на Вашу систему. Представляет собой количество HTTP-запросов в секунду, получаемых Вашим веб-приложением.
Ошибки
Это показатель количества запросов, которые потерпели неудачу либо явно (например, HTTP 500), либо неявно (например, успешный ответ HTTP 200, но с неправильным содержимым).
Сатурация
Показатель того, насколько заполнен Ваш сервер. Исходя из производительности Вашей системы, вы должны определить, как справится Ваша система, если трафик удвоится, увеличится на 10 % или уменьшится.
Prometheus: Надежный набор инструментов для мониторинга и оповещений
Prometheus - это набор инструментов для мониторинга и оповещения систем с открытым исходным кодом, предназначенный для обеспечения надежности и масштабируемости систем. Изначально он был разработан в компании SoundCloud в 2012 году. Prometheus отлично справляется со сбором и хранением метрик в виде временных рядов данных. Prometheus использует высокоразмерную модель данных, в которой метрики идентифицируются по имени и набору пар ключ-значение, называемых метками, что позволяет выполнять точные и гибкие запросы. PromQL - это язык, разработанный специально для запросов и агрегирования данных временных рядов.
Компоненты Prometheus
Экосистема Prometheus состоит из множества компонентов, многие из которых являются необязательными:
- Сервер Prometheus который собирает и хранит данные временных рядов;
- Клиентские библиотеки, предназначенные для создания кода приложения;
- Шлюз для выполнения несложных заданий
- Специальные экспортеры, предназначенные для таких сервисов, как HAProxy, StatsD, Graphite и т.д.
- Менеджер оповещений, рассылающий оповещения в случае необходимости
Архитектура Prometheus
Диаграмма, представленная ниже, наглядно иллюстрирует архитектуру Prometheus и некоторые компоненты его экосистемы.
Grafana: вся мощь визуализации данных
Grafana - это платформа с открытым исходным кодом, предназначенная для мониторинга и наблюдения за производительностью систем, которая отлично справляется с визуализацией данных временных рядов. Она предоставляет своим пользователям богатый набор функций для создания, изучения и обмена дашбордами, что делает ее идеальным дополнением к Prometheus. Grafana можно запустить через облако Grafana или разместить ее у себя локально.
Ключевые характеристики Grafana
- Гибкое составление дашбордов: Grafana предлагает своим пользователям широкий спектр возможностей визуализации данных, включая графики, тепловые карты, таблицы и многое другое.
- Интеграция с несколькими источниками данных: Grafana может интегрироваться с множеством источников данных, включая Prometheus, Elasticsearch, InfluxDB и многие другие, что позволяет осуществлять комплексный мониторинг различных систем.
- Оповещения и уведомления: Встроенные функции оповещения позволяют создавать сложные правила оповещения с поддержкой нескольких каналов оповещения, таких как электронная почта, Slack и PagerDuty.
- Шаблоны и переменные: Grafana поддерживает шаблоны и переменные, которые позволяют пользователям создавать динамические и многократно используемые дашборды.
- Сообщество и плагины: Активное сообщество и обширная экосистема плагинов расширяют функциональность Grafana, предлагая дополнительные типы визуализации, интеграции с источниками данных и специфические плагины для приложений.
Как настроить Prometheus и Grafana
Вы можете использовать весь исходный код, размещенный в этом репозитории. Здесь Вы найдете файл docker-compose со всеми необходимыми сервисами, которые являются частью одной сети под названием sample-net. Мы научимся настраивать Prometheus и Grafana, устанавливая мониторинг для простого NodeJS-приложения. Следует также отметить, что Prometheus сам по себе не может собирать метрики. Для сбора и отображения соответствующих метрик через конечные точки HTTP ему нужны другие сервисы. Prometheus будет использовать данные, которые эти сервисы предоставляют. Конечная точка API обычно представляет собой GET и POST API с «/metrics» в качестве пути.
Ниже приведен список сервисов, которые мы используем:
- У нас есть простой веб-сервер, построенный на NodeJS. Мы запустим приложение в контейнере Docker.
- Traefik: Для перенаправления запросов к нашему приложению NodeJS мы будем использовать балансировщик нагрузки Traefik. Это нужно для отслеживания HTTP-запросов, поступающих к нашему приложению NodeJS. Мы выставим эти метрики так, чтобы Prometheus мог собирать данные о запросах, поступающих на наш сервер.
- Node Exporter: раскрывает широкий спектр метрик, связанных с аппаратным обеспечением и ядром
- cAdvisor: (сокращенно от container Advisor) анализирует и предоставляет данные об использовании ресурсов и производительности всех запущенных контейнеров.
- Prometheus: может считывать и хранить метрики, и, наконец,
- Grafana: может читать метрики, полученные Prometheus
Следующая блок-схема представляет собой краткое описание нашей системы:
HTTP-запросы, поступающие в Traefik, будут перенаправляться в наше NodeJS-приложение. Traefik будет выставлять метрики так, чтобы Prometheus мог их «схватить». Node Exporter и cAdvisor также будут отображать метрики. Для визуализации данных, собранных Prometheus, мы будем использовать Grafana.
Приложение NodeJS
Ниже приведен код для приложения NodeJS . Оно имеет 2 API, / маршрут по умолчанию вернет статус 200 с сообщением hello world, а маршрут /error_or_not/:text вернет ошибку 500, если текст, переданный API, является ошибкой, в противном случае он вернет тот же текст с кодом состояния 200. Я добавил эти API для создания метрик для Traefik. Сервер работает на порту 3000 внутри контейнера.
var express = require("express");
var app = express();
app.get("/", function (req, res) {
res.send("Hello world!");
});
app.get("/error_or_not/:text", function (req, res) {
if (req.params.text === "error") {
res.status(500).send(req.params.text);
return;
}
res.status(200).send(req.params.text);
});
app.listen(3000);
Для этого приложения у нас есть простой Docker файл:
FROM node:20
WORKDIR /app COPY package.json .
ARG NODE_ENV RUN if [ "$NODE_ENV" = "development" ]; \ then npm install; \
else npm install --only=production; \
fi COPY . ./
EXPOSE 3000
Для приложения NodeJS в файле docker-compose мы используем файл docker и настраиваем Traefix на отправку запросов на порт 3000 внутри контейнера. Конфигурацию Traefik мы рассмотрим чуть позже.
nodeapp:
networks:
- sample-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.api-redirect.entryPoints=web"
- "traefik.http.routers.api-redirect.rule=PathPrefix(`/`)"
- "traefik.http.services.nodeapp-service.loadBalancer.server.port=3000"
build:
context: .
args:
NODE_ENV: production
volumes:
- ./:/app
- /app/node_modules
command: ["npm", "run", "start"]traefik.http.routers.api-redirect.entryPoints=web
Мы указали, какую точку входа в конфигурации Traefik следует использовать. В Traefik точки входа - это сопоставления портов.
traefik.http.routers.api-redirect.rule=PathPrefix(`/`)
Указывая PathPrefix(`/`) в правиле перенаправления, мы говорим Traefik отправлять все запросы в это приложение.
traefik.http.services.nodeapp-service.loadBalancer.server.port=3000
Мы указываем, на какой порт стоит перенаправлять запрос.
Интеграция Traefik
В этом уроке мы не будем глубоко погружаться в Traefik, я расскажу Вам лишь о самых необходимых аспектах. Конфигурации Traefik могут быть определены как статически, так и динамически. То, что мы видим в файле конфигурации Traefik, является статическим; конфигурация Traefik, которую мы упоминаем под сервисом node (который мы видели выше) в файле docker-compose, является динамической.
Конфигурационный файл Traefik:
providers:
docker:
network: sample-net
exposedbydefault: false
# API configuration
api:
insecure: true
log:
level: DEBUG
entryPoints:
web:
address: :80
websecure:
address: :443
metrics:
address: :8082
metrics:
prometheus:
addRoutersLabels: true
addEntryPointsLabels: true
buckets:
- 0.1
- 0.3
- 1.2
- 5.0
entryPoint: metrics
В разделе «Providers» мы указываем Traefik, драйвер - docker , сеть - sample-net. Как только мы запустим файл compose, движком docker будет создана сеть sample-net. Вы увидите точку входа в сеть, которая привязана к порту 80. Это точка входа, которую мы использовали в приложении NodeJS.
metrics: address: :8082
Итак, мы создали точку входа для отображения метрик.
Теперь мы можем включить метрики в Traefik для Prometheus в разделе метрик. Вы можете ознакомиться со своей необходимой документацией касательно всех доступных опций здесь.
addRoutersLabels: true
Включите метрики на роуторахторах. В конфигурации Traefik у нас есть только один маршрут для нашего NodeJS-приложения.addEntryPointsLabels: true
Включите метрики для точек входа.
buckets:
Мы можем распределить метрики по разным бакетам в зависимости от задержки.
entryPoint: metrics
Мы можем указать порт, через который хотим передавать метрики.
traefik:
image: traefik:v2.10.7
networks:
- sample-net
ports:
- "80:80"
- 8082:8082
volumes:
- ./traefik.yml:/etc/traefik/traefik.yml
- "/var/run/docker.sock:/var/run/docker.sock:ro"
Мы используем файл конфигурации Traefik в сервисе Traefik. Поскольку Traefik должен прослушивать события docker для поиска динамических конфигураций, нам нужно отобразить сокет docker. Мы открыли порт 80 для прослушивания входящих запросов и порт 8082 для метрик Prometheus.
Node Exporter
node-exporter:
image: quay.io/prometheus/node-exporter:latest volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro - /:/host:ro,rslave command:
- "--path.rootfs=/host"
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- --collector.filesystem.ignored-mount-points - "^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)"
networks: - sample-net restart: always
Интеграция для Node Exporter достаточно проста. Мы сопоставляем тома хост-машины с контейнером в режиме только для чтения (:or). Мы настроили необходимые команды для установки корневой файловой системы, из которой node-exporter будет производить скретчинг, и других системных путей, чтобы node-exporter мог получить подробную информацию об аппаратном обеспечении.
cAdvisor:
cadvisor:
image: gcr.io/cadvisor/cadvisor
ports:
- 8080:8080
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- sample-net
Интеграция с cAdvisor также достаточно проста. Мы создаем карту необходимых томов для того, чтобы cAdvisor мог извлекать метрики с хост-машины и движка docker. Он запускается на порту 8080.
Prometheus
Ниже представлена конфигурация для Prometheus:
global:
scrape_interval: 15s
scrape_timeout: 10s
scrape_configs:
- job_name: prometheus
honor_timestamps: true
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- prometheus:9090
- job_name: "node"
static_configs:
- targets: ["node-exporter:9100"]
- job_name: "cadvisor"
scrape_interval: 15s
static_configs:
- targets: ["cadvisor:8080"]
- job_name: 'traefik'
static_configs:
- targets: ['traefik:8082']
Пройдемся по данной конфигурации чуть подробнее:
global: scrape_interval:15s scrape_timeout: 10s
Мы можем задать более глобальные настройки, такие как интервал отбраковки и таймаут отбраковки.
В разделе scrape_configs у нас есть четыре задания:
- Задание Prometheus: Prometheus может собирать данные о себе. Для этого в качестве цели нужно указать prometheus.
- Задание узла: прослушивает порт 9100 в службе node-exporter. Это позволит получить метрики от node-exporter
- Задание cadvisor: Задание cAdvisor будет получать метрики от cAdvisor.
- Задание Traefik: Задание Traefik будет получать метрики от Traefik.
Каждое из этих заданий будет прослушивать цели, настроенные под них. В службе Prometheus мы загружаем файл конфигурации в контейнер. Prometheus будет хранить собранные данные на хост-машине.
prometheus:
image: prom/prometheus
ports:
- 9090:9090
command:
- "--config.file=/etc/prometheus/prometheus.yml"
restart: unless-stopped
networks:
- sample-net
volumes:
- ./prometheus:/etc/prometheus
- prom_data:/prometheus
Grafana
Для Grafana в качестве источника данных по умолчанию мы настроили Prometheus (хотя это и необязательно):
apiVersion: 1 datasources: - name: Prometheus type: prometheus url: http://prometheus:9090 isDefault: true access: proxy editable: true
В сервисе Grafana для установки учетных данных (GF_SECURITY_ADMIN_USER и GF_SECURITY_ADMIN_PASSWORD) мы можем передать переменные окружения:
grafana:
image: grafana/grafana
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=grafana
volumes:
- ./grafana/datasources:/etc/grafana/provisioning/datasources
ports:
- 3000:3000
networks:
- sample-net
Выполните следующую команду в каталоге reference_repo/prometheus_grafana_example для того, чтобы собрать образ для приложения NodeJS. При этом будет использован файл Docker-compose.
docker compose build
Для запуска всех служб выполните следующую команду:
docker compose up -d
Давайте проверим, все ли работает так, как ожидалось. Хотя мы можем использовать Grafana для визуализации метрик, некоторые сервисы (например, cAdvisor, Traefik и Prometheus) имеют свои собственные панели. Но они не будут работать так хорошо, как Grafana. Для доступа к панелям cAdvisor можно использовать следующую ссылку:
http://localhost:8080/containers/
Это должно выглядеть примерно так:
Если Вы видите этот дашборд, это означает, что cAdvisor работает успешно. Вы также можете получить доступ к метрикам, которые выдает cAdvisor, используя следующий URL:
http://localhost:8080/metrics
Аналогичным образом для проверки того, выставляются ли метрики из Traefik или нет, Вы можете использовать следующую ссылку:
http://localhost:8082/metrics
Вы должны увидеть следующий текст:
Доступ к браузеру Prometheus можно получить с помощью следующего URL:
http://localhost:9090/graph
Вы увидите примерно следующее:
Для запроса данных из PrometheusВы можете использовать PromQL. Например, для того, чтобы получить среднее значение сетевого трафика в секунду за последнюю минуту (в байтах) Вы можете выполнить следующий запрос:
rate(node_network_receive_bytes_total[1m])
Вы можете ввести запрос в поле поиска и нажать кнопку «Execute». Переключившись на вкладку «Graph», Вы увидите данные в виде графика:
Создание дашбордов в Grafana
Grafana будет запрашивать данные из Prometheus для того, чтобы показать данные, необходимые для создания дашбордов. Прежде чем мы начнем создавать дашборды в Grafana, пройдите по этим двум ссылками. С их помощью Вы сможте сгенерировать некоторые данные для Traefik:
Сгенерировать запрос 200:
http://localhost/error_or_not/no_error
Сгенерировать запрос 500:
http://localhost/error_or_not/error
Эти ссылки предназначены для веб-сервера Traefik, который будет перенаправлять запрос на приложение NodeJS.
Для доступа к Grafana используйте следующую ссылку:
http://localhost:3000/
Grafana будет выглядеть так:
Для входа в систему используйте учетные данные, которые мы настроили в разделе переменных среды для службы Grafana:
- Имя пользователя: admin
- Пароль: grafana
Проверка источника данных Prometheus
Давайте проверим, виден ли другим пользователям настроенный нами источник данных Prometheus в Grafana. Для этого в главном меню нажмите на источники данных:
В таблице Вы должны увидеть уже настроенный нами Prometheus:
Создание дашборда для Node Exporter
Давайте создадим дашборд в Grafana для node-exporter. Мы можем сами создавать виджеты в Grafana, но для этого Вам нужно будет самостоятельно создавать PromQL-запросы. К счастью, на сайте Grafana доступно множество уже готовых дашбордов с открытым исходным кодом, которые мы можем легко импортировать:
Шаг 1: Нажмите на меню Dashboards.
Шаг 2: Нажмите на вкладку Create dashboard
Шаг 3: Далее нажмите на вкладку Import dashboard.
Шаг 4: Для получения ID панели node-exporter с сайта Grafana используйте эту ссылку . Нажмите на кнопку копирования ID.
Шаг 5: Вернитесь на страницу Import Grafana dashboard и вставьте идентификатор в текстовое поле, нажмите кнопку Load:
Шаг 6: Задайте имя для своего дашборда. В выпадающем списке выберите Prometheus и нажмите на кнопку Import.
Дашборд для node-exporter будет выглядеть следующим образом:
Рис .16
Здесь Вы сможете увидеть такие показатели, как использование процессора и памяти и т. д. Поздравляем, Вы успешно создали дашборд в Grafana!
Для создания дашбордов для cAdvisor и Traefik Вы можете выполнить те же самые шаги.
FAQ:
Нужно ли запускать все эти сервисы в одном файле docker-compose для того, чтобы они работали должным образом?
Нет. Место, где нужно запускать службы, зависит от того, что именно делает служба. Службы node-exporter и cAdvisor должны быть запущены на экземпляре/машине, по которой Вы хотите собрать метрики. Prometheus и Grafana могут быть запущены абсолютно на любом экземпляре. Их не обязательно запускать на том же экземпляре, на котором запущены node-exporter или cAdvisor. Все, о чем Вам нужно позаботиться, - это доступ к инстансу по HTTP и порты, через которые передаются нужные Вам метрики.
Можно ли добавить несколько целей в конфигурацию Prometheus для одного задания?
Да, Вы можете добавить несколько целей для задания, добавив URL-адрес экземпляра к цели.
Существуют ли другие способы запуска этих служб?
Да, установочный файл Grafanа можно загрузить. Для запуска Prometheus и Node Exporter Вы можете использовать бинарные файлы. cAdvisor можно запустить только с помощью docker.
Заключение
В заключение следует отметить, что беспроигрышное сочетание Prometheus и Grafana обеспечивает комплексное решение для мониторинга состояния систем. Используя эти инструменты, Вы сможете добиться прозрачности работы своих приложений, эффективно управлять их производительностью и обеспечить надежность инфраструктуры в целом.



















