Pull to refresh

Мониторинг прогнозированием с помощью rrdtool, как это делается

Reading time 7 min
Views 17K


Введение


Недавно я описывал созданную мной систему мониторинга транзитного VoIP методом прогнозирования. Самым сильным плюсом данного метода в задаче мониторинга транзитного VoIP является то, что нет необходимости выставлять критерии того, что считать нормальной работой величин, находящихся под мониторингом, а что – потенциальным сбоем.
Ядром системы является rrdtool, в котором реализованы прогнозирование методом Хольта-Винтерса и механизм выявления аберраций.
Мониторинг методом прогнозирования можно использовать не только для VoIP, но и для любого другого типа трафика, а так же, для величин, которые изменяются во времени с некой прогнозируемой цикличностью. В отличие от стандартных методов, при мониторинге с помощью прогнозирования не осуществляет мониторинг состояния величин, находящихся под мониторингом, зато осуществляется мониторинг динамики изменения их состояний во времени.
Если вам интересна математика прогнозирования рекомендую прочесть. Чтобы быть хоть немного в курсе темы, прочтите главу “Метод прогнозирования реализованный в rrdtool” моего предыдущего поста.

Задача


Как я писал в предыдущем посте, прежде чем реализовать мониторинг транзитного VoIP методом прогнозирования, было решено проверить концепцию на сервере доступа Cisco AS5400, причем проверять на IP трафике, количестве активных звонков и загрузке его процессора. Как это было сделано я и опишу.
Данные, в данном случае, проще всего получать по SNMP. Таким образом, для тестирования необходимо снимать данные по двум счетчикам – количества октетов IN/OUT прошедших через FastEthernet интерфейс, и двум (в терминах SNMP и rrdtool) GAUGE значениям – по загрузке процессора и количеству активных звонков, точнее, количеству занятых тайм слотов на потоках E1.
Для проверки количества активных звонков используется вот этот OID
.1.3.6.1.4.1.9.10.19.1.1.4.0
Загрузка процессора проверяется чтением этого OID–а
.1.3.6.1.4.1.9.2.1.58.0
Счетчик исходящих октетов, прошедших через интерфейс доступен по OID–у
.1.3.6.1.2.1.2.2.1.16.1 если проверяется интерфейс с индексом 1.
Счетчик входящий октетов, пришедших на интерфейс доступен по OID –у
.1.3.6.1.2.1.2.2.1.10.1 если проверяется интерфейс с индексом 1.

Решение


Решение разбивается на несколько задач. Сначала корректно формируются базы данных rrdtool, потом пишется скрипт для заполнения баз данных значениям, далее скрипт для отображения данных на графике.

Создание баз данных rrd

Создаем два скрипта для формирования баз данных rrd
counter.sh
#!/usr/local/bin/bash
rrdtool create --step 300 $1.rrd \
DS:val:COUNTER:600:0:U \
RRA:AVERAGE:0.5:1:8064 \
RRA:HWPREDICT:8064:0.1:0.0035:288 \
RRA:FAILURES:8064:2:3:4


gauge.sh
#!/usr/local/bin/bash
rrdtool create --step 300 $1.rrd \
DS:val:GAUGE:600:0:U \
RRA:AVERAGE:0.5:1:8064 \
RRA:HWPREDICT:8064:0.1:0.0035:288 \
RRA:FAILURES:8064:2:3:4


Отличие заключается только в типе значения val.
Разберемся, что создастся при запуске скрипта.
1) RRA:AVERAGE:0.5:1:8064 — база данных, которая будет содержать 8064 значения измерений при частоте измерений раз в 5 минут. При частоте измерений раз в 5 минут, за день получается 288 измерений, всего в базе данных может храниться информация за 8064 / 288 = 28 дней.
2) RRA:HWPREDICT:8064:0.1:0.0035:288 – база данных будет хранить 8064 прогнозов, то есть столько же сколько определено значений измерений. Заданы коэффициенты alpha = 0.1, beta = 0.0035. Это коэффициенты, которые влияют на точность прогноза. Такие параметры оптимальны, если вы видите изо дня в день примерно одинаковую картину на графике. Более того, такие коэффициенты рекомендованы на сайте rrdtool. Коэффициенты можно менять, чтобы добиться более точных прогнозов, но это тема отдельной статьи. 288 – количество измерений за сезон, таким образом, сезон равен суткам.
3) RRA:FAILURES:8064:2:3:4. – база данных будет хранить информацию по вычисленным аберрациям за 28 дней (по умолчанию хранится только за последний сезон — сутки). Аберрации будут вычисляться с длиной плавающего окна равной 3 и количеством непопаданий в окно равному 2. Последний параметр – 4 это индекс DEVSEASONAL, этот индекс можно посмотреть командой rrdtool info.
Если возникли вопросы по созданию баз данных, посмотрите тут
Теперь создадим скриптами нужные базы данных
./counter.sh in_traf
./counter.sh out_traf
./gauge.sh cpu
./gauge.sh calls


