Показаны сообщения с ярлыком Fedora 21. Показать все сообщения
Показаны сообщения с ярлыком Fedora 21. Показать все сообщения

пятница, 30 октября 2015 г.

Пишем свои плагины

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

Я использую самописные плагины по следующим причинам:
- возможность логирования не только конечных данных, но и промежуточных, что возможно потребуется при разборе полётов некой ситуации;
- русификация текста сообщений выдаваемых плагином, т.к. не всегда персонал, получающий сообщения об изменении статуса объектов мониторинга, умеет читать буржуйские словечки, а некоторые лучше бы и не пытались читать;
- использование протокола SNMP для снятия данных, т.к. в реальной жизни существует много ограничений, например, бывают случаи, что не на все сервера можно ставить стороннее ПО, а SNMP есть почти везде и всегда это штатное исполнение;
- и, пожалуй, самая основная причины -- отсутствие нужных плагинов.

#!/bin/bash
# Супер плагин
# v.01a
/usr/bin/echo "Всё хорошо, прекрасная маркиза"
exit 0


Вот так выглядит вполне рабочий плагин. Система мониторинга может с ним работать, т.к. присутствует выводимый текст и код завершения.

Примерно становится понятно, что реальный плагин будет содержать в себе некие действия для определения параметров объекта мониторинга и вычисления его статуса, от которого будет зависеть код выполнения плагина.

Рассмотрим пример плагина, в котором определяется состояние сервиса на линуксовом сервере по протоколу SNMP.

#!/bin/bash
# Снимаем данные с серверов с ОС Linux по SNMP
# v.01
PATH_CONF="/usr/local/libexec/icinga2/my_libexec"
. $PATH_CONF/_exit_codes
. $PATH_CONF/_commands
. $PATH_CONF/_functions
. $PATH_CONF/_conf_def
case "$FUNCTION" in
        "proc"          )       ID_RAW=`$snmpwalkcmd -Oqs -c blablabla -v 1 $HOSTNAME prNames 2>>$LOG_FILE`
                                if [ $? = 0 ]
                                        then
                                                ID=`$echocmd "$ID_RAW" | $grepcmd "$ARG1" | $awkcmd '{print $1}' | $trcmd -d 'prNames.'`
                                                if [ -z $ID ]
                                                        then
                                                                MSG="ID процесса не определён"
                                                        else
                                                                CHECK_ERROR=`$snmpwalkcmd -Oqv -c
blablabla -v 1 $HOSTNAME prErrorFlag.$ID 2>>$LOG_FILE`
                                                                if [ $? = 0 ]
                                                                        then
                                                                                case "$CHECK_ERROR" in
                                                                                        "noError"       )       MSG="В работе"
                                                                                                                EXIT_CODE=$OK ;;
                                                                                        "error"         )       MSG="Служба остановлена"
                                                                                                                EXIT_CODE=$CRITICAL ;;
                                                                                        *               )       MSG="НЕИЗВЕСТНО"
                                                                                                                EXIT_CODE=$UNKNOWN ;;
                                                                                esac
                                                                        else
                                                                                MSG="$MSG_TIMEOUT"
                                                                fi
                                                fi
                                        else
                                                MSG="$MSG_TIMEOUT"
                                fi
                                $printfcmd "%b" "$DATE\nService: $ARG1\nID=$ID\nCHECK_ERROR: $CHECK_ERROR\n$MSG\n\n" >> $LOG_FILE

                        ;;
 ...
         *               )       exit $UNKNOWN
                                 $echocmd "Функция не определена" ;;
esac

$echocmd $MSG
exit $EXIT_CODE


где:
# cat _exit_codes
OK=0
WARNING=1
CRITICAL=2
UNKNOWN=3


# cat _conf_def
HOSTNAME=$1
FUNCTION=$2
ARG1=$3
ARG2=$4

......
LOG_FILE="/var/log/icinga2/snmp_logs/$HOSTNAME.$FUNCTION"
EXIT_CODE=$CRITICAL
MSG_TIMEOUT="Узел $HOSTNAME не ответил за максимально допустимое время"

.....

# cat _commands
echocmd="/usr/bin/echo"
awkcmd="/usr/bin/awk"
cutcmd="/usr/bin/cut"
bccmd="/usr/bin/bc"
grepcmd="/bin/grep"
snmpwalkcmd="/usr/bin/snmpwalk"
trcmd="/usr/bin/tr"
printfcmd="/usr/bin/printf"
wccmd="/usr/bin/wc"
smbclientcmd="/usr/bin/smbclient"
lscmd="/usr/bin/ls"

....

В первом файле (_exit_codes) определены коды выходов, чтобы удобнее и понятнее было их использовать. Во втором файле (_conf_def) аргументы передаваемые плагину, а в третьем (_commands) определены пути к исполняемым файлам, удобно при переносе на другую систему.

Запустить и проверить работоспособность плагина можно так:
$ ./check_snmp_linux server.local proc service_name
В работе
$ echo $?
0


Также к выводимому тексту можно добавить через трубу "|" дополнительные данные, так называемые "Performance Data", которые можно будет использовать для построения графиков числовых состояний объектов мониторинга, например:
$ ./check_snmp_linux server.local disk /dev/sda7 90 95
Используется 500.3 Гбайт (80%) из 656.6 Гбайт|disk=80%;9
0;95;0;100


или так:
$ ./check_snmp_linux server.local load 70 70 70 90 90 90
Средняя загрузка: 0.00, 0.00, 0.00, | 1min=0.00;70;90;0;100 5min=0.00;70;90;0;100 15min=0.00;70;90;0;100


С Performance Data попробуем разобраться попозже.

