Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api/metrics мониторинг отсутствие peers в upstream #81

Open
karabanov opened this issue Apr 7, 2024 · 12 comments
Open
Labels
enhancement New feature or request

Comments

@karabanov
Copy link

karabanov commented Apr 7, 2024

Здравствуйте.

Есть один недостаток который мешает корректно мониторить состояние upstream с помощью prometheus, а именно, если перестало резолвиться DNS имя сервера указанного в upstream, то все метрики angie_http_upstreams_peers_* пропадают из выдачи, при этом в Console Light для такого upstream выводиться сообщение No servers with 'all' state found in this upstream group.

image

В шаблоне 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.

@VBart
Copy link
Contributor

VBart commented Apr 7, 2024

Если включен динамический резолвинг, то список серверов обновляется согласно ответу DNS сервера. Если ответ пустой, то все сервера удаляются из upstream. Метрики привязаны к конкретным серверам, а те в свою очередь запрашиваются из DNS. Нет серверов, нет и метрик по ним.

@VBart
Copy link
Contributor

VBart commented Apr 7, 2024

У вас получается, что объект /http/upstreams/([^/]+)/peers пуст и не срабатывает матчинг - там нет метрик, которые бы имели значение, сохраняемое в $p8s_value. Пустые списки и объекты пропускаются, так что встроенными средствами модуля такую метрику сейчас получить не получится.

@karabanov
Copy link
Author

karabanov commented Apr 7, 2024

Если включен динамический резолвинг, то список серверов обновляется согласно ответу 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 не осталось серверов.

@VBart
Copy link
Contributor

VBart commented Apr 7, 2024

Да, надо придумать как это лучше всего сделать.

Пока могу предложить такое обходное решение:

    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.

@VBart
Copy link
Contributor

VBart commented Apr 7, 2024

Поясню, как это работает. auth_request позволяет сделать подзапрос и выставить переменную из ответа на подзапрос. В данном случае мы делаем подзапрос в API и если peers для upstream one пустой, то API вернет ответ {}\r\n - что ровно 4 байта. По размеру ответа в 4 байта с помощью map мы и определяем, что список пуст (к сожалению auth_request не дает доступ к самому телу ответа, поэтому приходится использовать косвенные признаки).

@karabanov
Copy link
Author

Поясню, как это работает. auth_request позволяет сделать подзапрос и выставить переменную из ответа на подзапрос. В данном случае мы делаем подзапрос в API и если peers для upstream one пустой, то API вернет ответ {}\r\n - что ровно 4 байта. По размеру ответа в 4 байта с помощью map мы и определяем, что список пуст (к сожалению auth_request не дает доступ к самому телу ответа, поэтому приходится использовать косвенные признаки).

Интересный механизм, но к сожалению upstrame в конфиге сотни, да и njs добавлять не хочется.

Будет очень хорошо если доработаете API, чтобы оно возвращало не пустой объект.

@VBart
Copy link
Contributor

VBart commented Apr 7, 2024

Подумаем, что с этим можно сделать. Не хотелось бы добавлять дополнительное значение на каждый объект или список в API, иначе это кратно увеличит число таких сопоставлений для генерации метрик. А делать какое-то исключение отдельно для peers - выглядит очень некрасивым решением.

Но вообще, ситуацию, когда не удалось порезолвить - лучше отслеживать по error_log - там будет [error] вида example.com could not be resolved (3: Host not found). Я бы настроил отправку логов на syslog, там зафильтровал подобные сообщения и поставил алерт на них. Такие алерты будут срабатывать оперативнее, т.к. привязаны к самому событию резолвинга, а не к моменту запроса метрик.

Понятно, что это сложнее и требует дополнительных инструментов.

@karabanov
Copy link
Author

Подумаем, что с этим можно сделать. Не хотелось бы добавлять дополнительное значение на каждый объект или список в API, иначе это кратно увеличит число таких сопоставлений для генерации метрик. А делать какое-то исключение отдельно для peers - выглядит очень некрасивым решением.

Но вообще, ситуацию, когда не удалось порезолвить - лучше отслеживать по error_log - там будет [error] вида example.com could not be resolved (3: Host not found). Я бы настроил отправку логов на syslog, там зафильтровал подобные сообщения и поставил алерт на них. Такие алерты будут срабатывать оперативнее, т.к. привязаны к самому событию резолвинга, а не к моменту запроса метрик.

Понятно, что это сложнее и требует дополнительных инструментов.

Если добавлять в API дополнительное значение сложно, может быть можно сделать так, чтобы в $p8s_value было значение (null), когда API возвращает пустой объект?

@VBart
Copy link
Contributor

VBart commented Apr 8, 2024

Если добавлять в API дополнительное значение сложно, может быть можно сделать так, чтобы в $p8s_value было значение (null), когда API возвращает пустой объект?

А так устроит, если значение будет только для пустого объекта? Ведь когда он будет непустым - метрики не будет в ответе прометеусу.

@karabanov
Copy link
Author

Если добавлять в API дополнительное значение сложно, может быть можно сделать так, чтобы в $p8s_value было значение (null), когда API возвращает пустой объект?

А так устроит, если значение будет только для пустого объекта? Ведь когда он будет непустым - метрики не будет в ответе прометеусу.

Думаю да, вполне устроит.

@VBart VBart added the enhancement New feature or request label Apr 12, 2024
@karabanov
Copy link
Author

Есть ли новости по этому вопросу?

@VBart
Copy link
Contributor

VBart commented Jul 26, 2024

Есть ли новости по этому вопросу?

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants