Nagios - установка и настройка

Материал из Belgorod Linux User Group - Белгород

Перейти к: навигация, поиск

Nagios - система мониторинга.

  • Позволяет мониторить как локальные, так и сетевые ресурсы в реальном времени
  • Отображение статуса в трехцветной форме (светофор) - зеленый (ok), желтый (warning), красный (error), с описанием причины ошибки
  • Может уведомлять пользователя (по почте, sms, jabber)
  • Имеет тактический монитор (позволяющий оперативно определить все возможные проблемы и их приоритет)
  • Строит всевозможные сводные таблицы и графики
  • Приятной особенностью является то, что отображаемые данные не обязательно должны быть системными или сетевыми параметрами - это могут быть любые количественные и качественные данные (например количество пользователей в базе, температура воздуха на улице, процент ошибок персонала и т.п.). Достигается это за счет простого написания скриптов для nagios (писать можно на любом языке: C, C++, bash, perl, php и т.п.).

Nagios-service.png

Содержание

Установка

Ставим nagios своим пакетным менеджером. Я буду описывать на примере Gentoo Linux.

Для начала посмотрим что мы имеем:

emerge -pv nagios

Затем выставим все нужные нам флаги (встроенные плагины к nagios устанавливаются посредством USE-флагов):

echo "net-analyzer/nagios-core apache2" >> /etc/portage/package.use
echo "net-analyzer/nagios-plugins mysql nagios-ntp nagios-ping nagios-ssh ups snmp" >> /etc/portage/package.use

Ставим сам пакет.

emerge nagios

Настройка

Настройка nagios производится посредством редактирования файлов конфигурации. Система работает автономно и может мониторить и уведомлять в режиме демона. Web-фронтэнд ей не обязателен. Но нам нужен :)

Web frontend

Создаем файл виртуального хоста для apache:

/etc/apache2/vhosts.d/nagios.conf

<VirtualHost *:80>
       ServerName monitoring.lan
       
       DocumentRoot /usr/share/nagios/                
       Alias /nagios/ /usr/share/nagios/htdocs/
       <Directory "/usr/share/nagios">
               Options None
               AllowOverride AuthConfig
               Order allow,deny
               Allow from all
       </Directory>
       
       ScriptAlias /nagios/cgi-bin/  /usr/lib/nagios/cgi-bin/
       <Directory "/usr/lib/nagios/cgi-bin">
               AllowOverride AuthConfig
               Options +ExecCGI
               Order allow,deny
               Allow from all
       </Directory>
</VirtualHost>

Теперь создадим файл авторизации пользователя.

/usr/lib/nagios/cgi-bin/.htaccess
AuthName "Nagios Access"
AuthType Basic
AuthUserFile /usr/share/nagios/htpasswd.users
require valid-user

Создаем сам пароль:

htpasswd -c /usr/share/nagios/htpasswd.users admin

Даем права нашему админу:

cd /etc/nagios/
sed "s/nagiosadmin/admin/gi" cgi.cfg > cgi.cfg

Перезапускаем apache

/etc/init.d/apache reload

Добавление серверов

Для этого удобнее создать для них отдельную директорию:

mkdir /etc/nagios/servers

И подключить эту директорию в файле nagios.cfg, просто раскоментировав строку

cfg_dir=/etc/nagios/servers

Теперь сами сервера. К примеру у нас 3 сервера для myweb (пусть имена у них srv_www, srv_db, srv_pool).

Группа серверов

Создаем файл к примеру /etc/nagios/servers/group-myweb.cfg

define hostgroup{
       hostgroup_name myweb ; имя группы
       alias           Web Servers ; описание
       members         srv_www, srv_db, srv_pool ; перечень серверов
       }

Хосты

  • Внимание: В nagios, в принципе, не имеет значения в каком вы файле что пишите. Главное, чтобы он или его директория подключались из главного конфигурационного файла nagios.cfg. По этому как называть файлы и что в них писать - решать вам. Как вам будет удобнее.

Удобнее для каждого хоста создать отдельный файл, в котором указать его имя, ip, и необходимые сервисы (которые будут мониториться). Создаем файл к примеру /etc/nagios/servers/myweb-srv_www.cfg

######
# HOST
define host{
       use                     linux-server
       host_name               srv_www            ; имя
       address                 192.168.0.12       ; IP
       }
######
# SERVICE
define service{
       use                             local-service
       host_name                       srv_www            ; имя сервера
       service_description             PING
       check_command                   check_ping!100.0,20%!500.0,60%
       }
define service{
       use                             local-service
       host_name                       srv_www            ; имя сервера
       service_description             SSH
       check_command                   check_ssh
       notifications_enabled           0
       }
define service{
       use                             local-service
       host_name                       srv_www            ; имя сервера
       service_description             HTTP
       check_command                   check_http
       notifications_enabled           0
       }

Для остальных хостов в группе делаем подобные файлы. Доступные команды описаны в файле /etc/nagios/objects/commands.cfg

Группа сервисов

Для объединения логически связанных сервисов из разных хостов существуют группы сервисов (servicegroup). Они видны на отдельной закладке и позволяют судить о здоровье сервиса в целом по заданным характеристикам. Для этого необходимо выделить важные сервисы из хостов и описать их по формату: имя_сервера,имя_его_сервиса,имя_сервера,имя_его_сервиса

define servicegroup {
       servicegroup_name       www
       alias   My www hosting
       members srv_www,Users,srv_www,Load Average,srv_db,Postgres Request Count,srv-db,Load Average,srv-db2,Load Average,srv-db3,Load Average
}

Запуск

/etc/init.d/nagios start
rc-update add nagios default

Построение графиков

Графики в nagios не являются основным. Для этого лучше использовать наверное Cacti. Но все же графики можно прирутить. Плагином например. php4nagios или nagiosgpaph

pnp4nagios

Установка

Для построения графиков будем использовать пакет pnp4nagios

Для начала выставим нужный флаг (будет нужен для rrdtool)

echo "x11-libs/cairo svg" >> /etc/portage/package.use
emerge -1 cairo

далее, для корректной отрисовки (проблемы с кодировкой) графиков в php4nagios потребуется пакет corefonts (ebuild почему-то не тянет его зависимостью):

emerge -1 corefonts

Ставим сам пакет:

emerge pnp4nagios

Добавляем алиас для него в apache:

