Pull to refresh
886.31
OTUS
Цифровые навыки от ведущих экспертов

Мониторинг приложений с Prometheus

Reading time7 min
Views31K
Original author: Alex Ellis
Добрый вечер!

На этой неделе мы запускаем четвёртый по счёту поток курса «DevOps: практики и инструменты», так что по традиции небольшая интересная статья для вас.

Поехали

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

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

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



Значение Экспортеров

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

Глоссарий:
Встраивание endpoints /metrics в существующее приложение, называется инструментированием (instrumentation). А когда endpoint /metrics является частью автономного процесса — экспортером (Expoter).

NodeExporter

Один из самых популярных экспортеров — NodeExporter. Когда NodeExporter запущен на хосте, он предоставляет детали нагрузки ввода-вывода, памяти, диска и CPU. Его можно запустить как Docker контейнер, но это требует большого количества дополнительных флагов, поэтому рекомендуется запускать его напрямую на хосте, где ведется мониторинг.

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

Prometheus предоставляет собственный набор метрик — что, по сути, dogfooding (использование своих собственных продуктов в целях тестирования). Он уже встроен и обычно включен по умолчанию.

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

Интересные экспортеры, написанные к Саммиту Docker в Берлине — экспортеры Docker Hub и GitHub Эдварда Маршала (Edward Marshall). Эти экспортеры собирают метрики сайтов Docker Hub и GitHub путем периодического запроса API и передачи этих значений.

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


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

Мой Bitcoin экспортер написан на Node.js и использует метрики типов Гистограмма и Радиальный датчик.


Прочие экспортеры выделены в документации. Например, MySQL, Mongo, Redis, NATS, Nginx и JenkinsCI.

Создание своего экспортера

И тут все становится намного интересней — мониторить можно почти все что угодно. Представим, что у нас есть магазин в Shopify (то есть: карманный онлайн-магазин), в котором мы следим за продажами и статусами заказов.

Вот несколько идей для метрик, за которыми можно следить:

  • самый продаваемый продукт;
  • самая продаваемая категория;
  • общее количество заказов за определенное время;
  • время ожидания между оплатой и отправкой заказа;
  • общее колличество отзывов;
  • средняя оценка в отзывах;
  • общее количество регистраций.

А если этот вид данных уже окажется доступным, можно просто следить за более низкоуровневыми метриками:

  • количество обработанных транзакций;
  • время отклика платежного шлюза;
  • ошибки HTTP, например 403 и 404;
  • геолокация покупателей с помощью IP адресов.

Посмотрим на простой Prometheus рецепт c Docker, а затем вернемся к написанию собственной инструментации для тестового приложения.

Prometheus с 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 routine — облегченная версия потока, которая используется в Golang для обеспечения конкурентности.

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

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

Посмотрим на инструментирование вашего приложения.

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

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

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

В чем заключается другой вариант?

Можно написать отдельный процесс, который выступает в качестве прослойки для получения доступа к информации из вашего приложения или окружения. В случае с экспортером Docker Hub, происходило считывание данных из внешнего API, управлять которым было невозможно. Поэтому, если вам трудно получить разрешение на изменение существующего приложения, этот способ может сработать.

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

Имплементация endpoint’а

Prometheus может считывать данные из двух форматов “экспозиции”. Зайдем на localhost:9090/metrics и посмотрим на результат предыдущего примера go_routines.

# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 92

Используйте клиентскую библиотеку

Существует множество библиотек для работы с метриками, и большинство из них может выводить текст и более эффективный бинарный формат (Protobuf), упомянутый выше.
Форматы экспозиции Prometheus

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

С полным списком можно ознакомиться здесь:

Библиотеки Prometheus

Стоит ли писать собственную?

Формат plaintext настолько прост, что можно с легкостью встроить протокол, следуя форматам экспозиции Prometheus.

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

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

Создадим простое приложение и инструментируем его напрямую с помощью библиотеки Golang Prometheus.

Пример использования:

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

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

К счастью, можно получить все вышеописанное, используя метрику гистограмма, но самым простым примером будет счетчик (всегда повышается или остается прежним) радиального датчика (аналогичен счетчику, но может как повышаться, так и понижаться).

Ознакомиться можно на Metric Types

Полный код, включая 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())
}

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

После этого записывать потраченное время можно с помощью вызова 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
Cледующее отобразится, если написать 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_config добавим следующее:

- 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, но повезло, что Джулиус написал очень детальную статью, доступную здесь.

  • Ответ на вопрос: Сколько получаем запросов для хэшей;

Выражение PromQl, написанное ниже, дает скорость возрастания для нашей хэш-функции в рамках 1 минуты. Рамки можно уменьшить, но они должны покрывать хотя бы два образца.

rate(hash_seconds_count[1m])

  • Ответ на вопрос: Сколько в среднем требуется времени для расчета хэша;

Чтобы узнать среднее значение за последние 5 минут, напишите:

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

  • Ответ на вопрос: Сколько ошибок 400 (bad request) мы получаем.

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

Завершение

  • Это работает на ARM процессоре или Raspberry Pi?

Да, у меня есть образ Docker (alexellis2/prometheus-armhf:1.5.2), доступный в Docker Hub для Prometheus, и проект AlertManager (alexellis2/alertmanager-armhf:0.5.1).

THE END

Как всегда ждём вопросы и комментарии тут или на Дне открытых дверей.
Tags:
Hubs:
Total votes 6: ↑6 and ↓0+6
Comments0

Articles

Information

Website
otus.ru
Registered
Founded
Employees
101–200 employees
Location
Россия
Representative
OTUS