Скрипт для заполнения баз данных значениями

Собственно, скрипт прост
rrdupdater.sh
#!/usr/local/bin/bash
rrdtool="/usr/local/bin/rrdtool update "
# snmpget -OQEav option will make value to be "clean" no quotes, oid name, etc…
snmpget="/usr/local/bin/snmpget -OQEav -v2c -c SuperSecret  "
rrdpath="/usr/rrdmonit/rrd/"
${rrdtool} ${rrdpath}in_traf.rrd N:`${snmpget} 192.168.50.31 .1.3.6.1.2.1.2.2.1.10.1`
${rrdtool} ${rrdpath}out_traf.rrd N:`${snmpget} 192.168.50.31 .1.3.6.1.2.1.2.2.1.16.1`
${rrdtool} ${rrdpath}cpu.rrd N:`${snmpget} 192.168.50.31 .1.3.6.1.4.1.9.2.1.58.0`
${rrdtool} ${rrdpath}calls.rrd N:`${snmpget} 192.168.50.31 .1.3.6.1.4.1.9.10.19.1.1.4.0`

Ну и конечно, в crontab его
*/5 * * * * /usr/rrdmonit/rrdupdater.sh

Отображение графиков

rrdtool – мощное средство для построения графиков. Графики можно сделать весьма информативными.
К примеру, в системе мониторинга VoIP трафика у нас они такие:

Синяя линия это реальные значения измерений количества минут, которые прошли на партнёра за 15 минутный интервал времени. Серая площадь – реальные значения, которые были ровно сутки назад. Розовая линия — прогноз. Красная и зелёные линии показывают верхнюю и нижнюю границу коридора допустимых значений. Черная линия в области отрицательных значений – прогноз допустимых отклонений от спрогнозированных значений (deviation). Золотым цветом показана аберрация. Когда появилась аберрация, система выдала оповещение (по e-mail) о потенциальном сбое. Очевидно, что в данном случае, наличие сбоя у поставщика трафика весьма вероятно.
Обратите внимание на значение Total для измеряемой величины. Оно, с погрешность в 1-2 процента равно значению, взятому из биллинга для данного поставщика. Для системы мониторинга это может считаться высокой точностью.
Необходимо отметить, что есть два различных подхода при построении графиков измеряемых величин. Первый подход реализован в классическом MRTG – графики (рисунки) строятся сразу после заполнения новым значением базы данных rrdtool. Второй подход реализован в cacti – графики строятся по запросу пользователя. В нашей системе мониторинга VoIP используется второй подход. Однако для проверки концепции можно использовать первый подход, он гораздо проще. Рисунки будут генерироваться сразу после заполнения базы данных.
Собственно скрипт:
#!/usr/bin/env python
import os
import time
import rrdtool

# Define params
rrdpath = '/usr/rrdmonit/rrd/'
pngpath = '/usr/local/share/cacti/rrdmonit/'
width = '500'
height = '200'

# Generate charts for last 48 hours
enddate = int(time.mktime(time.localtime())) 
begdate = enddate - 172800
        

