# Задания ## 1. Prometheus 1. Обновите приложение `todo_app` из задания 08 сделав `git pull` ветки `main`. API-сервис приложения теперь отдает метрики Prometheus на порту `9123`(можно поменять через переменную среды `Metrics__Port`) и по url `/metrics`. Таким образом, полное URL для получения метрик, выглядит, например, как `http://todo_api:9123/metrics`. Дополните Compose-файл для `todo_app` так, чтобы в сети `todo` запускался контейнер из образа `prom/prometheus`, при этом: - Напишите для него конфигурацию, то есть файл `prometheus.yml` \ (который должен в итоге находится в контейнере на месте `/etc/prometheus/prometheus.yml`), \ таким образом чтобы Prometheus собирал метрики из `todo_api` каждые 5 секунд. - Прокиньте порт `9090`, на котором находится веб-интерфейс Prometheus по умолчанию, на хост машины с Docker. - Создайте том данных `todo_prometheus_data`, который бы хранил данные внутренней БД Prometheus, и который бы\ монтировался на директорию `/prometheus` внутри его контейнера. Убедитесь, что веб-интерфейс Prometheus не был доступен извне. Для доступа к нему, сделайте SSH-туннель на вашу локальную машину. 2. Запустите систему в Compose-режиме, то есть не в режиме кластера, и без дополнительных реплик. 3. На веб-интерфейсе Prometheus, проверьте, что он собирает метрики из `todo_api`(на вкладке `Targets`) 4. На веб-интерфейсе Prometheus, выведите значение метрики `dotnet_total_memory_bytes` - общее число байт, находящихся в управляемой(т.е. подотчетной сборщику мусора .NET) памяти API-сервиса. 5. Выведите максимальное значение этой метрики за последние 15 минут. 6. Дополните compose-файл так, чтобы в сети `todo` запустить контейнер из образа `bitnami/postgres-exporter`, при этом: - Установите для этого контейнера переменную среды `DATA_SOURCE_NAME`\ в значение `postgresql://todo:todo@todo_postgres:5432/todo?sslmode=disable`(при необходимости поменяйте здесь порт, хост, итд.) - Отредактируйте конфигурацию `prometheus.yml` так, чтобы теперь также собирать метрики из `postgres-exporter`. \ Postgres Exporter по умолчанию отдает метрики на порту `9187`, и по URL `/metrics` 7. Проверьте на веб-интерфейсе Prometheus метрику `pg_stat_user_tables_size_bytes` (она показывает количество памяти, занимаемой пользовательскими таблицами в PostgreSQL) 8. Дополните compose-файл так, чтобы также запускать контейнер из образа `prom/node-exporter`.\ Учтите, что так как этот exporter используется для мониторинга хост-машин, ему не нужна такая изоляция, как обычным приложениям, и даже наоборот: - Для этого контейнера необходимо примонтировать корневую директорию хост-машины в read-only режиме, \ чтобы она была доступна например как директория `/host` внутри контейнера. - При старте этого контейнера, передайте ему аргумент `--path.rootfs=/host` - Также, установите значение `--pid` в `host` (`pid: host` в compose-файле) - Желательно также установить режим сети в `host` (`network_mode: host` в compose-файле) (N.B.: Работает только на Linux, и не работает на Docker Desktop на macOS и Windows) node-exporter по умолчанию отдает метрики на порту `9100` и по URL `/metrics`. \ Доступ к `host`-машине Docker изнутри контейнера Prometheus можно получить по адресу (`host.docker.internal`) Дополните конфигурацию `prometheus.yml` так чтобы собирать метрики и из `node-exporter` 9. Проверьте на веб-интерфейсе Prometheus метрику `node_memory_MemFree_bytes` - она показывает количество свободной оперативной памяти хост-машины(и берет ее из `/proc/meminfo`). ### 1.1 PromQL 1. При выборке данных в PromQL, значение метрик можно фильтровать по меткам. Например, `process_cpu_seconds_total{job="todo_api"}` - здесь метрики будут отфильтрованы по имени службы(job), \ указанной в конфигурации Prometheus. На веб-интерфейсе Prometheus, выведите сначала все временные ряды, связаннные с этой метрикой, а потом только для API-сервиса. 2. Записывая метрику в запросе как `process_cpu_seconds_total` - мы получаем так называемый `instant vector`. Это значение временного ряда(или рядов) за все время. Если же мы запишем метрику как `process_cpu_seconds_total[5m]` - мы получим `range vector`, то есть значения за определенный период времени.\ Значения по диапазону нельзя напрямую вывести на экран того же веб-интерфейса Prometheus, но можно применить к нему какую-либо функцию. Одна из наиболее часто используемых функций, особенно с метриками типа `Counter` - это функция `rate`.\ Она выводит среднее посекундное изменение значения какой-либо метрики, за определенное время, и получает на вход как раз `range vector`.\ Пример необходиомости ее использования: метрика `process_cpu_seconds_total`, которая сама по себе, говорит нам не очень о многом, \ это всего лишь счетчик секунд процессорного времени, занимаемого процессом; зато вот скорость изменения этой метрики \ за какое-то время - может нам показать нагрузку сервисов за это время. Выведите на веб-интерфейс Prometheus степень изменения метрики `process_cpu_seconds_total` за последние 5 минут. 2. Метрики типа `Gauge` - самые простые метрики, они показывают текущее значение какого-либо параметра. `node_memory_MemFree_bytes` - как раз метрика такого типа, показывает свободную память в операционной системе. \ Если взять от нее значения по диапазону(`range vector`), то к ним можно применить какие-либо функции PromQL, работающие с диапазонами. Используя функцию `avg_over_time` - выведите среднее значение этой метрики за последние 5 минут. 3. API-сервис отдает метрику `http_request_duration_seconds`. Она собирает время обработки HTTP-запроса API-сервисом в секундах. `http_request_duration_seconds_bucket` - значения метрики в виде гистограммы. \ `http_request_duration_seconds_sum` и `http_request_duration_seconds_count` - части этой метрики, отдающие, соответственно сумму времени всех запросов, и общее количество запросов. Эти части - сами по себе метрики типа `Counter`. Выведите среднее время обработки запроса за все время(подсказка: сумма времени деленное на количество запросов), так и за последние 5 минут(подсказка: примените функцию rate к диапазону значений за 5 минут). 4. Как видно, на веб-интерфейс Prometheus выводится несколько значений, сгруппированные по меткам, отображающим в частности URL метода API-сервиса. Для того чтобы слить все эти значения в одно, вы можете применить к нему функции аггрегации из PromQL, такие как `sum()`. Функции аггрегации чем-то напоминают аггрегацию по `group by` из SQL, и к ним тоже можно добавлять суффикс `by`. Так, например, можно сгруппировать значения `http_request_duration_seconds_sum` или `_count` по имени метода API-сервиса, обрабатывающего запрос(метка `action`). Выведите среднее время обработки запроса за последние 5 минут, которое бы включало все метки без исключения. 5. `http_request_duration_seconds_bucket` - непосредственно значения гистограммы времени HTTP-запросов, сгруппированное по диапазонам отражающим количество секунд, которое заняла обработка конкретного запроса. Так как значения гистограммы - это счетчики, то к ним также можно применять функции `rate` и `sum`.\ Если мы аггрегируем эту метрику с помощью суммы по метке `le`(собственно значения той оси гистограммы, которые показывают время обработки запроса), \ то к полученному результату мы можем применить функции PromQL, работающие с гистограммами, например `histogram_quantile`. Функцию `histogram_quantile` поможет посчитать время обработки запроса по заданному квантилю. Так, если первым параметром ей передать число 0.5,\ то мы можем оценить примерное медианное время обработки запроса(половина запросов отрабатывает быстрее, половина медленнее). Выведите медианное время обработки запроса за последние 5 минут. ## 2. Grafana 1. Дополните compose-файл так, чтобы в сети `todo` запустить контейнер из образа `grafana/grafana`. \ - Интерфейс grafana по умолчанию доступен на порту 3000, пробростье этот порт на хост машину. - Также, создайте том данных `todo_grafana_data`, примонтированный в контейнер по пути `/var/lib/grafana` - Установите для контейнера переменную окружения `GF_USERS_ALLOW_SIGN_UP` в значение `false`, чтобы отключить возможность регистрации пользователей. 2. Перезапустите систему. Убедитесь что `grafana` доступна извне. Для этого настройте конфигурацию `nginx` на хост-системе, если вы используете его в качестве внешнего прокси. 3. Зайдите на веб-интерфейс grafana. Логин и пароль по умолчанию - `admin` `admin`(пароль можно поменять установив переменную окружения `GF_SECURITY_ADMIN_PASSWORD`). \ Поменяйте пароль на свой, если вы не установили его как переменную среды. 4. Добавьте пользователя с именем `viewer`, и разрешением на просмотр визуализаций(роль `Viewer`). 5. Добавьте источник данных `Prometheus`, при этом установите его URL в `http://todo_prometheus:9090` (поменяйте хост на имя контейнера, в котором запускается Prometheus) 6. Создайте новый Dashboard, и добавьте на него новую визуализацию метрики `dotnet_total_memory_bytes`. - Выберите тип графика как `Time Series` - Назовите график с визуализацией `.NET Total Memory Bytes` - Поставьте единицу измерения `bytes(SI)` - Установите display name для выводимого поля, например в `.NET memory` - Сделайте так, чтобы на график выводилось значение за последние 5 минут. - Добавьте вывод порогового значения(`threshold`) в 10 мегабайт, так чтобы график выше этого значения был закрашен желтым. 7. Сохраните Dashboard под именем `My Dashboard`. Установите график обновления в 5 секунд. 8. Добавьте визуализацию свободной памяти на хост-машине. Сделайте так чтобы визуализация показывала минимальное за последние 5 минут значение, \ а сам график выводил показывал отрезок времени в последний час. Сохраните визуализацию и Dashboard. 9. Добавьте визуализацию среднего времени обработки HTTP-запросов API-сервером за последние 5 минут. Сохраните Dashboard. 10. Перезапустите всю систему, но уже не в Docker Compose, а в Docker Swarm. Сделайте так, чтобы API-сервис работал на трех репликах. Убедитесь, что Prometheus правильно собирает метрики со всех трех реплик одновременно(в Targets на интерфейсе Prometheus должны присутствовать все три). Отредактируйте визуализации, связанные с API-сервисом так, чтобы они показывали средние значения по всем трем репликам.