Итак, написать свой плагин не так уж и сложно, делать это можно на любом языке, никаких ограничений нет. Может быть использована любая цепочка обработки и переброски данных.
Например, есть группа серверов которая по мультикасту обменивается о своих ролях, нам необходимо знать текущие роли и во время узнавать о смене ролей.
Для этого нам нужно подписаться на мультикаст, можно использовать Twisted.
Пакеты с информацией о ролях серверов получили, теперь определим значения ролей, используя любой сетвой анализатор, для нашей цели может подойти NGREP, вывод которого можно разобрать своим парсером.
Осталось подсунуть конечные данные системе мониторинга, для этого существует множество вариантов от взятия из файла текущей роли до передачи через пассивные проверки, также предыдущий пункт мог быть выполнен как активная проверка (плагин для icinga2).
Также можно отправить дополнительное уведомление для не очень квалифицированного персонала, в котором будет подробное описание произошедшего, сделать это можно как и через систему мониторинга, так и без её использования.

вторник, 31 марта 2015 г.

Установка Icinga2 и Icinga Web 2

После затянувшейся паузы продолжим создавать систему мониторинга на базе Icinga2, некий костяк уже создан, теперь самое время установить саму айсингу. Сперва устанавливать будем на Fedora 21, на тестовый сервер и через некоторое время установим на основной сервер с CentOS.

Наверно, имеет смысл описать планируемый состав серверов. И так будет два сервера с идентичными настройками:
- основной боевой на CentOS и с этого сервера будет идти рассылка уведомлений дежурному персоналу (у меня есть такой персонал;);
- резервный тестовый сервер на Fedora 21, настроенный идентично за исключением рассылки уведомлений дежурному персоналу, уведомления будут слаться только администратору системы мониторинга для контроля адекватности работы и отлавливания ложных срабатываний (хотя избыточность уведомлений для дежурного персонала тоже не помешала бы, но это политическое решение).

На тестовом сервере будут тестироваться нововведения как и в самой айсинге, так и при добавлении новых объектов мониторинга и отлавливания всевозможных багов. Возможно количество основных серверов вырастет в зависимости от того как покажет себя кластерные фичи Icinga2.

В официальной документации установка описана подробно (только по каким то причинам пропущена установка из исходников), просто пробежимся по этому этапу:

Указываем прокси:
# export http_proxy=http://10.10.10.10:8080

Добавляем репозитарий с пакетами Icinga2:
# rpm --import http://packages.icinga.org/icinga.key
curl -o /etc/yum.repos.d/ICINGA-release.repo http://packages.icinga.org/fedora/ICINGA-release.repo
# yum makecache

Ставим пакеты, включаем и запускаем:

# yum install icinga2
# systemctl enable icinga2
# systemctl start icinga2


Теперь в айсинге имеется механизм подключения фич, посмотрим список выключенных и включеных фич:
# icinga2 feature list
Disabled features: api command compatlog debuglog gelf graphite icingastatus livestatus opentsdb perfdata statusdata syslog
Enabled features: checker mainlog notification


На данный момент включены:
checker -- выполнение проверок;
mainlog -- писать логи в icinga2.log;
notification -- рассылка уведомлений.

Включение и выключение фич будет подробнее описано здесь (TODO).

По умолчанию Icinga2 использует следующие файлы и каталоги:
/etc/icinga2                содержит конфигурационные файлы;
/etc/init.d/icinga2         стартовый скрипт;
/usr/sbin/icinga2           бинарники;
/usr/share/doc/icinga2      документация;
/usr/share/icinga2/include  конфигурации шаблонов и плагинов;
/var/run/icinga2            файл PID;
/var/run/icinga2/cmd        командный канал и сокет живого статуса;
/var/cache/icinga2          файлы status.dat/objects.cache, icinga2.debug;
/var/spool/icinga2          используется для фалов очереди обработки;
/var/lib/icinga2            файл состояния Icinga 2, кластерный лог, локальный удостоверяющий центр (CA) с конфигурационными файлами;
/var/log/icinga2            логи и директория compat для фичи CompatLogger;

Для выполнения проверок параметров объектов мониторинга потребуются так называемые плагины, по сути это скрипты или бинарники, которые выполняют некую проверку и в зависимости от полученного результата завершают своё выполнение с определенным кодом выхода. Позже мы научимся писать плагины сами (TODO), а теперь установим набор плагинов, который предоставляет The Monitoring Plugins Project, частью которых мы воспользуемся.

Установить этот набор плагинов можно из EPEL, как и указано в документации, мы же будем устанавливать из исходников:

# wget https://www.monitoring-plugins.org/download/monitoring-plugins-2.1.1.tar.gz
# tar zxvf monitoring-plugins-2.1.1.tar.gz
# cd monitoring-plugins-2.1.1/
# yum install gcc
# ./configure

На этом этапе могут появиться предупреждения о нехватке неких пакетов и информация о том, что некие плагины не будут собраны. Можно не заморачиваться сейчас об этом, самые необходимые плагины соберутся, остальные же можно будет дособирать по необходимости, поэтому:

# make
# cd plugins
# mkdir /usr/local/libexec/icinga2
# cp check_disk /usr/local/libexec/icinga2/
# cp check_http /usr/local/libexec/icinga2/
# cp check_load /usr/local/libexec/icinga2/
# cp check_ping /usr/local/libexec/icinga2/
# cp check_procs /usr/local/libexec/icinga2/
# cp check_ssh /usr/local/libexec/icinga2/
# cp check_swap /usr/local/libexec/icinga2/
# cp check_users /usr/local/libexec/icinga2/

здесь мы создали каталог для плагинов и скопировали в него некоторые плагины, которые используются в дефолтной конфигурации для мониторинга хоста на который мы установили Icinga2.
И сразу же внесём этот каталог в константы:

# grep "const PluginDir" /etc/icinga2/constants.conf
const PluginDir = "/usr/local/libexec/icinga2"


Перечитаем конфиги:
# systemctl reload icinga2

Для начальной установки и конфигурации плагинов этих действий достаточно.

