среда, 9 декабря 2015 г.

КМБ или бегло пытаемся настроить Icinga2

Начнём с самого главного файла icinga2.conf, по сути он содержит ссылки на конфигурационные файлы и описание содержимого этих самых файлов.

Первая ссылка:
include "constants.conf"

включает файл в котором мы будем хранить глобальные константы, глянем на них:

const PluginDir = "/usr/local/libexec/icinga2"
const CustomPluginDir = "/usr/local/libexec/icinga2/my_libexec"


const ManubulonPluginDir = "/usr/lib64/nagios/plugins"
const PluginContribDir = "/usr/lib64/nagios/plugins"

const ZoneName = NodeName
const TicketSalt = ""

Первая константа указывает директорию с плагинами из набора с сайта www.monitoring-plugins.org.
Вторая константа указывает директорию с самописными плагинами.

Третья и четвертая константы дефотные и не используются.

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

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

Как видно с определением констант не должно возникнуть сложностей, опять глянем в icinga2.conf:

include "zones.conf"

включается файлик для настройки зоны, кластер пока не рассматриваем и пропускаем этот файл.

include <itl>
include <plugins>


включаем Icinga Template Library (ITL) и основные плагины.
Заходим в /usr/share/icinga2/include и видим файлы с этими именами, посмотрев содержимое станет понятно, что это и как это можно будет использовать. Но на данном этапе проще пропустить это действие и вернуться уже после того как появится хотя бы минимально представление о настройке icinga2.

include "features-enabled/*.conf"

указывает где смотреть включенные фичи, оставляем дефолотным


include_recursive "repository.d"

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

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

include_recursive "conf.d"

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

Файл commands.conf изначально почему то содержит конфигурацию команд уведомлений, мы создадим отдельный файл для этой цели и соответствующим названием.
Здесь же будем настраивать команды которые непосредственно используются для проверки состояния объектов мониторинга.

Команда создаётся как объект типа CheckCommand

object CheckCommand "check-name" {
}

check-name - имя команды, в блоке заключенным в фигурные скобки будем использовать следующее:

import "plugin-check-command"

импортируем необходимые методы для работы с командами, будем считать, что является необходимой и обязательной опцией. (Конечно экспериментаторам всё пути доступны).

command = [ PluginDir + "/check_name" ]

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

PluginDir -- имя константы, определенной в constants.conf ;
check_name -- имя самого файла.

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

Следующие две опции не являются обязательными, но вполне удобны для использования:

1) Аргументы, которые принимает плагин, в основном применяется для стандартных плагинов и плагинов где аргументы предаются парами ключ-значение.
Лучше показать на примерах:

  arguments = {
   "-F" = "$mrtg_log_file$"
   "-a" = "$mrtg_type$"
   "-w" = "$mrtg_warning$"
   "-c" = "$mrtg_critical$"
   "-e" = "$mrtg_expire_minutes$"
  }


  arguments = {
    "-H" = "$pop_address$"
    "-w" = "$pop_warning$"
    "-c" = "$pop_critical$"
  }


в левой части указывается флаг/ключ, в правой переменная значение которой и будет передано с соответствующим флагом.

2) Переменные. Нам ведь нужно как то задать значения переменным, которые мы создали выше, например:

  vars.pop_address = "$address$"
  vars.pop_warning = "1"
  vars.pop_critical = "2"


$address$ -- внутрення переменная icinga2, содержит адрес указанный у объекта мониторинга, см. здесь (TODO).
"1" и "2" значения, т.е. плагин будет выполнен так:

/реальный/путь/check_pop -H <реальный_адрес> -w 1 -c 2

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

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

command = [ CustomPluginDir + "/check_snmp_linux", "$address$", "load", "$load_1_w$", "$load_5_w$", "$load_15_w$", "$load_1_c$", "$load_5_c$", "$load_15_c$" ]

и задать значения переменным.

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

Перейдём к следующему файлу, к commands_notifications.conf
В нём создадим команды для уведомлений, типа такой:

object NotificationCommand "mail-host-notification" {
  import "plugin-notification-command"

  command = [ SysconfDir + "/icinga2/scripts/mail-host-notification.sh" ]

  env = {
    NOTIFICATIONTYPE = "$notification.type$"
    HOSTALIAS = "$host.display_name$"
    HOSTADDRESS = "$address$"
    HOSTSTATE = "$host.state$"
    LONGDATETIME = "$icinga.long_date_time$"
    SHORTDATETIME = "$icinga.short_date_time$"
    HOSTOUTPUT = "$host.output$"
    NOTIFICATIONAUTHORNAME = "$notification.author$"
    NOTIFICATIONCOMMENT = "$notification.comment$"
    HOSTDISPLAYNAME = "$host.display_name$"
    USEREMAIL = "$user.email$"
  }
}


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

Заглядываем в mail-host-notification.sh и понимаем, как просто русифицировать текст сообщений уведомления и как можно писать любые плагины для отправки уведомлений различными способами (netsend, jabber, etc):

#!/bin/sh
case "$NOTIFICATIONTYPE" in
        "RECOVERY"      )       NOTIFICATIONTYPE="ПЕРЕХОД НА НОРМАЛЬНЫЙ РЕЖИМ" ;;
        "PROBLEM"       )       NOTIFICATIONTYPE="ПРОБЛЕМА" ;;
esac

case "$HOSTSTATE" in
        "UP"            )       HOSTSTATE="ДОСТУПЕН ПО СЕТИ" ;;
        "DOWN"          )       HOSTSTATE="НЕ ДОСТУПЕН ПО СЕТИ" ;;
esac