def gen_image(rrdpath, pngpath, fname, width, height, begdate, enddate):
    """
    Generates png file from rrd database:
    rrdpath - the path where rrd is located
    pngpath - the path png file should be created in
    fname - rrd file name, png file will have the same name .png extention
    width - chart area width
    height - chart area height
    begdate - unixtime
    enddate - unixtime  
    """
    # 24 hours before current time, will show on chart using SHIFT option  
    ldaybeg = str(begdate - 86400)
    ldayend = str(enddate - 86400)
    # Will show some additional info on chart 
    endd_str = time.strftime("%d/%m/%Y %H:%M:%S",(time.localtime(int(enddate)))).replace(':','\:')
    begd_str = time.strftime("%d/%m/%Y %H:%M:%S",(time.localtime(int(begdate)))).replace(':','\:')
    title = 'Chart for: '+fname.split('.')[0]
    # Files names 
    pngfname = pngpath+fname.split('.')[0]+'.png'
    rrdfname = rrdpath+fname
    # Get iformation from rrd file
    info = rrdtool.info(rrdfname)
    rrdtype = info['ds[val].type']
    # Will use multip variable for calculation of totals,
    # should be usefull for internet traffic accounting,
    # or call/minutes count from CDR's. 
    # Do not need logic for DERIVE and ABSOLUTE
    if rrdtype == 'COUNTER':
        multip = str(int(enddate) - int(begdate))
    else:
        # if value type is GAUGE should divide time to step value
        rrdstep = info['step']
        multip = str(round((int(enddate) - int(begdate))/int(rrdstep)))
    # Make png image
    rrdtool.graph(pngfname,
    '--width',width,'--height',height,
    '--start',str(begdate),'--end',str(enddate),'--title='+title,
    '--lower-limit','0',
    '--slope-mode',
    'COMMENT:From\:'+begd_str+'  To\:'+endd_str+'\\c',
    'DEF:value='+rrdfname+':val:AVERAGE',
    'DEF:pred='+rrdfname+':val:HWPREDICT',
    'DEF:dev='+rrdfname+':val:DEVPREDICT',
    'DEF:fail='+rrdfname+':val:FAILURES',
    'DEF:yvalue='+rrdfname+':val:AVERAGE:start='+ldaybeg+':end='+ldayend,
    'SHIFT:yvalue:86400',
    'CDEF:upper=pred,dev,2,*,+',
    'CDEF:lower=pred,dev,2,*,-',
    'CDEF:ndev=dev,-1,*',
    'CDEF:tot=value,'+multip+',*',
    'CDEF:ytot=yvalue,'+multip+',*',
    'TICK:fail#FDD017:1.0:"Failures"\\n',
    'AREA:yvalue#C0C0C0:"Yesterday\:"',
    'GPRINT:ytot:AVERAGE:"Total\:%8.0lf"',
    'GPRINT:yvalue:MAX:"Max\:%8.0lf"',
    'GPRINT:yvalue:AVERAGE:"Average\:%8.0lf" \\n',
    'LINE3:value#0000ff:"Value    \:"',
    'GPRINT:tot:AVERAGE:"Total\:%8.0lf"',
    'GPRINT:value:MAX:"Max\:%8.0lf"',
    'GPRINT:value:AVERAGE:"Average\:%8.0lf" \\n',
    'LINE1:upper#ff0000:"Upper Bound "',
    'LINE1:pred#ff00FF:"Forecast "',
    'LINE1:ndev#000000:"Deviation "',
    'LINE1:lower#00FF00:"Lower Bound "')

# List files and generate charts
for fname in os.listdir(rrdpath):
    gen_image(rrdpath, pngpath, fname, width, height, begdate, enddate)


Запускать выполнение скрипта надо сразу же после заполнения значений в rrdtool, поэтому строку для его запуска необходимо добавить в конец скрипта /usr/rrdmonit/rrdupdater.sh.
Дело осталось за малым – вывесить сгенерированные рисунки куда-то на web. Например, таким скриптом на PHP.
<?php
   $dir = './rrdmonit/';
   $dirHandle = opendir($dir);
   while ($file = readdir($dirHandle)) {
      if(!is_dir($file) && strpos($file, '.png')>0) {
         print "<img src='.$dir".$file."' />\n";
      }
   }
   closedir($dirHandle);
?>


Помнится, когда я первый раз настраивал такой мониторинг, потратил много времени, чтобы понять, что я делаю не так. Дело в том, что как я не настраивал прогнозирование, как ни пытался различными способами формировать рисунок графика, линия прогноза упорно не появлялась. Убив на курение мануалов несколько часов, я плюнул, чтобы вернуться к этому на следующий день. На следующий день – о чудо, прогноз появился сам собой. Все оказалось тривиально, прогноз не делался потому, что не прошел первый сезон прогнозирования (сутки после начала заполнения базы данных).
Как я писал раньше, наряду с прогнозированием значений измеряемой величины прогнозируется и коридор разброса возможных значений – diviation. Diviation можно прогнозировать только тогда, когда у вас есть значения для двух сезонов.
Поэтому, предварительный результат вы получите только с начала третьих суток.

На графике – первые три дня с момента начала измерений. Как видно прогноз кривой. Но посмотрите, что будет дальше.

Прогноз все более точен. Через неделю у вас будет полностью функциональный мониторинг интересующих величин.
Величины на представленных графиках ведут себя в течении суток по законам, похожим на синусоиды. Не хотелось бы, чтобы у вас возникло ощущение, что метод работает только для таких величин. К примеру величины ASR и ACD в транзитном VoIP ведут себя несколько иначе, не смотря на это метод работает прекрасно и для них. Взгляните на рисунок


Заключение


Система мониторинга делается не только для того, чтобы администратор пялился на рисунки, она должна давать оповещение (по меньшей мере по почте), когда обнаруживается аберрация. Об этом – в следующем посте.
Tags:
Hubs:
+39
Comments 13
Comments Comments 13

Articles