Кратко о командах которые поддерживает systemctl в отношении Icinga2:
start -- стартует демон Icinga2;
stop -- останавливает демона;
restart -- перезапуск, по факту выполняется команда stop с последующей командой start;
reload -- перезагрузка, посылается сигнал HUP, который вызывает перезапуск. Не равноценна команде restart, т.к. перезагрузка не дожидается пока Icinga2 перезапустится;
status -- проверяет статус;
enable -- включает (disable - выключает) сервис как загрузочный при старте системы (подобно chkconfig).

В официальной документации на этом месте настройка подсветки синтаксиса конфигурационных файлов в паре редакторов. Настроим подсветку в vim:

# PREFIX=~/.vim
# mkdir -p $PREFIX/{syntax,ftdetect}
# cp /usr/share/doc/icinga2-common/syntax/vim/syntax/icinga2.vim $PREFIX/syntax/
# cp /usr/share/doc/icinga2-common/syntax/vim/ftdetect/icinga2.vim $PREFIX/ftdetect/

эти действия необходимо делать под тем пользователем, под которым будет происходить редактирование конфигурационных файлов.

Быстро проверить подсветку можно так:
# vim /etc/icinga2/conf.d/templates.conf

Теперь установим веб-интерфейс Icinga Web 2, для этого добавим поддержу PostgreSQL, т.к. будем использовать его и он у нас уже установлен (если есть желание использовать MySQL, то процесс установки этой поддержи так же описан в документации):
# yum install icinga2-ido-pgsql

Создаем пользователя и базу:
# cd /tmp
# sudo -u postgres psql -c "CREATE ROLE icinga WITH LOGIN PASSWORD 'icinga'";
# sudo -u postgres createdb -O icinga -E UTF8 icinga
# sudo -u postgres createlang plpgsql icinga


пароль конечно же можно изменить, но не забывать и далее его использовать, т.к. в примерных настройках будет использован пароль 'icinga'.

И настраиваем:
# vim /var/lib/pgsql/data/pg_hba.conf

# snmptt

local   snmptt      snmptt                            md5
# icinga
local   icinga      icinga                            md5
host    icinga      icinga      127.0.0.1/32          md5
host    icinga      icinga      ::1/128               md5

# "local" is for Unix domain socket connections only
local   all         all                              
md5
# IPv4 local connections:
host    all         all         127.0.0.1/32         
md5
# IPv6 local connections:
host    all         all         ::1/128              
md5

# systemctl restart postgresql


Заливаем схему:
# export PGPASSWORD=icinga
# psql -U icinga -d icinga < /usr/share/icinga2-ido-pgsql/schema/pgsql.sql


Проверяем включение фичи ido-pgsql:
# icinga2 feature list
Disabled features: api command compatlog debuglog gelf graphite icingastatus livestatus opentsdb perfdata statusdata syslog
Enabled features: checker ido-pgsql mainlog notification


Включаем фичу, в случае если она не включилась :
# icinga2 feature enable ido-pgsql
# systemctl restart icinga2

Для работы веб-интефейса  требуется веб-сервер, в нашем случае устанавливать его нет нужды, т.к. он у нас уже установлен.
Вместо настройки фаервола выключим его и SELinux:
# systemctl stop firewalld
# systemctl disable firewalld
# grep -v ^# /etc/sysconfig/selinux

SELINUX=disabled
SELINUXTYPE=targeted

# reboot

Веб-интерфейс и другие дополнения айсинги могут посылать команды демону айсинги через канал внешних команд. Для этого включим соответствующую фичу:

# icinga2 feature enable command
# # systemctl restart icinga2

Так же потребуется добавить в группу icingacmd пользователя под которым запущен веб-сервер, в нашем случае этот пользователь apache:
# usermod -a -G icingacmd apache
# id apache
uid=48(apache) gid=48(apache) groups=48(apache),986(icingacmd)

Теперь займемся установкой непосредственно самого веб-интерфейса. Устанавливать будем из пакета, этот процесс не описан в документации, разберёмся по ходу:
# yum install icingaweb2
# systemctl restart httpd

Запускаем браузер и идем по адресу: http://адрес_сервера/icingweb2
Дальнейшее повествование будет в картинках:


Выбираем использование "web-based setup-wizard".


Выполняем предлагаемые действия:
# grep icingaweb2 /etc/group
icingaweb2:x:985:apache
# yum install icingacli
# icingacli setup config directory --group icingaweb2;
Successfully created configuration directory /etc/icingaweb2
# icingacli setup token create;
The newly generated setup token is: blablablablabla1

Вводим сгенерированный установочный токен и жмём ''Next".

Предлагают сделать выбор из трех предложенных модулей. Модуль с документацией никогда не мешает, основной модуль "Monitoring" в нашей ситуации просто обязателен, необходимость модуля с переводом крайне мала. Ставим галку на первом модуле и двигаемся дальше.




 Для удовлетворения всех зависимостей произведем следующие действия:

1. Настроим временную зону в PHP, как это сделать описано здесь:

# grep ^date.timezone /etc/php.ini
date.timezone = "Asia/Yekaterinburg"


Имя своей зоны можно поискать здесь: /usr/share/zoneinfo/.

2. Ставим модуль поддержи LDAP для PHP, для включение доменной авторизации, авторизация через локальную базу у меня не заработала:


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

# yum install php-ldap
# systemctl restart httpd

И обновляем результаты тестирования зависимостей для этого жмём "Refresh".


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


Выбираем авторизацию LDAP, дальше.





Здесь можно выбрать типа хранилища настроек пользователя, стараемся как можно больше засунть в базу, поэтому выбираем тип Database, далее.


Настраиваем доступ к базе, далее.


Предлагают указать имя домена, для которого будут обнаружены сервера авторизации, можно и пропустить этот шаг, выставив галку в опции Skip. Мы укажем имя домена, далее.




