Api/metrics мониторинг отсутствие peers в upstream
karabanov opened this issue · 12 comments
Здравствуйте.
Есть один недостаток который мешает корректно мониторить состояние upstream с помощью prometheus, а именно, если перестало резолвиться DNS имя сервера указанного в upstream, то все метрики angie_http_upstreams_peers_*
пропадают из выдачи, при этом в Console Light для такого upstream выводиться сообщение No servers with 'all' state found in this upstream group.
В шаблоне prometheus_all присутствует метрика angie_http_upstreams_peers_state
:
'angie_http_upstreams_peers_state{upstream="$1",peer="$2"}' $p8st_all_ups_state
path=~^/http/upstreams/([^/]+)/peers/([^/]+)/state$
type=gauge
'help=The current state of an upstream peer in "HTTP": 1 - up, 2 - down, 3 - unavailable, 4 - recovering.';
map $p8s_value $p8st_all_ups_state {
volatile;
"up" 1;
"down" 2;
"unavailable" 3;
"recovering" 4;
default 0;
}
Но она тоже пропадает, что странно ведь в map
указано значение по умолчанию.
Я попробовал сделать такой шаблон, чтобы отслеживать эту ситуацию:
'angie_http_upstreams_peers_available{upstream="$1",available="$2"}' $p8st_all_ups_available
path=~^/http/upstreams/([^/]+)/peers(.*)
type=gauge
'help=Availability peers in upstream group.';
map $p8s_value $p8st_all_ups_available {
volatile;
"(null)" 0;
"{}" 0;
default 0;
}
Но ничего не вышло...
Может регулярка в директиве path
должна как-то иначе выглядеть? Или требуется доработка модуля http_prometheus?
Помогите пожалуйста решить проблему с мониторингом наличия серверов в upstream.
Если включен динамический резолвинг, то список серверов обновляется согласно ответу DNS сервера. Если ответ пустой, то все сервера удаляются из upstream
. Метрики привязаны к конкретным серверам, а те в свою очередь запрашиваются из DNS. Нет серверов, нет и метрик по ним.
У вас получается, что объект /http/upstreams/([^/]+)/peers
пуст и не срабатывает матчинг - там нет метрик, которые бы имели значение, сохраняемое в $p8s_value
. Пустые списки и объекты пропускаются, так что встроенными средствами модуля такую метрику сейчас получить не получится.
Если включен динамический резолвинг, то список серверов обновляется согласно ответу DNS сервера. Если ответ пустой, то все сервера удаляются из
upstream
. Метрики привязаны к конкретным серверам, а те в свою очередь запрашиваются из DNS. Нет серверов, нет и метрик по ним.
@VBart, а можете добавить метрику для случая, когда в upstream нет серверов, чтобы эту ситуацию было видно не только в Console Light, но и в Prometheus метриках? Полагаю достаточно сделать так, чтобы в случае отсутствия серверов API возвращало не пустой объект, а что-то, что можно матчить.
Было бы очень удобно получать алерт от Promrtheus, когда такое происходит - у нас это довольно частая ситуация, так как речь идёт о так называемой Keepalive Proxy, которая позволяет приложению не умеющему самостоятельно работать с keepalive соединениями (приложение на PHP), всё таки с ними работать.
Сейчас у нас Keepalive Proxy реализована на базе Nginx и bash скрипта, который присылает алерт в Slack если DNS имя перестало резолвиться, убирает из конфига неработающий upstream
и выполняет reload - всё это очень неудобно, Angie благодаря наличию параметра resolve
и метрик идеально подходит на роль Keepalive Proxy, только вот не хватает одной метрики, чтобы отслеживать ситуацию, когда в upstream
не осталось серверов.
Да, надо придумать как это лучше всего сделать.
Пока могу предложить такое обходное решение:
upstream one {
#...
zone one 1m;
}
map $peers_len $is_peers_empty {
4 1;
default 0;
}
prometheus_template test {
angie_peers_empty $is_peers_empty type=gauge;
}
server {
listen 8000;
location / {
auth_request /api_peers/;
auth_request_set $peers_len $sent_http_content_length;
prometheus test;
}
location =/api_peers/ {
internal;
api /status/http/upstreams/one/peers/;
}
}
Для одного upstream
блока работает. Если нужно несколько, то тут уже сложнее, понадобится njs.
Поясню, как это работает. auth_request
позволяет сделать подзапрос и выставить переменную из ответа на подзапрос. В данном случае мы делаем подзапрос в API и если peers
для upstream one
пустой, то API вернет ответ {}\r\n
- что ровно 4 байта. По размеру ответа в 4 байта с помощью map
мы и определяем, что список пуст (к сожалению auth_request
не дает доступ к самому телу ответа, поэтому приходится использовать косвенные признаки).
Поясню, как это работает.
auth_request
позволяет сделать подзапрос и выставить переменную из ответа на подзапрос. В данном случае мы делаем подзапрос в API и еслиpeers
дляupstream one
пустой, то API вернет ответ{}\r\n
- что ровно 4 байта. По размеру ответа в 4 байта с помощьюmap
мы и определяем, что список пуст (к сожалениюauth_request
не дает доступ к самому телу ответа, поэтому приходится использовать косвенные признаки).
Интересный механизм, но к сожалению upstrame
в конфиге сотни, да и njs добавлять не хочется.
Будет очень хорошо если доработаете API, чтобы оно возвращало не пустой объект.
Подумаем, что с этим можно сделать. Не хотелось бы добавлять дополнительное значение на каждый объект или список в API, иначе это кратно увеличит число таких сопоставлений для генерации метрик. А делать какое-то исключение отдельно для peers
- выглядит очень некрасивым решением.
Но вообще, ситуацию, когда не удалось порезолвить - лучше отслеживать по error_log - там будет [error]
вида example.com could not be resolved (3: Host not found)
. Я бы настроил отправку логов на syslog, там зафильтровал подобные сообщения и поставил алерт на них. Такие алерты будут срабатывать оперативнее, т.к. привязаны к самому событию резолвинга, а не к моменту запроса метрик.
Понятно, что это сложнее и требует дополнительных инструментов.
Подумаем, что с этим можно сделать. Не хотелось бы добавлять дополнительное значение на каждый объект или список в API, иначе это кратно увеличит число таких сопоставлений для генерации метрик. А делать какое-то исключение отдельно для
peers
- выглядит очень некрасивым решением.Но вообще, ситуацию, когда не удалось порезолвить - лучше отслеживать по error_log - там будет
[error]
видаexample.com could not be resolved (3: Host not found)
. Я бы настроил отправку логов на syslog, там зафильтровал подобные сообщения и поставил алерт на них. Такие алерты будут срабатывать оперативнее, т.к. привязаны к самому событию резолвинга, а не к моменту запроса метрик.Понятно, что это сложнее и требует дополнительных инструментов.
Если добавлять в API дополнительное значение сложно, может быть можно сделать так, чтобы в $p8s_value
было значение (null)
, когда API возвращает пустой объект?
Если добавлять в API дополнительное значение сложно, может быть можно сделать так, чтобы в
$p8s_value
было значение(null)
, когда API возвращает пустой объект?
А так устроит, если значение будет только для пустого объекта? Ведь когда он будет непустым - метрики не будет в ответе прометеусу.
Если добавлять в API дополнительное значение сложно, может быть можно сделать так, чтобы в
$p8s_value
было значение(null)
, когда API возвращает пустой объект?А так устроит, если значение будет только для пустого объекта? Ведь когда он будет непустым - метрики не будет в ответе прометеусу.
Думаю да, вполне устроит.
Есть ли новости по этому вопросу?
Есть ли новости по этому вопросу?
Функциональность находится в списке идей на реализацию. Как только освободится место в дорожной карте и если не будет более приоритетных задач, то добавим.