/etc/apache2/vhosts.d/nagios.conf
Alias /nagios/pnp       /usr/share/pnp/
       <Directory /usr/share/pnp>
               AllowOverride AuthConfig
               Order allow,deny
               Allow from all
       </Directory>

(до описания Alias /nagios/ )

Настройка

Чтобы собирались графики надо выставить значение

process_performance_data=1

Это можно поменять либо для всех ( в файле /etc/nagios/nagios.cfg )

Либо для каждого сервиса отдельно, в файлах сервисов ( /etc/nagios/servers ). Делается это там же, в описании сервисов. К примеру:

define service{
       use                             local-service
       host_name                       www
       service_description             PING
       check_command                   check_ping!100.0,20%!500.0,60%
       process_perf_data 1
       }

будет означать, что надо собирать данные по ping-у


Так же в файле /etc/nagios/nagios.cfg раскоментируем:

host_perfdata_command=process-host-perfdata
service_perfdata_command=process-service-perfdata

Теперь надо добавить сами команды в файл /etc/nagios/objects/commands.cfg, закоментировав их предыдущее определение

define command {
 command_name    process-service-perfdata
 command_line    /usr/bin/perl /usr/libexec/process_perfdata.pl
}
define command {
 command_name    process-host-perfdata
 command_line    /usr/bin/perl /usr/libexec/process_perfdata.pl -d HOSTPERFDATA
}


Чтобы появились ссылки на графики, в описание хостов ( файлах, расположенных в /etc/nagios/servers/ ) добавляем строку

       action_url /nagios/pnp/index.php?host=$HOSTNAME$

Пример:

define host{
       use                     linux-server
       host_name               www
       address                 192.178.0.12
       action_url /nagios/pnp/index.php?host=$HOSTNAME$
       }

Либо если хотим для всех хостов, то тобавляем в их шаблон ( /etc/nagios/objects/templates.cfg )

define host{
       name linux-server
       use  generic-host
       ......
       action_url /nagios/pnp/index.php?host=$HOSTNAME$
}
/etc/init.d/nagios reload

У вашего хоста рядом появится уже "клякса", которая будет ссылкой на графики.

Создание собственного сервиса и графика к нему

Создаем скрипт, который будет в одну строку возвращать нужные нам данные в формате

"статус | имя=значение имя2=значение2 ..."

К примеру такой скрипт использования памяти :

#!/bin/bash
OID_TOTAL=".1.3.6.1.4.1.2021.336.4.1.2.7.102.114.101.101.77.101.109.1"
OID_CACHED=".1.3.6.1.4.1.2021.336.4.1.2.7.102.114.101.101.77.101.109.2"
OID_USED=".1.3.6.1.4.1.2021.336.4.1.2.7.102.114.101.101.77.101.109.3"

HOST=$1
COMMUNITY=$2

RES=0
function my_snmp_get () {
 RES=$(/usr/bin/snmpget -t 1 -r 5 -m  -v 1 -c$COMMUNITY $HOST $1 | sed 's/[^"]*"\(.*\)"/\1/gi')
}

my_snmp_get $OID_TOTAL
TOTAL=$RES

my_snmp_get $OID_CACHED
CACHED=$RES

my_snmp_get $OID_USED
USED=$RES

MU=$(echo "$USED/1024" | bc)
MT=$(echo "$TOTAL/1024" | bc)

echo "OK - used ${MU}M of ${MT}M | total=$TOTAL cached=$CACHED used=$USED"
exit 0

Как видно - наш плагин является просто bash-скриптом. Это может быть любой исполняемый файл. Главное чтобы он возвращал статус (принято OK / WARNING / CRITICAL) и нужные нам значения переменных через пробел в формате имя=значение. В данном случаи скрипт принимает на вход первым параметром адрес опрашиваемого по SNMP хоста, а вторым - snmp community. Так же мы возвращаем код ошибки (по exit) 0-это OK, 1-WARNING, 2-CRITICAL, 3-UNKNOWN, 4-DEPENDENT

Сохраняем его в директории с плагинами Nagios: /usr/lib/nagios/plugins/check_my_mem и даем ему право на запуск:

chmod +x /usr/lib/nagios/plugins/check_my_mem

Далее описываем команду для запуска этого скрипта в файле команд: /etc/nagios/objects/commands.cfg

define command{
       command_name    check_my_mem
       command_line    $USER1$/check_my_mem $HOSTADDRESS$ $ARG1$
}

тут мы указали имя скрипта и передали нужные параметры: имя хоста и community. Community мы передадим из сервиса в качестве параметра $ARG1$, т.к. он может быть разный для каждого хоста.

Теперь описываем сервис (в шаблоне хостов или в самом хосте ):

define service {
       use                             local-service
       host_name                       web
       service_description             My Memory Usage
       check_command                   check_my_mem!public
}

Как видно мы вызвали нашу описанную выше команду с параметром коммьюнити. Как правило остальными параметрами (разделяются через знак !) передаются пределы значений для WARNING и CRITICAL, которые будут обрабатываться скриптом / плагином и возвращать соответствующий статус.

Теперь можно перечитать настройки nagios и через некоторое время посмотреть - создался ли файл данных для нашего нового сервиса:

/etc/init.d/nagios reload
less /var/nagios/perfdata/www/My_Memory_Usage.xml


Шаблоны pnp4nagios

Теперь наши данные собираются и уже их видно в мониторинге. Осталось нарисовать график.

Если вы знакомы с rrdtools, то шаблоны pnp4nagios не будут для вас препятствием. Если не знакомы - ничего страшного.

Создаем шаблон с именем нашего сервиса:

vim /usr/share/pnp/templates/check_my_mem.php

И пишем туда следующее:

<?php
$opt[1] = "--alt-autoscale-max --lower-limit=0 ";
$def[1] .= "DEF:a1=$rrdfile:$DS[1]:AVERAGE ";
$def[1] .= "DEF:a2=$rrdfile:$DS[2]:AVERAGE ";
$def[1] .= "DEF:a3=$rrdfile:$DS[3]:AVERAGE ";

$def[1] .= "CDEF:var1=a1,1024,* ";
$def[1] .= "CDEF:var2=a2,1024,* ";
$def[1] .= "CDEF:var3=a3,1024,* ";
 
$def[1] .= "AREA:var1#002A97:$NAME[1] ";
$def[1] .= "AREA:var2#FFAB00:$NAME[2] ";
$def[1] .= "AREA:var3#FF0000:$NAME[3] ";