Обнаруженные настройки необходимо поправить, в моём случае это адрес хоста, и дополнить это имя пользователя в формате "user@domain.org" и его пароль, далее.


Здесь необходимо указать как отлавливать пользователей для авторизации, подключаемся к конторолеру домена любым LDAP-браузером и выбираем удобный для себя вариант, я пока настроил так как на предыдущем скрине.

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


писываем себя и жмём "Next".


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





Мы успешно настроили Icinga Web 2. Прежде, чем двигаться дальше, предлагают проверить корректность настроенных опций, при необходимости можно вернуться к предыдущим шагам и исправить некие опции. У нас все верно, жмём "Next".


Приступаем к настройке модуля мониторинга, далее.


Оставляем предложенное заполнение полей, далее.


Настраиваем доступ для IDO к базе, далее.







Настройка командного файлы, мы выберем вариант с локальным командным файлом (так же есть возможность настройки удалённого командного файла, возможно при кластерной конфигурации этот вариант будет более оптимальным), далее.





Настройка некой безопасности, оставляем всё по умолчанию, далее.


Наконец то и модуль настроили, проверяем настроенные опции и в случае если всё верно жмём "Finish".







Проверяем отсутствие ошибок и принимаем поздравления.

Осталось самое последнее действие: "Login to Icinga Web 2"





На этом установку Icinga2 и Icinga Web 2 можно считать завершённой, далее можно попробовать авторизоваться и начать настройку системы мониторинга.

понедельник, 6 октября 2014 г.

Мониторим загрузку трафика

Для этой цели будем использовать инструментарий Multi Router Traffic Grapher (MRTG).

Установка:
# yum install mrtg

Конфигурационные файлы для mrtg можно генерировать утилитой cfgmaker, но мы создадим основную конфигурацию /etc/mrtg/mrtg.cfg вручную, а для самих устройств уже нагенеририм конфигурации.

