Мониторинг приложений с помощью Prometheus

В этой статье мы расскажем, как интегрировать мониторинг Prometheus в существующее приложение. Мониторинг приложения даст вам представление о том, как и когда оно используется. Также вы сможете увидеть и предотвратить потенциальные проблемы.

Ключевые моменты:

  • Изучение методов мониторинга приложений и серверов с помощью Prometheus.
  • Запуск Prometheus в Docker.
  • Мониторинг и применение образца приложения на Golang.
  • Развертывание Prometheus с помощью Docker.
  • Получение примеров быстрого запуска с PromQL.

Prometheus — ведущая база данных временных рядов и решение для мониторинга.
На снимке сверху — 
Julius Volz, соучредитель на Docker Berlin Summit.

Ищете примеры кода для быстрого старта? Жмите Star или Fork на Github:

Роль экспортеров

Prometheus — база данных временных рядов с пользовательским интерфейсом и сложным языком запросов (PromQL). Prometheus может очищать метрики, счетчики, датчики и гистограммы через HTTP с использованием простого текста или более эффективного протокола.

Глоссарий:

Конечная точка /metrics, внедряемая в существующее приложение, называется контрольно-измерительным прибором. Когда конечная точка /metrics — отдельный проект, он называется «Экспортер».

NodeExporter

Одним из наиболее широко используемых экспортеров является NodeExporter. Когда NodeExporter запущен на хосте, он предоставляет подробную информацию о нагрузках ввода / вывода, памяти, диска и ЦП. Вы можете запустить NodeExporter в контейнере Docker, но для этого требуется множество дополнительных флагов, которые проект рекомендует запускать на контролируемом хосте.

Встроенный экспортер

Prometheus предоставляет собственный набор показателей. Он интегрирован и обычно настроен на сбор по умолчанию.

Поддерживаемые сообществом экспортеры

Интересные экспортеры, которые были представлены на Docker’s Berlin summit, — Docker Hub и Github Edward Marshall. Эти экспортеры предоставляют метрики с сайтов Docker Hub или Github, периодически запрашивая API, а затем передавая значения.

Эд использовал клиентскую библиотеку Python, чтобы собрать экспортер, но доступны и другие привязки к языку.

Один из первых экспортеров Prometheus, который я написал, должен был мониторить статистику биткоинов: сколько долларов я заработал и сколько решений (хэшей) за секунду обрабатывает оборудование.

Биткоин-экспортер написан на Node.js и использует Gauge и показатели Histogram.

Построение собственного экспортера

В построении собственного экспортера можно контролировать практически все. Представьте, что вы запустили магазин Shopify (think: webstore-in-a-box) и отслеживаете статус продаж и заказов.

В панель инструментов можно включить параметры:

  • Наиболее продаваемый продукт.
  • Наиболее продаваемая категория.
  • Общее число заказов.
  • Время реагирования.
  • Общее число отзывов.
  • Средний рейтинг по отзывам.
  • Количество подписок.

Также можно отслеживать следующие показатели:

  • Обработанные транзакции.
  • Время отклика платежного шлюза.
  • Ошибки HTTP, такие как 403 и 404.
  • Географическое расположение клиентов по IP-адресу.

Для начала рассмотрим простой вариант работы Prometheus с Docker, а затем вернемся к написанию инструментария для примера приложения.

Работа Prometheus c Docker

Prometheus написан на Golang и может использоваться как один статически скомпилированный двоичный файл. Проект упаковывает двоичный файл с разумной конфигурацией в контейнер Docker.

Запускаем Prometheus в Docker

Определяем Docker Compose, благодаря которому командные строки будут простыми и повторяемыми:

«`version: “3”
services:
prometheus:
image: quay.io/prometheus/prometheus:latest
ports:

  • 9090:9090
  • Разверните файл стека:

Для развертывания файлов стека требуется режим Swarm, поэтому запустите docker swarm init.

$ docker swarm init
$ docker stack deploy monitoring --compose-file=./docker-compose.yml

Переходите на: http://localhost:9090/ для просмотра пользовательского интерфейса.

На скриншоте выше вы видите количество используемых go_routines, записанных Prometheus. Чтобы увидеть исходные показатели Prometheus, откройте браузер и перейдите на http://localhost:9090/metrics

Go_routines – легкая версия потока, используемая в Golang для обеспечения параллелизма.

Возможно, вы не захотите контролировать Prometheus, но тот факт, что батарейки включены, означает, что вы имеете представление о показателях.

Инструментирование приложения

Существуют два подхода к инструментированию, которые подразумевают, что вы открываете конечную точку HTTP/s. По умолчанию конечная точка — /metrics, но может быть настроена в файле prometheus.yml. Prometheus будет использовать эту конечную точку для очистки показателей с регулярными интервалами, например, каждые 5 или 30 секунд.

Нужно ли изменять код приложения?

Вы можете сделать конечную точку /metrics частью кода в существующем приложении. Это означает, что у вас уже есть необходимые секреты и учетные данные для взаимодействия с бизнесом / платежами или уровнями базы данных. Недостатком является то, что вам нужно включить новую библиотеку, конечную точку и зависимость в свой продукт или проект.

Есть ли другой вариант?

Также возможно писать раздельные процессы, которые действуют как оболочка для предоставления информации из вашего приложения или среды. Ed’s Docker Hub — экспортер располагает данными из внешнего API, которые он не контролирует. Такой вариант пригодится, если нельзя получить разрешение на изменение существующего приложения.

Преимущество отдельного процесса заключается в том, что вы можете обновлять то, что контролируете, не переустанавливая свои
приложения.

Имплементация конечной точки:

Есть два формата «изложения». Давайте посмотрим на результат предыдущего примера go_routines, посетив http://localhost:9090/metrics.

«`# HELP go_goroutines Number of goroutines that currently exist.

TYPE go_goroutines gauge