template=`cat <<TEMPLATE
***** Система мониторинга *****

Тип уведомления: $NOTIFICATIONTYPE

Узел: $HOSTALIAS
Адрес: $HOSTADDRESS
Состояние: $HOSTSTATE

Дата/Время: $SHORTDATETIME

Дополнительная информация: $HOSTOUTPUT

Комментарии: [$NOTIFICATIONAUTHORNAME] $NOTIFICATIONCOMMENT
TEMPLATE
`
/usr/bin/printf "%b" "$template" | mail -s "$NOTIFICATIONTYPE - $HOSTDISPLAYNAME is $HOSTSTATE" $USEREMAIL


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

Описание всех доступных переменных можно посмотреть в документации или здесь (TODO).

Следующий файл downtimes.conf
Пропускаем.

У меня следующим идёт functions.conf
Пропускаем и его, т.к. используется для функций которые вызываются другими конфигами, эту возможность рассмотрим позже.

Файл groups.conf определяет группы:

object HostGroup "name" {
  display_name = "Алиас"
}


Файл hosts.conf содержит настройку локального узла, логичнее его перенести в место хранение группы к которой принадлежит данный узел.
Как настраиваются объекты мониторинга, в частности узлы, будет рассмотрено здесь (TODO).

Далее в файле notifications.conf определяется кому, как и при каких условия слать уведомления.

apply Notification "mail-icingaadmin" to Host {
  import "mail-host-notification"

  user_groups = [ "icingaadmins" ]
  interval = 0
  assign where host.address

}


Уведомления уже не создаются, а применяются, т.е. нам нужно дать уведомлению имя, в данном случае "mail-icingaadmin", выбрать к узлу (to Host) или к сервису (to Service) применяется это уведомление.
Импортировать необходимые методы, определить группу пользователей (см. ниже), параметр user_groups и назначить некие условия, по которым определяются узлы или сервисы к которым должно примениться это уведомление.
В рассматриваемом примере уведомление применяется ко всем узлам имеющим адрес:

assign where host.address

Конечно более подробные описания приведены в официальной документации (TODO), а здесь я приведу пару примеров для наглядности:

ignore where service.name == "TRAP"
assign where host.vars.os in [ "Windows", "Linux" ]

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

interval = 0 отключает повторную отправку уведомления.

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

  if (service.name == "load") {
    times.begin = 15m

}

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

Следующий файл satellite.conf пропускаем.

services.conf пропускаем и использовать не будем, сервисы будем настраивать здесь (TODO).

Далее идёт файл шаблонов templates.conf.

template Host "generic-host" {
  max_check_attempts = 3
  check_interval = 1m
  retry_interval = 30s

  check_command = "hostalive"
}


Создаем шаблон для узла с именем "generic-host", проверяем узел каждую минуту, в случае неудачной проверки производим повторную проверку через 30 секунд и максимальное таких перепроверок 3 штуки.
Для проверки используется команда hostalive , выше мы встречали include <plugins> в основном конфигурационном файле, что и даёт нам возможность использовать эту команду (см. /usr/share/icinga2/include/plugins).

Шаблон для сервиса:

template Service "generic-service" {
  max_check_attempts = 5
  check_interval = 1m
  retry_interval = 30s
}


Для пользователя:

template User "generic-user" {

}


По умолчанию он пустой.

И шаблон для уведомлений:

template Notification "mail-host-notification" {
  command = "mail-host-notification"

  states = [ Up, Down ]
  types = [ Problem, Acknowledgement, Recovery, Custom,
            FlappingStart, FlappingEnd,
            DowntimeStart, DowntimeEnd, DowntimeRemoved ]

  period = "24x7"
}


В принципе всё просто, указан тип шаблона, его имя, команда. Выбраны состояния на которые реагировать и типы изменений.
Период выбран, а настраивается он в следующем файле timeperiods.conf.

object TimePeriod "24x7" {
  import "legacy-timeperiod"

  display_name = "Icinga 2 24x7 TimePeriod"
  ranges = {
    "monday"    = "00:00-24:00"
    "tuesday"   = "00:00-24:00"
    "wednesday" = "00:00-24:00"
    "thursday"  = "00:00-24:00"
    "friday"    = "00:00-24:00"
    "saturday"  = "00:00-24:00"
    "sunday"    = "00:00-24:00"
  }
}


Там же есть дефолтные периоды "9to5" и "never", для начала их должно хватить, ну или можно изменить часы рабочего времени.

Последний файл с пользователями и группами users.conf:

object User "icingaadmin" {
  import "generic-user"

  display_name = "Icinga 2 Admin"
  groups = [ "icingaadmins" ]

  email = "address@mail.local"
  vars.jabber = "nickname@jabba.local"
}


Создаём оъект пользователь, присваиваем ему имя, импортируем необходимые методы, указываем имя которое будет отображаться в web-интерфейсе, закидываем в группу.
Указываем значения внутренней переменной email и созданной нами vars.jabber.

Группу тоже необходимо создать:

object UserGroup "icingaadmins" {
  display_name = "Группа админов"
}


И так, основные конфигурационные файлы бегло рассмотрели, осталось разобраться с настройкой узлов и сервисов и с теми моментами которые были пропущены. В какой то момент времени и это появится здесь.
Да прибудет с тобой icinga ;)

пятница, 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.

четверг, 2 октября 2014 г.

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

Web SNMP Traps List (WSTL)

Структура базы SNMPTT, в которой хранятся распознанные трапы и трапы для которых нет конфигурационных файлов до такой степени простая, что написать некий веб-интерфейс для отображения данных и их некой обработке не составляет большого труда. Точнее сводится к обработке SQL запросов о выборке из двух таблиц snmptt и snmptt_unknown (таблицу snmptt_statistics не рассматриваем, т.к. не совсем понятно когда заработает статистика):

SELECT * FROM snmptt;
SELECT * FROM snmptt_unknown;

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

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