Сперва создадим каталог для конфигурационных файлов оборудования, в данном случае cisco и укажем в mrtg это расположение:
Include:        cisco/*.cfg

каталог cisco расположен в том же каталоге, что и основной конфигурационный файл mrtg.cfg (в /etc/mrtg).

Далее настроим глобальное определение WorkDir, которое будет указывать расположение логов и веб-страничек.
WorkDir:        /var/www/mrtg

Вместо WorkDir можно использовать определения HtmlDir, ImageDir и LogDir для сепарации данных по каталогам. Названия этих определений говорят о своём функциональном назначении.

Настроим количество процессов:
Forks:          4

Укажем срок хранения логов в секундах:
MaxAge:         604800

Настроим выводные данные:
Options[_]:     growright, bits

  • опция growright определяет, что время на графике будет расти вправо и шкала значений будет расположена слева;
  • опция bits определят, что все значение будут выводиться в битах, а не в байтах (т.е. умноженные на 8).
Также существуют и другие опции, с которыми можно ознакомиться в документации.

Запускать будем в режиме демона:
RunAsDaemon:    Yes

и укажем интервал снятия данных в минутах:
Interval:       5

Отключаем неиспользуемый IPv6:
EnableIPv6:     no

В итоге основной конфигурационный файл выглядит так:
# grep -v ^# /etc/mrtg/mrtg.cfg
Include:        cisco/*.cfg
WorkDir:        /var/www/mrtg
Forks:          4
MaxAge:         604800
Options[_]:     growright, bits
RunAsDaemon:    Yes
Interval:       5
EnableIPv6:     no


Запускать демона будем не привилегированным пользователем mrgt:
# useradd -s /usr/sbin/nologin mrtg
# systemctl enable mrtg

Правим в файле /usr/lib/systemd/system/mrtg.service следующие строки:
ExecStart=/usr/bin/mrtg --user=mrtg --group=mrtg /etc/mrtg/mrtg.cfg --lock-file /var/lock/mrtg/mrtg_l --confcache-file /var/lib/mrtg/mrtg.ok --pid-file=/var/lib/mrtg/mrtg.pid
Type=forking

Перечитываем конфиги systemd:
# systemctl daemon-reload

В первой строке указываем пользователя и группу, во второй выбираем тип демона в соответствии с нашими настройками (RunAsDaemon: yes; NoDetach: no).

Теперь необходимо расставить верные права на рабочие каталоги mrtg:
# chown mrtg.mrtg /var/www/mrtg
# chown mrtg.mrtg /etc/mrtg/*
# chown mrtg.mrtg /var/lock/mrtg
# chown mrtg.mrtg /var/lib/mrtg/

Сервис mrtg готов к запуску:
# systemctl start mrtg

Настройка конфигураций устройств подлежащих мониторингу.
# cfgmaker --output=file_name.cfg community@address

где:
  • file_name.cfg - имя генерируемого файла;
  • community - общая строка (пароль);
  • address - адрес оборудования.
В сгенерированном файле можно закомментировать порты/интерфейсы не требующие контроля или же наоборот раскомментировать те порты/интерфейсы, которые утилита cfgmaker промаркировала как комментарии.

И подобным образом создаются конфигурационные файлы mrtg для всех устройств, требующих мониторинга. Располагаться эти файлы должны в месте, которое знает mrtg (определение Include в файле /etc/mrtg/mrtg.cfg).

После изменения файлов конфигураций или добавлении нового файла необходимо перезапустить сервис mrtg.

пятница, 26 сентября 2014 г.

Настройка конфигурационных файлов snmptt

При установке snmptt предлагается некий конфигурационный файл  snmptt.conf.generic в качестве примера.

Рассмотрим фрагмент этого файла:

EVENT linkDown .1.3.6.1.6.3.1.1.5.3 "Status Events" Normal
FORMAT Link down on interface $1.  Admin state: $2.  Operational state: $3
#EXEC qpage -f TRAP notifygroup1 "Link down on interface $1.  Admin state: $2.  Operational state: $3"
SDESC
A linkDown trap signifies that the SNMP entity, acting in
an agent role, has detected that the ifOperStatus object for
one of its communication links is about to enter the down
state from some other state (but not from the notPresent
state).  This other state is indicated by the included value
of ifOperStatus.
EDESC

В первой строке указывается цифровой OID и его статус.
Вторая строка описывает содержимое сообщения трапа и в большинстве случаев помогает понять, что за переменные оно содержит.
В третьей строке мы должны указать действие которое необходимо выполнить при получении это трапа. 
Между стартовым тегом SDESC и тегом закрытия EDESC содержится некое описание.

Для создания конкретных конфигурационных файлов существует утилита входящая в пакет snmptt: snmpttconvertmib.
Для начальных данных этой утилите нужен MIB файл (или набор файлов) для оборудования от которого планируется получать трапы:
# snmpttconvertmib --in=path-to-mib --out=output-file-name

если установлен модуль perl NET-SNMP (пакет net-snmp-perl), то можно использовать дополнительно опцию -net_snmp_perl и в файле на выходе переменные будут описаны более подробно, например:

# snmpttconvertmib --in=/usr/share/snmp/mibs/UPS-MIB.txt --out=snmptt.conf.apc
# snmpttconvertmib --in=/usr/share/snmp/mibs/UPS-MIB.txt --out=snmptt.conf.apc2 -net_snmp_perl

первое событие в файле snmptt.conf.apc описано так:
EVENT upsTrapOnBattery .1.3.6.1.2.1.33.2.1 "Status Events" Normal
FORMAT The UPS is operating on battery power.  This trap is $*
SDESC
The UPS is operating on battery power.  This trap is
persistent and is resent at one minute intervals until
the UPS either turns off or is no longer running on
battery.
Variables:
  1: upsEstimatedMinutesRemaining
  2: upsSecondsOnBattery
  3: upsConfigLowBattTime
EDESC

в случае использования дополнительной опции -net_snmp_perl первое событие в файле snmptt.conf.apc2 уже описано так:
EVENT upsTrapOnBattery .1.3.6.1.2.1.33.2.1 "Status Events" Normal
FORMAT The UPS is operating on battery power.  This trap is $*
SDESC
The UPS is operating on battery power.  This trap is
persistent and is resent at one minute intervals until
the UPS either turns off or is no longer running on
battery.
Variables:
  1: upsEstimatedMinutesRemaining
     Syntax="INTEGER"
     Descr="An estimate of the time to battery charge depletion
            under the present load conditions if the utility power
            is off and remains off, or if it were to be lost and
            remain off."
  2: upsSecondsOnBattery
     Syntax="INTEGER"
     Descr="If the unit is on battery power, the elapsed time
            since the UPS last switched to battery power, or the
            time since the network management subsystem was last
            restarted, whichever is less.  Zero shall be returned
            if the unit is not on battery power."
  3: upsConfigLowBattTime
     Syntax="INTEGER"
     Descr="The value of upsEstimatedMinutesRemaining at which a
            lowBattery condition is declared.  For agents which
            support only discrete (discontinuous) values, then the
            agent shall round up to the next supported value.  If
            the requested value is larger than the largest
            supported value, then the largest supported value
            shall be selected."
EDESC

Второй вариант даёт более ясное представление о переменных, их содержании и взаимосвязях.

Утилита snmpttconvertmib умеет формировать и добавлять строку с определением EXEC, в которой указывается действие, выполняемое при получении этого трапа. Для этого используется опция --exec=command, где command строка заключенная в одиночные кавычки. К строке указаной в качестве command добавляется содержимое строки с опрелением FORMAT, заключённое в двойные ковычки:
# snmptt_1.4/snmpttconvertmib --in=/usr/share/snmp/mibs/UPS-MIB.txt --out=snmptt.conf.apc -net_snmp_perl --exec='/usr/local/icinga/libexec/eventhandlers/submit_check_result $r TRAP 1'

событие сформируется следующим образом:
EVENT upsTrapOnBattery .1.3.6.1.2.1.33.2.1 "Status Events" Normal
FORMAT The UPS is operating on battery power.  This trap is $*
EXEC /usr/local/icinga/libexec/eventhandlers/submit_check_result $r TRAP 1 "The UPS is operating on battery power.  This trap is $*"

в большинстве случаев это очень удобно. В случае возникновения необходимости всегда можно откорректировать содержимое строки выполнения.

Также никто не мешает написать конфигурационный файл самостоятельно. Рассмотрим, например, файл в котором описаны действия, выполняемые в случае получения трапа о изменении статуса порта от оборудования Cisco:
EVENT linkDown .1.3.6.1.6.3.1.1.5.3 "Status Events" Normal
FORMAT Port name: $2 Status: $4
EXEC /usr/local/icinga/libexec/eventhandlers/submit_check_result $r "Port $2" 2 "Аварийный режим"

EVENT linkUp .1.3.6.1.6.3.1.1.5.4 "Status Events" Normal
FORMAT Port name: $2 Status: $4
EXEC /usr/local/icinga/libexec/eventhandlers/submit_check_result $r "Port $2" 0 "В работе"

Разберём первое событие построчно.
Первая строка:
EVENT linkDown .1.3.6.1.6.3.1.1.5.3 "Status Events" Normal 

начинается с определения EVENT, далее следуют:
- наименование события, в данном случае linkDown, уникальная текстовая метка (алиас) не должна содержать пробелы;
- OID события, в данном случае .1.3.6.1.6.3.1.1.5.3, в цифровом виде, можно использовать и символьный вариант. Допустимо использование шаблонов поиска, например, .1.3.6.1.6.3.1.1.5.*, но при этом необходимо учитывать, что OID'ы будут обрабатываться в порядке их перечисления;
- категория, в данном случае "Status Events", символьная строка заключенная в двойные кавычки, используется для логирования. Если указать категорию "IGNORE", то никаких действий по выполнению определений EXEC и FORMAT не будет выполнено. Также существует категория "LOGONLY", которая отключает выполнение определения EXEC, но логирование осуществляется;
- уровень статуса, в данном случае Normal, символьная строка указывающая статус, например, Minor, Major, Normal, Critical, Warning, используется для логирования. Можно связать с уровнями syslog'а (см. snmptt.ini, опции syslog_level_*).

Вторая строка:
FORMAT Port name: $2 Status: $4

начинается с определения FORMAT за которым следует строка генерирующая текст при логировании. У каждого события может быть только одна строка с определением FORMAT.
Для генерации возможно использование следующих переменных:

$A - имя узла агента;
$aA - IP адрес агента;
$Be - securityEngineID (snmpEngineID) (доступно только при использовании встроенного обработчика);
$Bu - securityName (snmpCommunitySecurityName) (доступно только при использовании встроенного обработчика);
$BE - contextEngineID (snmpCommunityContextEngineID) (доступно только при использовании встроенного обработчика);
$Bn - contextName (snmpCommunityContextName) (доступно только при использовании встроенного обработчика);
$c - категория;
$C - общая строка (community string);
$D - текстовое описание их snmptt.conf или MIB файла (см. опцию description_mode в snmptt.ini);
$E - OID трапа в символьном виде;
$e - OID трапа в числовом виде;
$Fa - звуковой сигнал (bell) (BEL);
$Ff - прогон страницы, новая страница (FF);
$Fn -  перевод строки (LF, NL);
$Fr - перевод каретки (CR);
$Ft - символ горизонтальной табуляции (HT, TAB);
$Fz - транслированная строка FROMAT (работает только в опредлении EXEC);
$G - номер общего трапа (generic trap, 0 в случае enterprise trap);
$H - имя узла на котором запущен snmptt;
$S - номер особого трапа (specific trap, 0 в случае enterprise trap);
$N - имя события, которое определено в .conf файле
$i - OID события (может быть шаблонным);
$O - OID трапа в символьном формате (необходимо включить опцию translate_trap_oid_format в snmptt.ini, также требуются установленный модуль Perl Net-SNMP и его включённая поддержка - опция net_snmp_perl_enable в snmptt.ini);
$o - OID трапа в числовом формате;
$R, $r - имя узла отправившего трап;
$aR, $ar - IP адрес узла отправившего трап;
$s - уровень статуса (указанный определение EVENT);
$T - Uptime: время прошедшее после инициализации сетевого объекта;
$X -  время попадания трапа в очередь обработки (в случае режима daemon) или текущее время (в случае режима standalone);
$x - дата попадания трапа в очередь обработки (в случае режима daemon) или текущее время (в случае режима standalone);
$# - количество переменных, которые передаются в трапе;
$$ - печатает символ $;
$@ - количество секунд прошедших от начала времён (01.01.1970 г.) до момента попадания трапа в очередь обработки (в случае режима daemon) или текущее время (в случае режима standalone);
$n - выводит значение переменной n;
$+n - выполняет подстановку переменной n в виде:  имя переменной:значение;
$-n -  выполняет подстановку переменной n в виде:  имя переменной (тип переменной):значение;
$vn - выводит имя переменной n;
$* - выводит значение всех переменных n;
$+* - тоже самое, что и $+n только делает подстановку для всех переменных;
$-* - тоже самое, что и $-n только делает подстановку для всех переменных.

Для работы с переменными которые выполняют подстановку n-перемененных, необходимо учитывать, что нумерация начинается с 1 и требуется настройка следующих опций в snmptt.ini:
  • net_snmp_perl_enable (и конечно же установленный модуль Perl Net-SNMP);
  • translate_* (по умолчанию все необходимые опции включены);
  • mibs_enviroment = ALL (или настройка файла snmp.conf).
Таким образом рассматриваемая строка будет генерировать собщение:

Port name: $2 Status: $4

в котором будет выполнена соответствующая подстановка переменных $2 и $4 их значениями, именем порта и его статусом.

Третья строка:
EXEC /usr/local/icinga/libexec/eventhandlers/submit_check_result $r "Port $2" 2 "Аварийный режим"

начинается с определения  EXEC за которым следует комадная строка. В данном случае текст "Аварийный режим" заключенный в двойные кавычки, передаётся обработчику событий системы мониторинга Icinga, которому также необходимо передать имя узла, имя сервиса и код статуса.
У каждого события может быть несколько строк с определением EXEC, соответственно можно можно выполнить несколько действий при получении одного трапа. В командной строке можно использовать те же переменные, что и в строке определения FORMAT.

Также в конфигурации трансляции трапа можно использовать определения: PREEXEC, NODES, MATCH, REGEX и конечно же SDESC и EDESC. Пара последних опрледелений используется для открытия возможного описания и его закрытия. Описание остальных определений можно найти в официальной документации.

В рассматриваемом примере используется обработчик событий поставляемый системой мониторинга Icinga, но можно использовать любой обработчик, в некоторых случаях возможно и придётся написать его самостоятельно.

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

среда, 24 сентября 2014 г.

Обработка и хранения snmp трапов

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

1. Сбор трапов

Этой задачей будет заниматься snmptrapd. Устанавливается он из пакета net-snmp.
После установки необходимо проверить, скомпилирован ли snmptrapd со встроенной поддержкой Perl:
[root@hostname]#snmptrapd -H 2>&1 | grep perl
    perl                     PERLCODE
    perlInitFile             string

наличие первой строки сообщает, что требуемая поддержка имеется и возможно использование встроенного обработчика помимо стандартного обработчика трапов.
Если же эта строка отсутствует, то придётся компилировать net-snmp из исходников с опцией --enable-embedded-perl или использовать только стандартный обработчик трапов, у которого есть существенный недостаток -- snmptthandler запускается и считывает snmptt.ini при каждом получении трапа, возможно из-за этого иногда происходит зависания процесса в случае использования стандартного обработчика в связке с PostgreSQL.

Конфигурация:
# grep -v ^# /etc/snmp/snmptrapd.conf
disableAuthorization yes
perl do "/usr/sbin/snmptthandler-embedded"
;

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

Чтобы не возникали проблемы с переводом символьных OID'ов в числовые, добавим опцию к сервису snmptrapd:
# grep -v ^# /etc/sysconfig/snmptrapd
OPTIONS="-On"

Для перехода к следующему этапу необходимо найти и скачать MIB файлы  для оборудование которое подлежит мониторингу посредством snmp трапов и скопировать их в каталог /usr/share/snmp/mibs/.

2. Трансляция трапов

Для этой задачи существует набор скриптов под названием SNMPTT (SNMP Trap Translator). В большинстве случаев возможностей snmptt будет хватать, но также существует  возможность парсить содержимое трапов своими скриптами, формировать сообщение по требуемым правилам, этот вариант будет описан позже (уже после установки и настройки системы мониторинга icinga).

Установка скриптов snmptt возможна двумя способами:
- установка через менеджер пакетов;
- установка из исходников (для дистрибутивов у которых пакетный менеджер не знает этот пакет и также для тех кто хочет установить самую свежую версию набора скриптов).

Установка во втором варианте заключается в том, что необходимо скачать исходники с www.snmptt.org и скопировать исполняемые и конфигурационные файлы, этот процесс описан в официальной документации и выглядит примерно так:

# tar zxvf snmptt_1.4.tgz
# cd snmptt_1.4
# cp snmptt /usr/sbin/
# cp snmptthandler-embedded /usr/sbin/
# chmod +x /usr/sbin/snmptthandler-embedded
# ls -la /usr/sbin/ | grep snmptt
-rwxr-xr-x.  1 root root      177455 Sep 25 15:04 snmptt
-rwxr-xr-x.  1 root root        9227 Sep 25 15:04 snmptthandler-embedded
# cp snmptt.ini /etc/snmp/
# cp snmptt.logrotate /etc/logrotate.d/snmptt

копировать файл примера конфигурации snmptt.conf.generic нет необходимости, достаточно просто заглянут в него для понимания того, как должна примерно выглядеть структура файла конфигурации трапов, которые требуется транслировать.

Рассмотрим основные моменты настройки snmptt.ini.

mode = daemon
Используем режим daemon, т.к. используется встроенный обработчик трапов и он поддерживает только этот режим. Режим standalone можно использовать только со стандартным обработчиком.

net_snmp_perl_enable = 1
Включаем поддержку модуля Perl и получаем возможность использовать подстановку переменных в конфигурационных ini файлах.

spool_directory = /var/spool/snmptt/
Вполне понятная опция, только необходимо создать данный каталог.

log_system_enable = 1
unknown_trap_log_enable = 1
Включаем логирование системных ошибок и неизвестных трапов. Файлы логов и их расположение используем стандартные, но необходимо создать каталог /var/log/snmptt/.

statistics_interval = 5184000
Опция связанная с какой то статистикой, посмотрим может в этот раз это сработает)

syslog_level = debug
Включаем самый подробный уровень логирования.

postgresql_dbi_enable = 1
postgresql_dbi_module = 1
postgresql_dbi_hostport_enable = 1
Использовать в качестве базы данных будем PostgreSQL.

postgresql_dbi_host = localhost
postgresql_dbi_port = 5432
postgresql_dbi_database = snmptt
Стандартные настройки

postgresql_dbi_table_statistics = snmptt_statistics
Оптимистично укажем таблицу для статистики)

postgresql_dbi_username = snmpttuser
postgresql_dbi_password = password
Параметры аторизации.

DEBUGGING = 2
DEBUGGING_FILE = /var/log/snmptt/snmptt.debug
DEBUGGING_FILE_HANDLER = /var/log/snmptt/snmptthandler.debug
Выставляем везде максимально возможный уровень логирования

snmptt_conf_files = <<END
/etc/snmp/snmptt.conf.apc
/etc/snmp/snmptt.conf.cisco
/etc/snmp/snmptt.conf.cisco_port_status
/etc/snmp/snmptt.conf.rad
/etc/snmp/snmptt.conf.mq
END
Секция в которой перечисляются все конфигурационные файлы. (см. Настройка конфигурационных файлов snmptt)

Установим и настроим PostgreSQL:
# yum install postgresql-server postgresql
# systemctl enable postgresql.service
# postgresql-setup initdb 

Настроим аутентификацию:
# grep -v ^# /var/lib/pgsql/data/pg_hba.conf
local   snmptt          snmptt                                  md5
local   all             all                                     md5
host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5
# systemctl restart postgresql

Создадим базу и необходимые таблицы:
# su - postgres
$ createuser -P snmptt
Enter password for new role:
Enter it again:
$ createdb -O snmptt snmptt
$ psql snmptt
psql (9.2.7)
Type "help" for help.

snmptt=# CREATE TABLE snmptt (
snmptt(# eventname VARCHAR(50),
snmptt(# eventid VARCHAR(50),
snmptt(# trapoid VARCHAR(100),
snmptt(# enterprise VARCHAR(100),
snmptt(# community VARCHAR(20),
snmptt(# hostname VARCHAR(100),
snmptt(# agentip  VARCHAR(16),
snmptt(# category VARCHAR(20),
snmptt(# severity VARCHAR(20),
snmptt(# uptime  VARCHAR(20),
snmptt(# traptime VARCHAR(30),
snmptt(# formatline VARCHAR(255));
CREATE TABLE
snmptt=# GRANT ALL ON snmptt TO snmptt;
GRANT
snmptt=# CREATE TABLE snmptt_unknown (
snmptt(# trapoid VARCHAR(100),
snmptt(# enterprise VARCHAR(100),
snmptt(# community VARCHAR(20),
snmptt(# hostname VARCHAR(100),
snmptt(# agentip  VARCHAR(16),
snmptt(# uptime  VARCHAR(20),
snmptt(# traptime VARCHAR(30),
snmptt(# formatline VARCHAR(255));
CREATE TABLE
snmptt=# GRANT ALL ON snmptt_unknown TO snmptt;
GRANT
snmptt=# CREATE TABLE snmptt_statistics (
snmptt(# stat_time VARCHAR(30),
snmptt(# total_received BIGINT,
snmptt(# total_translated BIGINT,
snmptt(# total_ignored BIGINT,
snmptt(# total_unknown BIGINT);
CREATE TABLE
snmptt=# GRANT ALL ON snmptt_statistics TO snmptt;
GRANT
snmptt=# \q

Добавим пользователя, изменим владельца созданных выше каталогов и настроим запуск демона snmptt:
# useradd snmptt
# id snmptt
# uid=1001(snmptt) gid=1001(snmptt) groups=1001(snmptt)
# cp snmptt-init.d /etc/init.d/snmptt
# ls -la /etc/init.d/ | grep snmp
-rwxr-xr-x.  1 root root  1702 Sep 25 15:56 snmptt
# chkconfig --add snmptt
# chkconfig snmptt on
# systemctl --system daemon-reload
# chown snmptt.snmptt /var/spool/snmptt
# chown snmptt.snmptt /var/log/snmptt
# systemctl start snmptt

при запуске получаем ошибку:

snmptt: Starting snmptt: Can't locate Config/IniFiles.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/sbin/snmptt line 4023.

Исправить эту проблему можно многими путями, например, установить пакет perl-Config-IniFiles, но в репозитариях CentOS 7 этот пакет отсутствует, поэтому найдем в интернетах rpm-пакет perl-Config-IniFiles и установим его:
[root@hostname]# rpm -i perl-Config-IniFiles-2.68-1.5.noarch.rpm
(в Fedora 21 этот пакет есть: # yum install perl-Config-IniFiles)

Чтобы соблюсти все зависимости и избавиться при запуске snmptt от следующих ошибок:
snmptt: Starting snmptt: Can't locate Sys/Syslog.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at (eval 5) line 1.
snmptt: Starting snmptt: Can't locate SNMP.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at (eval 7) line 1.
snmptt: Starting snmptt: Can't locate SNMP.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at (eval 7) line 1.
snmptt: Can't locate DBI.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at (eval 9) line 1.
snmptt: Can't locate DBD/Pg.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at (eval 12) line 1.

установим необходимые пакеты:
# yum install perl-Sys-Syslog net-snmp-perl perl-DBD-Pg

Также потребуется пакет perl-Time-HiRes, при использовании встроенного обработчика ошибка о необходимости этого пакета не возникает, но без него и не будет работать передача трапов от snmptrapd в snmptt:
# yum install perl-Time-HiRes

и запустим снова демон snmptt:
# systemctl start snmptt

На этом этапе у нас работаю сервисы PostgreSQL и SNMPTT, теперь запустим snmptrapd:
# systemctl start snmptrapd

и начнём получать, транслировать и складывать в базу трапы.

Сейчас самое время заняться отладкой, для этого заглянем логи, например, в /var/log/snmptt/snmptt.debug обнаружилась следующая ошибка:
Postgres error: Unable to perform INSERT INTO (EXECUTE): ERROR:  value too long for type character varying(20)

Находим в логах PostgreSQL:
ERROR:  value too long for type character varying(20)
STATEMENT:  INSERT INTO snmptt_unknown (trapoid,enterprise,community,hostname,agentip,uptime,traptime,formatline) VALUES ($1,$2,$3,$4,$5,$6,$7,$8)

Получается, что проблема возникает с трапами которые не знает snmptt, определяем в /var/log/snmptt/snmpttunknown.log параметр, который не влазит в размеры указанные при создании базы и правим его (например, через phpPgAdmin), возможно с некоторым запасом.
И подобным образом добиваемся устранения всех ошибок.

3. Веб-интерфейс к полученным трапам

Данный этап необязателен и не оказывает влияние на работоспособность системы мониторинга.
Сперва установим веб-сервер и для удобства установим phpPgAdmin:
# yum install httpd
# systemctl enable httpd
# systemctl start httpd

Yum в CentOS 7 не знает пакет phpPgAdmin (в Fedora 21 пакет есть в репозиториях: # yum install phpPgAdmin), скачиваем дистрибутив с phppgadmin.sourceforge.net, распаковываем, например, в /usr/share/ и настраиваем веб-сервер:

# grep -v ^# /etc/httpd/conf.d/phppgadmin.conf
Alias /phppgadmin /usr/share/phppgadmin

<Directory /usr/share/phppgadmin>
  DirectoryIndex index.php
  AllowOverride None
  Require all granted
<IfModule mod_php5.c>
  php_flag magic_quotes_gpc Off
  php_flag track_vars On
  php_value include_path .
</IfModule>
<IfModule !mod_php5.c>
  <IfModule mod_actions.c>
    <IfModule mod_cgi.c>
      AddType application/x-httpd-php .php
      Action application/x-httpd-php /cgi-bin/php
    </IfModule>
    <IfModule mod_cgid.c>
      AddType application/x-httpd-php .php
      Action application/x-httpd-php /cgi-bin/php
    </IfModule>
  </IfModule>
</IfModule>

</Directory>


В Fedora 21 правим /etc/httpd/conf.d/phpPgAdmin.conf.
# grep Require /etc/httpd/conf.d/phpPgAdmin.conf
        #Require local
        Require all granted
        #Require host example.com


И перечитываем конфиги веб сервера:
# systemctl restart httpd

Простецкий веб-интерфейс WSTL:


Итак, основные вопросы со сбором, трансляцией и хранением трапов рассмотрены можно двигаться дальше к созданию системы мониторинга.