m2/10/tasks

pull/5/head
Dmitry Ignatiev 12 months ago
parent 4be6ec03ef
commit 75fcea1371

@ -1,3 +1,4 @@
Dockerfile Dockerfile
docker-compose.yml docker-compose.yml
nginx.conf nginx.conf
prometheus.yml

@ -0,0 +1,12 @@
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace TodoApi.Helpers
{
public class TodoHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = new CancellationToken())
{
return Task.FromResult(new HealthCheckResult(HealthStatus.Healthy));
}
}
}

@ -1,6 +1,8 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Prometheus;
using TodoApi.Helpers;
using TodoApi.Model; using TodoApi.Model;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -27,6 +29,15 @@ builder.Services.AddControllers()
o.JsonSerializerOptions.Converters.Add(enumConverter); o.JsonSerializerOptions.Converters.Add(enumConverter);
}); });
builder.Services.AddMetricServer(options =>
{
options.Port = config.GetRequiredSection("Metrics").GetValue<ushort>("Port", 9123);
});
builder.Services.AddHealthChecks()
.AddCheck<TodoHealthCheck>(nameof(TodoHealthCheck))
.ForwardToPrometheus();
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@ -35,6 +46,8 @@ app.UseStaticFiles();
app.MapControllers(); app.MapControllers();
app.UseHttpMetrics();
app.MapFallbackToFile("index.html"); app.MapFallbackToFile("index.html");
app.Run(); app.Run();

@ -8,6 +8,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.11" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.11" />
<PackageReference Include="prometheus-net" Version="8.1.0" />
<PackageReference Include="prometheus-net.AspNetCore" Version="8.1.0" />
<PackageReference Include="prometheus-net.AspNetCore.HealthChecks" Version="8.1.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -8,5 +8,8 @@
"ConnectionStrings": { "ConnectionStrings": {
"PostgreSQL": "Host=localhost;Port=5432;Database=todo;Username=todo;Password=todo" "PostgreSQL": "Host=localhost;Port=5432;Database=todo;Username=todo;Password=todo"
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
"Metrics": {
"Port": 9123
}
} }

@ -0,0 +1,10 @@
## Ссылки
- https://prometheus.io/docs/prometheus/latest/getting_started/
- https://povilasv.me/prometheus-tracking-request-duration/
- https://www.innoq.com/en/blog/2020/04/scraping-docker-swarm-service-instances-with-prometheus/
- https://github.com/prometheus/node_exporter
- https://prometheus.io/docs/practices/histograms/
- https://grafana.com/docs/
- https://grafana.com/blog/2020/06/23/how-to-visualize-prometheus-histograms-in-grafana/

@ -0,0 +1,91 @@
# Задания
## Prometheus
1. Вы должны были получить обновленное приложение `todo_app`.
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`).
## 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. API-сервис отдает метрику `http_request_duration_seconds`. Она собирает время обработки HTTP-запроса API-сервисом в секундах. \
`http_request_duration_seconds_bucket` - значения метрики в виде гистограммы. \
`http_request_duration_seconds_sum` и `http_request_duration_seconds_count` - части этой метрики, отдающие, соответственно сумму времени всех запросов, и общее количество запросов.
Добавьте визуализацию среднего времени обработки HTTP-запросов API-сервером за последние 5 минут. Сохраните Dashboard.
10. Перезапустите всю систему, но уже не в Docker Compose, а в Docker Swarm. Сделайте так, чтобы API-сервис работал на трех репликах.
Убедитесь, что Prometheus правильно собирает метрики со всех трех реплик одновременно(в Targets на интерфейсе Prometheus должны присутствовать все три).
Отредактируйте визуализации, связанные с API-сервисом так, чтобы они показывали средние значения по всем трем репликам.
Loading…
Cancel
Save