go_goroutines 92 «`

Использование клиентской библиотеки

Доступно несколько библиотек для экспонирования показателей, большинство из которых могут выводить текст или более эффективный двоичный формат (Protobuf), упомянутый выше.

Форматы экспозиции Prometheus

Привязки к языку Golang, Java, Python и Ruby поддерживаются проектом, но также доступно множество других привязок с открытым исходным кодом. Полный список можно найти здесь:

Библиотеки Prometheus

Стоит ли составлять собственный протокол?

Формат текста настолько прост, что вы можете легко реализовать протокол, следуя форматам изложения Prometheus. Перед тем как составлять протокол, убедитесь, что действительно не сможете воспользоваться проверенными клиентскими библиотеками.

Инструментирование приложения Golang

Давайте создадим простое приложение и применим его к библиотеке Golang Prometheus.

Вариант использования:

Нам было предложено написать веб-сервис для предоставления хэшей SHA-256 по требованию. Для этого нам нужно знать:

  • сколько запросов мы получаем для хэшей;
  • сколько в среднем времени занимает вычисление каждого хэша;
  • сколько ошибок 400 (неудачных запросов) мы получаем.

К счастью, мы можем это узнать, используя метрику гистограммы. Но самым простым способом является счетчик датчика. Счетчик всегда остается неизменным, в то время как датчик может идти вверх или вниз.

Читайте о типах метрик

Полный код, содержащий Dockerfile, доступен на Github: alexellis/hash-browns

Пример файла server.go:

«`func main() {
histogram := prometheus.NewHistogramVec(prometheus.HistogramOpts{
Name: “hash_duration_seconds”,
Help: “Time taken to create hashes”,
}, []string{“code”})

r := mux.NewRouter()
r.Handle("/metrics", prometheusHandler())
r.Handle("/hash", hashHandler(histogram))
prometheus.Register(histogram)
s := &http.Server{
    Addr:           ":8080",
    ReadTimeout:    8 * time.Second,
    WriteTimeout:   8 * time.Second,
    MaxHeaderBytes: 1 << 20,
    Handler:        r,
}
log.Fatal(s.ListenAndServe())

}«`

Здесь мы регистрируем маршрут приложения и метрик.

Время записи — случай вызова histogram.Observe(seconds).

start := time.Now()
// Do something
duration := time.Since(start)
code := 200 // some HTTP Code
histogram.WithLabelValues(fmt.Sprintf("%d", code)).Observe(duration.Seconds())

Вы можете создать хэш следующим образом:

$ curl localhost:8080/hash -d "my_input_value_here"
49b8c4256d603a68ee9bcd95f8e11eed784189bd40c354950014b6d7f7263d6c

Это будет отображаться, если мы curl localhost:8080/metrics.

# HELP hash_seconds Time taken to create hashes
# TYPE hash_seconds histogram
hash_seconds_bucket{code="200",le="1"} 2
hash_seconds_bucket{code="200",le="2.5"} 2
hash_seconds_bucket{code="200",le="5"} 2
hash_seconds_bucket{code="200",le="10"} 2
hash_seconds_bucket{code="200",le="+Inf"} 2
hash_seconds_sum{code="200"} 9.370800000000002e-05
hash_seconds_count{code="200"} 2

Последний шаг. Отредактируйте файл prometheus.yml и начните очищать новый код приложения. Затем найдите метрику в раскрывающемся списке и отобразите значения.

Собирая все воедино

Нам нужно отредактировать конфигурацию Prometheus. Вот трюк, чтобы извлечь конфигурацию по умолчанию из официального образа Docker:

$ docker run --entrypoint='' -ti quay.io/prometheus/prometheus:latest /bin/cat /etc/prometheus/prometheus.yml > prometheus.yml

Теперь отредактируйте файл prometheus.yml, созданный в вашем текущем каталоге. В разделе scrape_configs добавьте следующее:

«` — job_name: ‘hashbrowns’

# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
  - targets: ['hashbrowns:8080']```

Docker Swarm позволяет сервисам взаимодействовать друг с другом через встроенный DNS, поэтому цель — метка («hashbrowns») из файла компоновки.

Теперь создайте новый файл docker-compose.yml:

«`version: “3”
services:
prometheus:
image: quay.io/prometheus/prometheus:latest
ports:

  • 9090:9090
    volumes:
  • “./prometheus.yml:/etc/prometheus/prometheus.yml”
  • hashbrowns:
    image: alexellis2/hash-browns
    ports:
  • 8080:8080«`

Разверните файл стека:

$ docker stack deploy tutorial --compose-file=./docker-compose.yml

Примечание. Адресация службы по имени будет функционировать хорошо, пока у вас есть только одна реплика. Если вы решите масштабировать услугу, нужно будет изучить способность Prometheus обнаруживать все реплики отдельно с большей точностью.

Вот как это будет выглядеть в интерфейсе Prometheus:

Теперь мы дадим ответы в формате [PromQL] для показателей, которые хотели собрать выше. Мне потребовалось некоторое время, чтобы привыкнуть к PromQL, но, к счастью, Julius написал очень подробную статью, доступную здесь.

  • Вопрос: Сколько запросов мы получаем для хэшей

Следующий оператор PromQL дает скорость увеличения для нашей хэш-функции в течение 1-минутного окна. Это окно может быть меньше, но оно должно охватывать как минимум два образца.

rate(hash_seconds_count[1m])

  • Вопрос: Cколько в среднем времени занимает вычисление каждого хэша

Для среднего выполнения за последние 5 минут введите:

rate(hash_seconds_sum[5m]) / rate(hash_seconds_count[5m])

  • Вопрос: Покажите, сколько ошибок 400 мы получили за последние 5 минут

rate(hash_seconds_count{code="400"}[5m])