$def[1] .= 'COMMENT:" \n" ';
$def[1] .= "GPRINT:var1:AVERAGE:\"%8.2lf %s $NAME[1] \" ";
$def[1] .= "GPRINT:var2:AVERAGE:\"%8.2lf %s $NAME[2] \" ";
$def[1] .= "GPRINT:var3:AVERAGE:\"%8.2lf %s $NAME[3] \" ";
?>

Это по сути формирование командной строки для rrdtool. Тут я использую переменные $DS, $NAME и прочие. С ними можно ознакомиться, посмотрев xml-файл, созданный pnp4nagios-ом при опросе.

less /var/nagios/perfdata/www/My_Memory_Usage.xml

Видим, что NAME - это имя. А индекс в массиве - это номер записи. $rrdfile - файл, $DS - имя (номер) источника данных. Там еще много может быть переменных - это и максимальные и критические значения и пр. Но мы пока это опустим. Для нас главное, это то, что переменная для отрисовки определяется как DEF:a1=$rrdfile:$DS[1]:AVERAGE, а индекс [1] - это номер значения. Если своим скриптом мы возвращали одно имя=значение, то достаточно $DS[1], а если несколько, то появятся и 2 и 3, как у меня в примере.

Далее. Формат описания для rrdtool довольно прост.

* DEF - определение переменной, 
* CDEF - применение функции к переменной (в данном случаи я умножаю на 1024)
* AREA / LINE - отрисовка переменной 
* COMMENT - строка коментария
* GPRINT - печать переменной заданным шаблоном

Теперь можно смотреть графики. Если график не отрисовался - не переживайте, кликните на "битую" картинку, и pnp4nagios покажет свой debug и скажет в чем вы ошиблись.

nagiosgraph

Еще один плагин для отрисовки графиков - nagiosgraph

Установка

В портах ebuild-а я его не нашел, но установка у него достаточно проста. Скачиваем с их сайта http://nagiosgraph.sourceforge.net/ пакет, распаковываем и следуем указаниям в INSTALL.

Настройка

В файл /etc/nagios/nagios.cfg добавляем строки:

process_performance_data=1
service_perfdata_file=/var/log/nagios/perfdata.log
service_perfdata_file_template=$LASTSERVICECHECK$||$HOSTNAME$||$SERVICEDESC$||$SERVICEOUTPUT$||$SERVICEPERFDATA$
service_perfdata_file_mode=a
service_perfdata_file_processing_interval=30
service_perfdata_file_processing_command=process-service-perfdata

в файл /etc/nagios/objects/commands.cfg строки:

define command{
      command_name  process-service-perfdata
      command_line  /usr/lib/nagios/insert.pl "$LASTSERVICECHECK$||$HOSTNAME$||$SERVICEDESC$||$SERVICEOUTPUT$||$SERVICEPERFDATA$"
}

в файл шаблона /etc/nagios/objects/templates.cfg или в файлы шаблонов хостов /etc/nagios/servers добавляем строки:

notes_url       /nagiosgraph/show.cgi?host=$HOSTNAME$&service=$SERVICEDESC$
icon_image      graph.gif
icon_image_alt  View graphs

Шаблонизация

Nagios представляет собой очень гибкую систему. Одна из ее полезных черт - удобная шаблонизация.

  • Свои шаблоны удобнее хранить в отдельном файле. Заведите себе где-нибудь файл my-templates.cfg, и пропишите строку
cfg_file=/etc/nagios/objects/my_templates.cfg

в файле nageios.cfg

Рассмотрим шаблонизацию на примере плагина мониторинга места http://nagios.manubulon.com/snmp_storage.html

Скачиваем плагин, помещаем его в /usr/lib/nagios/plugins/ и даем права на запуск. Смотрим параметры. Формируем свою строку из этих параметров. У меня получилось что-то вроде этого:

./check_snmp_storage.pl -H 192.168.0.52 -C public -w 80 -c 90 -f -m /var 

Флаг -f (в некоторых плагинах -F) - обязателен для нас, т.к. мы будем строить графики, а этот флаг отвечает за вывод данных в формате имя=значение, для сбора их в perfparse.

Команда

Описываем команду:

# storage usage
define command {
       command_name    check_snmp_storage
       command_line    $USER1$/check_snmp_storage.pl -H $HOSTADDRESS$ -C $ARG1$ -w $ARG2$ -c $ARG3$ -f -m $ARG4$
}

Тут я описал нашу командную строку, составленную выше. Как видим передаю имя хоста, а затем коммьюнити - первым параметром, warning-вторым (проценты заполнения), critical - третьим, а само имя storage буду передавать четвертым. В принципе, в системе уже можно использовать эту команду примерно так:

define service {
service_description Storage Usage
check_snmp_storage!public!80!90!/var
host_name www
}

Но мы будем все упрощать и шаблонизировать!

Хост

Создаем свой шаблон хостов:

define host {
       name                            my-linux-server
       use                             linux-server
       _COMMUNITY                      public
       register                        0
}
  • register 0 указывает на то, что данное описание является шаблоном и в системе не регистрируется как отдельный сервис или хост.

Тут я использовал переменную (макрос) _COMMUNITY для задания snmp-коммьюнити своих хостов. Это макрос хоста. Он будет доступен как $_HOSTvar, т.е. в нашем случаи как $_HOSTCOMMUNITY. Эту переменную я и буду использовать в шаблоне сервисов. По этому если наш хост будет использовать эту коммьюнити, я смогу написать просто use my-linux-server, а могу переназначить его так:

define host {
use my-linux-server
_COMMUNITY S4js3D
....
}

Сервис

Шаблонизируем сервис. Описываем шаблон сервиса:

# storage usage
define service {
       use                             local-service
       name                            snmp-storage
       service_description             Storage Usage
       _WARNING                        80
       _CRITICAL                       90
       _STORAGE                        / -r
       check_command            check_snmp_storage!$_HOSTCOMMUNITY$!$_SERVICEWARNING!$_SERVICECRITICAL!$_SERVICESTORAGE$
       register                        0
}

Тут я описал нашу команду и задал свои макросы. К примеру я ввел такие переменные как _WARNING, _CRITICAL, _STORAGE и выставил их по-умолчанию. В хосте их можно будет переназначить. Вот пример использования это сервиса внутри хоста:

define service {
       use                             snmp-storage
       _STORAGE                        /var
       service_description             /var Usage
       host_name                       www
}

Тут я переназначил значение переменной _STORAGE, и она попадет в команду (check_command) под именем $_SERVICECOMMAND. То есть эти переменные (макросы) я ввел специально, чтобы их можно было переназначить в конечном сервисе, если это будет необходимо (допустим изменить порог _WARNING именно для этого хоста).

Суперсервис

Красивый пример шаблонизации - шаблонизация уже шаблонизированного :) Вот сервис Swap, который мониторит использования свопа, базируясь на нашем вышеописанном шаблоне сервиса snmp-storage:

define service {
       use                             snmp-storage
       name                            swap
       _STORAGE                        Swap
       service_description             Swap Usage
       register                        0
}

Как видно тут я использую свой же шаблон snmp-storage и просто переопределил переменную _STORAGE, получив новый сервис - мониторинга свопа. Использовать в хосте его можно будет очень просто. Так:

define service {
       use                             swap
       host_name                       www
}

Просто. Не правда-ли?

Более того! У нас уже собираются данные, а значит и могут рисоваться графики. Создадим шаблон графика для pnp4nagios:

График

Вот мой файл для этого скрипта:

/usr/share/pnp/templates/check_snmp_storage.php                                                          
<?php
$opt[1] = "--imgformat=PNG ";
$opt[1] .= "--rigid ";
$opt[1] .= "--base=1000 ";
$opt[1] .= "--height=120 ";
$opt[1] .= "--width=500 ";
$opt[1] .= "--alt-autoscale-max ";
$opt[1] .= "--lower-limit=0 ";
$opt[1] .= "--slope-mode ";
$opt[1] .= "--font TITLE:12: ";
$opt[1] .= "--font AXIS:8: ";
$opt[1] .= "--font LEGEND:10: ";
$opt[1] .= "--font UNIT:8: ";
$opt[1] .= return "--title=\"$text $hostname - $servicedesc\" ";
$opt[1] .= "--vertical-label=MB ";

$def[1] = "DEF:var1=$rrdfile:$DS[1]:AVERAGE ";
$def[1] .= "AREA:$MAX[1]#002A97: ";
$def[1] .= "AREA:var1#FF0000: ";

$def[1] .= "HRULE:$MAX[1]#003300:\"Size $MAX[1] MB\" ";
$def[1] .= "HRULE:$WARN[1]#ffff00:\"Warning on $WARN[1] MB \" ";
$def[1] .= "HRULE:$CRIT[1]#ff0000:\"Critical on $CRIT[1] MB \\n\" ";
$def[1] .= "GPRINT:var1:LAST:\"%8.2lf MB of $MAX[1] MB used \\n\" ";
$def[1] .= "GPRINT:var1:MAX:\"%8.2lf MB max used \\n\" ";
$def[1] .= "GPRINT:var1:AVERAGE:\"%8.2lf MB avg used\" ";
?>

Все. Данные и графики для свопа и места на любых носителях готовы.

Совет

Шаблонизируйте все! Описывая любой свой сервис - используйте шаблон. Пусть даже пустой. Создайте метасервис. Пример: Хотим описать много сервисов.

Создаем сначала заглушку - метасервис:

# metaservice
define service {
       use                             local-service
       name                            my-local-service
}

Затем, описываем сами сервисы, наследуя от метасервиса. К примеру для SSH

# SSH
define service{
       use                             my-local-service
       name                            ssh
       service_description             SSH
       check_command                   check_ssh
       register                        0
}

Теперь использовать этот сервис для хоста будем так:

define service {
       use                             ssh
       host_name                       www-srv
}

Удобно. И таких сервисов будет много. НО! Тут мы захотели к примеру добавить уведомления для всех сервисов. Для этого придется либо в каждом конечном сервисе, либо в каждом шаблоне добавлять строки. А мы добавим всего в родительском мета-сервисе:

# metaservice
define service {
       use                             local-service
       name                            my-local-service
       contact_groups                  www-admins
       notification_period             workhours
       register                        0
}

Уведомления

nagios умеет по крайней мере 2 вида уведомлений - уведомления хоста (host_notification) и уведомления сервиса ( service_notification). Уведомления хоста приходят в случаи проблем с хостом (хост недоступен), уведомления сервиса приходят от сервисов (когда превышен порог или сервис недоступен). Типы оповещений тоже настраиваются. Уведомления приходят на соответствующую группу контактов (contact_groups). По этому все это надо описать.

Контакт

Шаблон

Для начала создадим шаблон контактов. Описать его можно к примеру в вашем файле шаблонов

define contact {
       use     generic-contact
       name    my-www-contact
       host_notification_commands      notify-host-by-email,host-notify-by-jabber
       host_notification_options       d,u,r
       service_notification_commands   notify-by-jabber
       service_notification_options    w,u,c,r
       register    0
}

Тут мы создали шаблон контакта. Которому как мы видим от хоста сообщения будут идти и на почту и на jabber. А уведомления от сервиса - только в jabber. Так же мы выставили, события, по которым будут идти уведомления.

d - down, u - unknown, r - recovery, w - warning, c - critical, f - flapping, s - sheduled

Группа

Опишем группу котактов

define contactgroup {
       contactgroup_name    www-admins
       alias                my www hosting
       members              me, cosysop
}

Пользователь

Теперь опишем конечных пользователей, используя наш шаблон:

define contact {
       use                     my-www-contact
       contact_name            me
       alias                   Alex P. Burlutsky
}

Заметим, используется шаблон my-www-contact. Вот так мы описали пользователя с логином me, который состоит в группе www-admins.

Хост

Теперь надо указать, что этой группе (www-admins) должны приходить оповещения от хоста. Для этого в описании хоста (а лучше шаблона хоста) нужно вписать contact_groups:

define host{
       use                     my-linux-server
       host_name               www-srv
       contact_groups          www-admins
....

По умолчанию проверка хоста идет по icmp (по ping), если у вас на хосте закрыт ping (firewall-ом например), то nagios будет показывать, что host down. Для изменения типа проверки в хосте следует указать параметр check_command. Вот пример для проверки по http:

define host{
       use                     my-linux-server
       host_name               web-srv
       contact_groups          www-admins
       check_command           check_http
...

Сервис

Чтобы ходили уведомления от сервиса - надо в самом сервисе (или в его шаблоне) так же вписать группу контактов:

define service {
       use                             local-service
       name                            snmp-lavr
       service_description             Load Average
       contact_groups                  www-admins
....

Команды

Jabber

В рассмотренном выше примере идет уведомление nagios на jabber. В стандатрной поставке такого скрипта нет, по этому расскажу как это сделать. Скачиваем сам скрипт тут:

http://nagios.sourceforge.net/download/contrib/notifications/notify_via_jabber

Для gmail аккаунтов хороший скрипт:

http://www.gridpp.ac.uk/wiki/Nagios_jabber_notification

(только надо заменить tls на ssl и порт на 5223)

и кладем его в /usr/lib/nagios/plugins, ставим на него права запуска

chmod +x notify_via_jabber

редактируем, выставляя логин, пароль от которогу будут идти уведомления.

* Внимание! Необходимо предварительно зарегистрировать этот адрес, и желательно добавить этого пользователя в свои ростеры.

ставим CPAN модуль для работы Perl с джаббер:

emerge Net-Jabber

Описываем командуы:

# ---- NOTIFY ---
# 'host-notify-by-jabber' command definition
define command{
       command_name    host-notify-by-jabber
       command_line    $USER1$/notify_via_jabber $CONTACTPAGER$ "Host '$HOSTALIAS$' is $HOSTSTATE$ - Info: $HOSTOUTPUT$"
}
# 'notify-by-jabber' command definition
define command{
       command_name    notify-by-jabber
       command_line    $USER1$/notify_via_jabber $CONTACTPAGER$ "$NOTIFICATIONTYPE$ $HOSTNAME$ $SERVICEDESC$  $SERVICESTATE$ $SERVICEOUTPUT$ $LONGDATETIME$"
}

SMS

Уведомлять по SMS тоже можно несколькими способами. Можно подключить модем, а вот пример через сервис smstraffic:

vim /usr/lib/nagios/plugins/notify_via_sms
#/bin/bash
LOG="/tmp/sms.log"
tel="$1"
msg="$2"
form="0"

login="mylogin"
pass="mypassword"

orig="Nagios"
msg_cx=`echo $msg|wc -c`
if [ $msg_cx -gt 128 ]; then
       echo "Message is too long"
       exit 2
fi
dat=$(date +"%Y-%m-%d %H:%M:59")
host="http://smsmail.ru/corp/multi.php"
curl -F "login=$login" -F "password=$pass" -F "originator=$orig" -F "phones=$tel" -F "message=$msg" -F "start_date=$dat" -F "rus=$form" $host > $LOG 2> $LOG

Описываем команду:

define command{
       command_name    host-notify-by-sms
       command_line    $USER1$/notify_via_sms $CONTACTADDRESS1$ "'$HOSTALIAS$' is $HOSTSTATE$ - $HOSTOUTPUT$"
}

Добавляем вызов команды оповещения к примеру в шаблоне контакта:

define contact {
       use     generic-contact
       name    my-contact
       host_notification_commands      notify-host-by-email,host-notify-by-jabber,host-notify-by-sms
       service_notification_commands   notify-by-jabber
       service_notification_options    w,c
       register                        0
}

Карта

Чтобы увидеть пользовательскую карту, необходимо в меню выбрать Map -> User-supplied coords -> Update. Но перед этим эти координаты надо задать. Я для карты завел отдельный файл, чтобы все координаты были в нем. Описываются они в hostextinfo параметры:

* icon_image - имя иконки, отображаемой рядом с хостом и во всплывающих подсказках. Иконки находятся тут: /usr/share/nagios/htdocs/images/logos/
* statusmap_image - имя иконки, которая будет отображена на карте
* 2d_coords - координаты x,y - от левой верхней точки.

Вот пример моего файла:

# Шаблон по умолчанию 
define hostextinfo {
       name            my-he
       register        0
       icon_image      gentoo.png
       statusmap_image gentoo.gd2
}

define hostextinfo{
       use             my-he
       host_name       www-vm
       2d_coords       50,100
}
define hostextinfo{
       use             my-he
       host_name       www-svn
       2d_coords       150,100
}
define hostextinfo{
       use             my-he
       host_name       www-srv
       2d_coords       250,100
...
define hostextinfo{
       use             my-he
       host_name       my-router
       2d_coords       200,200
}
...
define hostextinfo{
       use             my-he
       host_name       my-other
       icon_image      suse.jpg
       statusmap_image suse.jpg
       2d_coords       200,400
}

Примеры

На закуску вот еще шаблоны для некоторых встроенных и плагинов с http://nagios.manubulon.com/

Команды

# load average
define command {
       command_name    check_snmp_load
       command_line    $USER1$/check_snmp_load.pl -H $HOSTADDRESS$ -C $ARG1$ -w $ARG2$ -c $ARG3$ -T netsl -f
}
# process count
define command {
       command_name    check_snmp_process
       command_line    $USER1$/check_snmp_process.pl -H $HOSTADDRESS$ -C $ARG1$ -F -w $ARG2$ -c $ARG3$ -n $ARG4$
}
# interface statistic
define command {
       command_name    check_snmp_int
       command_line    $USER1$/check_snmp_int.pl -H $HOSTADDRESS$ -C $ARG1$ -n $ARG2$ -f -q
}

Сервисы

# Ping
define service{
       use                             local-service
       name                            ping
       service_description             PING
       _WARNING                        200.0,20%
       _CRITICAL                       500.0,60%
       check_command                   check_ping!$_SERVICEWARNING!$_SERVICECRITICAL
       register                        0
       }
# SSH
define service{
       use                             local-service
       name                            ssh
       service_description             SSH
       check_command                   check_ssh
       register                        0
}
# load average
define service {
       use                             local-service
       name                            snmp-lavr
       service_description             Load Average
       _WARNING                        3,3,2
       _CRITICAL                       4,4,5
       check_command                   check_snmp_load!$_HOSTCOMMUNITY$!$_SERVICEWARNING!$_SERVICECRITICAL
       register                        0
}
# process count
define service {
       use                             local-service
       name                            snmp-process
       service_description             Processes
       _WARNING                        3,8
       _CRITICAL                       0,20
       _PROCESS                        postmaster
       check_command                    check_snmp_process!$_HOSTCOMMUNITY$!$_SERVICEWARNING$!$_SERVICECRITICAL!$_SERVICEPROCESS
       register                        0
}
# http availability
define service {
       use                             local-service
       name                            http
       service_description             HTTP
       check_command                   check_http
       register                        0
}
# interface traffice
define service {
       use                             local-service
       name                            traffic
       service_description             Traffic
       _INTERFACE                      eth0
       check_command                   check_snmp_int!$_HOSTCOMMUNITY$!$_SERVICEINTERFACE!
}

Хост

Их использование в хосте будет примерно таким:

define host{
       use                     my-linux-server
       host_name               www
       address                 192.168.0.52
}

define service {
       use                             ping
       host_name                       www
}
define service {
       use                             ssh
       host_name                       www
}
define service {
       use                             snmp-lavr
       host_name                       www
}
define service {
       use                             swap
       host_name                       www
}
define service {
       use                             traffic
       _INTERFACE                      eth1
       host_name                       www
}

Удобно не правда-ли?

Графики

Вот мои шаблоны графиков:

  • Load average
/usr/share/pnp/templates/check_snmp_load.php 
<?php
require_once ("/usr/share/pnp/my/_my.php");
$opt[1] = m_base();
$opt[1] .= m_title();
$def[1] =  "DEF:var1=$rrdfile:$DS[1]:AVERAGE " ;
$def[1] .= "DEF:var2=$rrdfile:$DS[2]:AVERAGE " ;
$def[1] .= "DEF:var3=$rrdfile:$DS[3]:AVERAGE " ;
$def[1] .= "HRULE:$WARN[1]#FFFF00 ";
$def[1] .= "HRULE:$CRIT[1]#FF0000 ";
$def[1] .= "AREA:var3#FF0000:\"Load 15\" " ;
$def[1] .= "GPRINT:var3:LAST:\"%6.2lf last\" " ;
$def[1] .= "GPRINT:var3:AVERAGE:\"%6.2lf avg\" " ;
$def[1] .= "GPRINT:var3:MAX:\"%6.2lf max\\n\" " ;
$def[1] .= "AREA:var2#EA8F00:\"Load 5 \" " ;
$def[1] .= "GPRINT:var2:LAST:\"%6.2lf last\" " ;
$def[1] .= "GPRINT:var2:AVERAGE:\"%6.2lf avg\" " ;
$def[1] .= "GPRINT:var2:MAX:\"%6.2lf max\\n\" " ;
$def[1] .= "AREA:var1#EACC00:\"load 1 \" " ;
$def[1] .= "LINE1:var1#000000FF: ";
$def[1] .= "GPRINT:var1:LAST:\"%6.2lf last\" " ;
$def[1] .= "GPRINT:var1:AVERAGE:\"%6.2lf avg\" " ;
$def[1] .= "GPRINT:var1:MAX:\"%6.2lf max\\n\" ";
?>
  • Traffic
/usr/share/pnp/templates/check_snmp_int.php                                                              
<?php
require_once ("/usr/share/pnp/my/_my.php");
$opt[1] = m_base();
$opt[1] .= m_title("Interface Traffic for");
$opt[1] .= m_vlabel("Traffic");
$opt[1] .= "-b 1024 ";
$def[1] .= "DEF:a=$rrdfile:$DS[1]:AVERAGE ";
$def[1] .= "DEF:b=$rrdfile:$DS[1]:MAX ";
$def[1] .= "DEF:c=$rrdfile:$DS[2]:AVERAGE ";
$def[1] .= "DEF:d=$rrdfile:$DS[2]:MAX ";
$def[1] .= "CDEF:cdefa=TIME,$NAGIOS_EVENTSTARTTIME,GT,a,a,UN,0,a,IF,IF,TIME,$NAGIOS_EVENTSTARTTIME,GT,c,c,UN,0,c,IF,IF,+ ";
$def[1] .= "AREA:a#96E78AFF:\"Inbound\" ";
$def[1] .= "GPRINT:a:LAST:\"Current\:%6.2lf %s\" ";
$def[1] .= "GPRINT:a:AVERAGE:\"Average\:%6.2lf %s\" ";
$def[1] .= "GPRINT:b:MAX:\"Maximum\:%6.2lf %s\\n\" ";
$def[1] .= "COMMENT:\"Total In\:  0 bytes\\n\" ";
$def[1] .= "AREA:c#FFC73BFF:Outbound ";
$def[1] .= "GPRINT:c:LAST:\"Current\:%6.2lf %s\" ";
$def[1] .= "GPRINT:c:AVERAGE:\"Average\:%6.2lf %s\" ";
$def[1] .= "GPRINT:d:MAX:\"Maximum\:%6.2lf %s\" ";
$def[1] .= "COMMENT:\"Total Out\: 0 bytes\" ";
$def[1] .= "LINE1:c#2175D9FF: ";
$def[1] .= "LINE1:a#2175D9FF: ";
$def[1] .= "GPRINT:cdefa:LAST:\"Summ\:%6.2lf %s\" ";
$def[1] .= "LINE1:cdefa#000000FF: ";
?>
  • Storage
/usr/share/pnp/templates/check_snmp_storage.php                                                          
<?php
require_once ("/usr/share/pnp/my/_my.php");
$opt[1] = m_base ();
$opt[1] .= m_title ();
$opt[1] .= m_vlabel ("MB");
$def[1] = "DEF:var1=$rrdfile:$DS[1]:AVERAGE ";
$def[1] .= "AREA:$MAX[1]#002A97: ";
$def[1] .= "AREA:var1#FF0000: ";
$def[1] .= "HRULE:$MAX[1]#003300:\"Size $MAX[1] MB\" ";
$def[1] .= "HRULE:$WARN[1]#ffff00:\"Warning on $WARN[1] MB \" ";
$def[1] .= "HRULE:$CRIT[1]#ff0000:\"Critical on $CRIT[1] MB \\n\" ";
$def[1] .= "GPRINT:var1:LAST:\"%8.2lf MB of $MAX[1] MB used \\n\" ";
$def[1] .= "GPRINT:var1:MAX:\"%8.2lf MB max used \\n\" ";
$def[1] .= "GPRINT:var1:AVERAGE:\"%8.2lf MB avg used\" ";
?>
  • общий файл
/usr/share/pnp/my/_my.php                                                                                
<?php
function m_base () {
$res = "--imgformat=PNG ";
$res .= "--rigid ";
$res .= "--base=1000 ";
$res .= "--height=120 ";
$res .= "--width=500 ";
$res .= "--alt-autoscale-max ";
$res .= "--lower-limit=0 ";
$res .= "--slope-mode ";
$res .= "--font TITLE:12: ";
$res .= "--font AXIS:8: ";
$res .= "--font LEGEND:10: ";
$res .= "--font UNIT:8: ";
return $res;
}
function m_title($text) {
       global $hostname, $servicedesc;
 return "--title=\"$text $hostname - $servicedesc\" ";
}
function m_vlabel($text) {
 return "--vertical-label=\"$text\" ";
}
?>

Добавление градиента

Очень симпатично смотрятся графики с градиентом (см. графики PING). Для этого в шаблон по умолчанию

vim /usr/share/pnp/templates.dist/default.php

вносим изменения:

#define("_AREA", '#EACC00');
define("_AREA", '#EA7400');
...
$def[$i] .= "AREA:var1" . _AREA . ":\"$NAME[$i] \" ";
// gradient
       $def[$i] .=  "CDEF:sp1=var1,100,/,12,* " ;
       $def[$i] .=  "CDEF:sp2=var1,100,/,30,* " ;
       $def[$i] .=  "CDEF:sp3=var1,100,/,50,* " ;
       $def[$i] .=  "CDEF:sp4=var1,100,/,70,* " ;
       $def[$i] .= "AREA:sp4#EA8A00: " ;
       $def[$i] .= "AREA:sp3#EAB000: " ;
       $def[$i] .= "AREA:sp2#EACC00: " ;
       $def[$i] .= "AREA:sp1#E2EA00: " ;
//
$def[$i] .= "LINE1:var1" . _LINE . ":\"\" ";

Мониторинг через SSH

Частным случаем мониторинга может служить мониторинг через SSH. Обычно применяется, когда на сервере нет возможности поставить или открыть SNMP.

Так же подходит для случая, когда сервера находятся за DMZ, и их можно мониторить только через шлюз по SSH.

Для этого используется плагин check_by_ssh, который авторизуется на сервере по SSH и выполняет там команду. Для простоты будем сервер мониторинга с Nagios называть просто сервер (server), а клиентские машины, которые необходимо мониторить - клиент (client).


Авторизация

Сервер должен авторизоваться на клиенте по ключу. Для этого генерируем пару ключей RSA на сервере, и выкладываем окрытый ключ на клиента:
server# sudo su - nagios
nagios@server$ mkdir .ssh
nagios@server$ chmod 700 .ssh
nagios@server$ ssh-keygen -t rsa
nagios@server$ scp .ssh/id_rsa.pub user@client.ip:/home/user

На клиенте создаем пользователя, от которого будут исполняться скрипты мониторинга и помещаем только что созданный публичный ключ, как ключ для авторизации:

client# useradd -c Nagios.Monitoring.By.SSH -m nagios
client# mkdir /home/nagios/.ssh
client# mv /home/user/id_rsa.pub /home/nagios/.ssh/authorized_keys
client# chown -R nagios:users /home/nagios/.ssh/
client# chmod 700 /home/nagios/.ssh/
client# chmod 600 /home/nagios/.ssh/authorized_keys

Проверяем коннект с сервера по ключу с сервера:

nagios@server$ ssh -v nagios@client.ip

Должно законнектиться без запроса пароля.

Плагины

Проверки будут выполняться путем исполнения плагинов nagios на клиенте. Для этого их надо перелить с сервера на клиента:

nagios@server$ scp /usr/lib/nagios/plugins/* nagios@client.ip:/home/nagios/

Проверяем с сервера:

nagios@server$ ssh nagios@client.ip "/home/nagios/check_load -w 1,1,1 -c 3,3,3"

Должен выдать загрузку клиента:

OK - load average: 0.01, 0.04, 0.11|load1=0.010;1.000;3.000;0; load5=0.040;1.000;3.000;0; load15=0.110;1.000;3.000;0; 

Теперь тоже самое через плагин:

/usr/lib/nagios/plugins/check_by_ssh -H tzselektra.ru -C "/home/nagios/check_load -w 1,1,1 -c 3,3,3"

получаем:

OK - load average: 0.06, 0.05, 0.10|load1=0.060;1.000;3.000;0; load5=0.050;1.000;3.000;0; load15=0.100;1.000;3.000;0;

Работает.

Команда

Теперь мы можем описать команду опроса через ssh:

define command {
       command_name    check_ssh_load
       command_line    $USER1$/check_by_ssh -H $HOSTADDRESS$ -C "/home/hagios/check_load -w $ARG1$ -c $ARG2$"
}

Сервис

и соответствующий ей сервис:

define service {
       use                             local-service           ; check current load on machine
       service_description             Current Load
       check_command                   check_ssh_load!1,1,1!2,2,2
}


Все. Можно добавлять сервис в хосты (см. описание выше).

DMZ

Что делать если сервер находится за DMZ? Делаем все тоже, что и выше, только появляется сервер, который виден только за клиентом, назовем его client2.

Авторизация

Разрешим клиенту, на котором уже может авторизоваться наш сервер - авторизовываться на client2. Для этого так же генерируем пару ключей и переливаем публичный ключ на client2

 client# sudo su - nagios
 nagios@client$ ssh-keygen -t rsa
 nagios@client$ scp .ssh/id_rsa.pub user@client2:/home/user/

далее уже на client2 (на который мы можем зайти только с client) - создаем пользователя nagios и отдаем ему этот ключ:

client2# useradd -c Nagios.Monitoring.By.SSH -m nagios
client2# mkdir /home/nagios/.ssh
client2# mv /home/user/id_rsa.pub /home/nagios/.ssh/authorized_keys
client2# chown -R nagios:users /home/nagios/.ssh/
client2# chmod 700 /home/nagios/.ssh/
client2# chmod 600 /home/nagios/.ssh/authorized_keys

Пробуем залогиниться по ключу с client на client2:

nagios@client$ ssh client2

должно залогиниться без запроса пароля:

nagios@client$ ssh client2
nagios@client2$ 
nagios@client2$ exit
nagios@client$


Плагины

Заливаем плагины на client2:

nagios@client$ scp /home/nagios/check* client2:/home/nagios/

Проверяем с клиента:

nagios@server$ ssh nagios@client.ip "/home/nagios/check_load -w 1,1,1 -c 3,3,3"

Должно ответить:

WARNING - load average: 1.25, 1.90, 2.47|load1=1.250;1.000;3.000;0; load5=1.900;1.000;3.000;0; load15=2.470;1.000;3.000;0;

А теперь фокус! Проверяем с сервера через 2 ssh да еще и через плагин! Сразу client2, которого напрямую не видно с сервера:

nagios@server$ /usr/lib/nagios/plugins/check_by_ssh -H client.ip -C "ssh client2 /home/nagios/check_load -w 1,1,1 -c 3,3,3"

Отвечает:

WARNING - load average: 1.60, 1.88, 2.38|load1=1.600;1.000;3.000;0; load5=1.880;1.000;3.000;0; load15=2.380;1.000;3.000;0;

Если все ок - можно добавлять остальных клиентов, находящихся за client.ip.

Команда

Создаем команды, для опроса серверов за DMZ.

define command {
       command_name    check_dmz_load
       command_line    $USER1$/check_by_ssh -H $ARG1$ -C "ssh $HOSTADDRESS$ /home/nagios/check_load -w $ARG2$ -c $ARG3$"
}

Тут мы указываем первым параметром наш client, а уже на нем выполняем команду ssh с указанием адреса client2 и запуска уже на client2 скрипта check_load.

define command {
       command_name    check_dmz_ssh
       command_line    $USER1$/check_by_ssh -H $ARG1$ -C "/home/nagios/check_ssh $HOSTADDRESS$"
}

А тут мы просто проверяем доступность ssh на client2 с client

Сервис

И описываем сервис:

define service {
       use                             local-service
       name                            dmz-lavr
       service_description             Load Average
       _WARNING                        3,3,2
       _CRITICAL                       4,4,5
       check_command                   check_dmz_load!$_HOSTDMZ$!$_SERVICEWARNING!$_SERVICECRITICAL
       register                        0
}

Ну и для check_dmz_ssh:

define service {                        
        use                            local-service
        name                            dmz-ssh
        service_description             SSH
        check_command                   check_dmz_ssh!$_HOSTDMZ$ 
        register                        0
}

Хост

Регистрируем сам хост client2:

define host{
       use                     linux-server
       host_name               my-client2        # просто имя, которое будет видно в nagios
       _DMZ                    client.ip         # адрес клиента, доступного с сервера сбора (за которым находится client2),
                                                 # так называемый пограничный сервер DMZ
       address                 client2           # адрес client2, видный только из client
       check_command           check_dmz_ssh!client.ip     # проверяем хост по доступности по ssh с client
}

# Load Average 
define service {
       use                             dmz-lavr    # а это наш сервис
       host_name                       my-client2
}
# SSH
define service {
       use                             dmz-ssh
       host_name                       my-client2
}


Пассивные проверки

Возможность nagios-а не инициировать проверку данных, а просто получать их от клиента (инициируется на стороне клиента) называется passive check.

Пассивные проверки делаются через дополнительный модуль: NSCA (Nagios Service Check Acceptor).

Сервер слушает - клиент когда надо отсылает.


Сервер

В nagios.cfg проверяем стоят ли параметры

 "check_external_commands=1";
 "accept_passive_service_checks=1";


ПО

ставим на сервере NSCA с суперсервером к нему:

emerge net-analyzer/nagios-nsca xinetd


Убедимся, что в файле /etc/nagios/nagios.cfg есть строка:

command_file=/var/nagios/rw/nagios.cmd

Также эта строка должна быть в /etc/nagios/nsca.conf в этом же файле можно установить метод шифрования и пароль (должны совпадать с клиентом).

Настраиваем xinetd. Для этого создаем файл с описанием сервиса NSCA:

cat > /etc/xinetd.d/nsca <<EOF
service nsca
{
 flags           = REUSE
 type = UNLISTED
 port = 5667
 socket_type     = stream
 wait            = no

 server          = /usr/bin/nsca
 server_args     = -c /etc/nagios/nsca.cfg --inetd
 user            = nagios
 group           = nagios

 log_on_failure  += USERID

 disable         = no
}
EOF
echo "nsca   5667/tcp" >> /etc/services
echo "nsca   5667/udp" >> /etc/services

/etc/init.d/xinetd start
rc-update add xinetd default
netstat -alnp | grep xinet

Настройки

в my_commands.cfg добавляем пустую команду

# dummy command for passive service
define command{
           command_name check_dummy
           command_line $USER1$/check_dummy $ARG1$
  }

в my_templates описываем пассивный сервис

# passive service
define service {
       use                             my-local-service
       name                            passive-service
       active_checks_enabled           0
       passive_checks_enabled          1
       max_check_attempts              1
       check_command                   check_dummy!0
       register                        0
}

Теперь можно хосту добавить сервис на базе этого шаблона такого типа:

define service {
       use                             passive-service
       service_description             test-passive
       host_name                       my-dev
}


Клиент

На клиенте ставим nsca клиент:

emerge net-analyzer/nagios-nsca

Теперь можно проверить правильно ли работает сервис, отправив ему сообщение через send_nsca в таком формате:

<hostname>[tab]<service_name>[tab]<return_code>[tab]<output>[\n]

Пример:

printf "%s\t%s\t%d\t%s\n" "my-dev" "test-passive" 0 "All Ok" | /usr/lib/nagios/plugins/send_nsca -H mon.lan -c /etc/nagios/send_nsca.cfg
  •  ! Обязательно добавить пользователя, от которого будет рассылаться - в группу nagios !

Скрипт

Скрипт как понятно из определения сервиса - будет выполняться на клиенте к примеру по крону, и отправлять данные по необходимости. Вот пример:

NSCA_SERVER=mon.lan
NSCA_SERVICE="Postgres Connect Error"
NSCA_HOST="my-dev"
if [ ! -z "$1" ]; then
       NSCA_HOST="$1"
fi

function nsca () {
printf "%s\t%s\t%d\t%s\n" "$NSCA_HOST" "$NSCA_SERVICE" "$ERROR" "$MSG" | /usr/lib/nagios/plugins/send_nsca -H $NSCA_SERVER -c /etc/nagios/send1
}

...
# warning here
MSG="WARNING: Try $COUNT times | res=$RES count=$COUNT"
ERROR=1
nsca
echo $MSG
exit $ERROR

...
# error here
MSG="CRITICAL: Try $COUNT times | res=$RES count=$COUNT"
ERROR=2
nsca 
echo $MSG
exit $ERROR

Ссылки

Личные инструменты