Стероиды для Munin

в 15:40, , рубрики: linux, munin, системное администрирование, метки: ,

Munin очень неплохая штука для мониторинга серверов, особенно одного-двух. Однако если количество серверов растёт работает он всё хуже и хуже. Под катом рассказ как я разгонял его до мониторинга больше чем 1000 виртуалок (275K rrd файлов в системе).

Почему Munin

Munin прекрасен:
— не требователен по ресурсам (пока серверов мало);
— простая настройка (удобные умолчания, простой текстовый конфиг);
— просто пишутся плагины (и есть куча готовых плагинов).

Munin ужасен:
— удобные умолчания не изменяются;
— интеграция с Nagios бесполезна;
— неудобные группировки графиков;
— «не любит» долго работающих плагинов, нужно делать костыли;
— код внутри тоже не блещет красотой.

Базируется на rrd, это добавляет как плюсы, так и минусы.

Модель плагинов у Munin оказалась удобной, разработчик может добавить графики в роль не дожидаясь пока кто-то заведёт что-то в центральной базе. Это нам ещё аукнется размером конфига, но удобно же.
Главное, Munin уже был. Переходить на другую систему значит переделывать существующий софт и переучивать людей.

Проблемы

— стал наступать себе на хвост (не успевает завершиться за 5 минут);
— очень сильно грузит диск;
— неудобно править конфиги (постоянно забываешь добавить новый сервер или убрать старый);
— агрегированные графики сложно писать;
— не было интеграции с Nagios.

Вдобавок агрегированные графики лгут. Потому что если суммировать количество запросов с 10 серверов, а потом выключить 5, то исторические данные убавяться в 2 раза! Естественно, так как суммарный график вычисляется каждый раз и не сохраняется, поменялась формула — поменялся прошлый график.

И их решение

Разгоняем

Обязательно надо сделать генерацию графиков как CGI/FastCGI, это ускоряет но не сильно.

Радикально разогнать Munin можно только затратным способом, положить все rrd в память (tmpfs). Ничего другого, ни RAID, ни SSD не помогает, увы. 275K rrd занимают 14GB, что не так уж и много, сервер с 32GB RAM не редкость (ещё несколько GB сожрут процессы самого Munin). Зато диск может быть самый обычный.

Естественно, раз в пару часов надо сбрасывать на диск и паковать имеющиеся RRD на всякий случай. Упакованный архив прекрасно пишется на SATA диск.

Сам Munin не чистит rrd, поэтому надо чистить не используемые rrd
/usr/bin/find /mnt/ramdrive/ -type f -mtime +5 -delete

Небольшое отступление про неизбежность использования памяти

Проблема всех подобных систем в том, что данные поступают «поперечно» (одно измерение с каждой метрики), а обрабатываются «продольно» (все измерения для одной метрики) и перетасовать этот поток очень непросто. Можно писать как rrd сразу «продольно» и ждать записи, можно писать в базу «поперечно» (просто добавлять записи по одной в большую таблицу) и потом медленно их читать.
В любом случае без большого кеша/индекса в памяти не обойтись.

Раз уж у нас много памяти, то update запускаем без ограничения процессов, это помогает с медленными плагинами. Только я взводил таймер для убийства munin-update, которые работают дольше 3 минут.

Следующим начинает тупить рисовалка графиков. Профилирование показало, что чем больше серверов, тем больше конфиг и он парсится при каждом запуске munin-graph-cgi. У меня конфиг дорос до 64 мегабайт и парсинг его занимал до 7 секунд (100% загрузка CPU). Решение очевидно, не надо парсить его повторно, но чтобы подставить этот костыль надо править код Munin.

munin-update будет читать и писать конфиг как обычно, плюс сохранять объект конфига при помощи модуля Storable. munin-graph будет читать Storable файл, если он есть.
Это разгоняет рисование графиков, но кушает память, 64 мегабайта конфига превращаются в 375MB виртуальной памяти на процесс.

Как ни странно это не большая проблема для munin-update, так как он сначала разворачивает конфиг в памяти, а потом делает fork. В итоге в top 1000 процессов с RSS в 250MB и всего 21GB RAM used (14 из них это rrd!)
Куда большая проблема с munin-graph, так как там каждый процесс честно кушает свои 400MB памяти, но пока памяти хватает.

Следующая проблема оказалась с запуском munin-html, он не успевал отрабатывать. Вылечилось запуском асинхронно, и несколькими fork в коде. HTML рисуются раз в 10, а не в 5 минут, но это и не нужно особенно, только если новый сервер добавить.

И делаем удобнее

Текстовые конфиги неудобно править руками, но очень удобно генерировать скриптом. Благо к тому времени у нас уже была база серверов с разбиением по системам (виртуалки) и по датацентрам (физические хосты). Простенький скрипт переписывает конфиг Munin на основании этой базы и группирует сервера по системам (Domain в терминах Munin). Новые сервера появляются автоматически, старые так же автоматически пропадают. Красота!

Следующая проблема это рисование агрегированных графиков.
План такой, скриптом делаем выборку нужных rrd, берём последнее значение из них и, например, складываем.

Получается вот такой munin плагин для рисования суммы запросов по серверам

#!/usr/bin/perl -w

use strict;
use warnings;

if($ARGV[0] && $ARGV[0] eq 'config') {
    print <<<'EOS';
host_name Aggregated
graph_title Total requests 
graph_args --base 1000 -l 0
graph_vlabel requests
graph_category Nginx 
graph_info Total count of requests
total.label total requests
total.info total requests
EOS    
    exit(0);
}

my <hh user=rrd_files> = `/bin/ls /mnt/ramdrive/munin/oMobile/*-nginx_log_access-total-d.rrd`;
my $sum = 0;

foreach my $filename (<hh user=rrd_files>) {
   next unless(-f $filename);
   my $lastline = `/usr/bin/rrdtool fetch $filename AVERAGE -s -15M -e now | fgrep -v 'nan' | tail -n 1`;
   if($lastline =~ m/^d+: ([-+.0-9e]+)s*$/) {
      $sum+=$1;
   }
}
print "total.value $sumn";
exit(0);

Никогда так не делайте! Это только для демонстрации, он делает тучу ненужных exec, в продакшен обязательно использовать RRD.

Чаще всего делается или сумма, или группировка нескольких линий на один график (очень хорошо видно не выбивается ли кто-то из толпы). Но можно же и вычислять нечто более сложное. Например, дано среднее время обработки запроса на каждом сервере и количество запросов на сервер, тогда можно вычислить среднее время запроса по всей системе.

Обратите внимание на host_name, так можно создать виртуальные хосты и домены в Munin и группировать интересные графики в них.

Если читать не только последнее значение из RRD, то можно ловить резкие взлёты и падения графиков. Как правило, резкое, процентов на 20, изменение количества запросов, времени ответа, LA и т.д. не к добру и требует внимания. Берём данные за последний час, день, неделю и сравниваем. Если расхождение большое, то можно послать алерт (passive check в Nagios, например).

Итого

— Любую систему, базирующуюся на rrd можно разогнать, если положить rrd файлы в память (tmpfs);
— Munin удобный для небольших проектов можно растянуть и на заметное количество серверов (у меня >1500 munin-node);
— Небольшой скрипт и можно нарисовать довольно сложные графики;
— Небольшой скрипт и можно анализировать тренды и репортить алерты на них.

Автор: vmarunin


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js