АНДРЕЙ БЕШКОВ
Мониторинг UNIX-серверов
c помощью Nagios и SNMP
В предыдущей статье этого цикла [1] мы говорили о том, как научить Nagios следить за Windows-серверами, пользуясь сведениями, предоставляемыми SNMP. Теперь пришла пора рассказать, как можно собирать данные о жизнедеятельности серверов, работающих под управлением разных диалектов UNIX. Для этого мы будем снова использовать SNMP. Если вас мучают вопросы, что такое этот пресловутый SNMP, как он работает и для чего предназначен, то, наверное, стоит ознакомиться с RFC 1156, 1157, 1213, 1146, 2571, 2574 и заодно прочитать предыдущую статью [1]. Перед началом повествования следует сказать, что система мониторинга, на которой будут выполняться все действия, описанные ниже, у меня работает под управлением FreeBSD. За время, прошедшее с момента публикации предыдущей статьи, Nagios дорос до версии 1.2, также изменилась с 4.7 на 4.10 версия системы FreeBSD, используемой на моем сервере. Теперь уже нет необходимости компилировать Nagios из исходников, все прекрасно ставится из портов. Впрочем, стоит, как всегда, сделать традиционную оговорку: все, что я рассказывал в предыдущих статьях о Nagios и о чем буду говорить впредь, вполне надежно работает и под управлением других UNIX-подобных операционных систем.
Вдобавок необходимо заметить, что пакет usd-snmp, использовавшийся нами для работы с SNMP прежде, теперь превратился в net-snmp версии 5.1.1.
Перейдем к задаче на сегодня. Необходимо настроить мониторинг серверов, работающих под управлением FreeBSD 4.10 и ALT Linux 2.3. Соответственно, для примера им даны имена reddaemon и penguin. Впрочем, стоит заметить, что net-snmp успешно работает и на многих других UNIX-подобных системах:
- HP-UX (9.0, 10.20, 11.0);
- Ultrix (от 4.2 до 4.5);
- OSF (3.2, 4.0);
- Solaris (SPARC/ULTRA от 2.3 до 2.8) (Intel 2.9) SunOS (4.1.4 и выше);
- NetBSD (от 1.0 до 1.5 alpha);
- FreeBSD (от 2.2 и выше);
- Linux (ядра от 1.3 и выше);
- BSDI (от 2.1 до 4.0.1);
- AIX (3.2.5, 4.1.5);
- OpenBSD (2.6, 2.8);
- OS X (10.1.1, 10.1.2);
- Irix (от 5.1 до 6.5);
- QNX 6.2.1A;
- Dynix/PTX 4.4.
На данный момент идут работы по портированию net-snmp на Windows. В результате уже сейчас можно сказать, что программа работает на 90% при условии компиляции с помощью Visual C++ и cygwin32.
Отсюда можно сделать вывод, что, приложив некоторые усилия, мы смогли бы мониторить любую из этих операционных систем, благо процедуры установки и настройки net-snmp для каждой из них почти не отличаются друг от друга.
Первым делом на сервере мониторинга, работающем под FreeBSD, устанавливаем самую новую версию пакетов net-snmp и nagios-plugins.
# cd /usr/ports/net-mgmt/net-snmp
# make install clean
# cd /usr/ports/net-mgmt/nagios-plugins
# make install clean
Пакет net-snmp4, все еще присутствующий в дереве портов, устанавливать не стоит из-за сильной устарелости.
На подопытных серверах также необходимо проинсталлировать net-snmp. Для FreeBSD это делается вышеуказанным способом, но nagios-plugins ставить не следует. Для ALT Linux 2.3 требуется выполнить следующие команды.
# apt-get update
# apt-get install net-snmp net-snmp-utils
На этом процедуру инсталляции можно считать завершенной. Для того чтобы система могла отвечать на SNMP-запросы, внутри нее должен работать демон snmpd. Ему, как и всем порядочным программам, для успешного функционирования необходимо иметь конфигурационный файл. В качестве такового обычно выступает snmpd.conf. При работе с Linux он, как правило, располагается в /etc/snmp/, а для FreeBSD соответственно актуальна директория /usr/local/etc/.
Файл конфигурации одинаков для всех систем, поэтому мы изучим его на примере, используемом для Linux.
# Местонахождение системы в реальном мире
syslocation Rostov-on-Don Kranoarmejskaya str. Building 1 testlab 407
# Контакты администратора
syscontact Andrew Beshkov admin@example.com tel. 390-34-89
# Сервисы, предоставляемые системой
sysservices = 79
Думаю, что есть необходимость подробно объяснить процедуру, с помощью которой рассчитывается содержимое переменной sysservices. Нужно выбрать из списка уровень и подставить его номер вместо L в формулу 2L-1.
- 1 – physical (концентраторы);
- 2 – datalink/subnetwork (мосты);
- 3 – internet (IP-шлюзы);
- 4 – end-to-end (IP-хост);
- 5 – OSI (протоколы OSI);
- 6 – OSI (протоколы OSI);
- 7 – applications (SMTP, POP3 и прочие сервисы).
К примеру, для маршрутизатора расчет будет выглядеть так: 23-1=4. А для обычного хоста 24-1 + 27-1 = 72. Если вы хотите мониторить все уровни, то лучше всего использовать цифру 79.
Можно создать файлы конфигурации с помощью программы snmpconf, но я предпочитаю делать все самостоятельно. По крайней мере, так достигается глубинное понимание механизмов работы используемого программного обеспечения.
Следующим интересным моментом является безопасность. В традиционном SNMP для версий протокола 1 и 2с за нее отвечают строки сообществ (community strings). Их стоит воспринимать как своеобразные аналоги паролей. Сообщества бывают двух видов – private и public. Отличаются они друг от друга лишь тем, что первое позволяет изменять данные внутри наблюдаемого устройства, а второе дает возможность только просматривать их. Самым простым способом определить эти сообщества является внесение в конфигурационный файл следующих строк:
rocommunity InK12345
rwcommunity 12r341289j
Как вы уже могли догадаться, rocommunity дает право читать данные, а rwcommunity предоставляет полный доступ. Впрочем rwcommunity тоже можно удалить, если вы не собираетесь изменять данные внутри устройства с помощью snmp. Вышеприведенные опции составляют минимальный рабочий файл конфигурации. Но квалифицированные системные администраторы обычно так не делают, потому что иначе будет трудно различать это устройство среди огромного множества других SNMP-приборов.
Итак, давайте посмотрим, что за сведения могут предоставить нам подопытные устройства. Для этого запускаем на них демон snmpd. Чтобы это сделать, кладем на Linux-машине файл snmpd.conf в /etc/snmp и затем выполняем следующую команду:
# service snmpd start
Если есть желание, чтобы демон стартовал автоматически при запуске машины, выполняем еще и такую команду:
# chkconfig snmpd on
И обязательно убеждаемся в успешности выполнения предыдущей команды с помощью:
# chkconfig snmpd --list
Для FreeBSD файл с настройками должен находиться в /usr/local/etc/snmp/. Кроме этого, нужно включить запуск демона в скрипте /usr/local/etc/rc.d/snmpd.sh. Чтобы это сделать, ищем внутри него строку snmpd_enable= «NO» и вписываем в нее слово «YES». Затем вручную запускаем демон.
# /usr/local/etc/rc.d/snmpd.s
Стоит отметить тот факт, что, кроме snmpd, в комплект net-snmp входит демон snmptrapd, отвечающий за обработку SNMP-ловушек. По умолчанию он выключен, стоит помнить, что в системе не должно работать ненужного программного обеспечения, поэтому без особой надобности не будем его включать. Говорить о том, как можно использовать эти самые ловушки, мы будем в следующей статье.
Теперь можно проверить, что за сведения предоставляют наши сервера. Сделать это можно как минимум двумя способами. C помощью утилит командной строки snmpget или snmpwalk.
# snmpwalk -m ALL -c InK12345 -v1 penguin .iso.org.dod.internet.mgmt.mib-2.system
SNMPv2-MIB::sysDescr.0 = STRING: Linux altlinux.unreal.net 2.4.27-std-up-alt1 #1 Sun Oct 17 22:42:45 MSD 2004 i686
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
SNMPv2-MIB::sysUpTime.0 = Timeticks: (1751738) 4:51:57.38
SNMPv2-MIB::sysContact.0 = STRING: Andrew Beshkov
SNMPv2-MIB::sysName.0 = STRING: penguin.example.com
SNMPv2-MIB::sysLocation.0 = STRING: Rostov-on-Don Kranoarmejskaya str. Building 1 testlab 407
SNMPv2-MIB::sysServices.0 = INTEGER: 0
SNMPv2-MIB::sysORLastChange.0 = Timeticks: (3) 0:00:00.03
SNMPv2-MIB::sysORID.1 = OID: IF-MIB::ifMIB
SNMPv2-MIB::sysORID.2 = OID: SNMPv2-MIB::snmpMIB
SNMPv2-MIB::sysORID.3 = OID: TCP-MIB::tcpMIB
SNMPv2-MIB::sysORID.4 = OID: IP-MIB::ip
SNMPv2-MIB::sysORID.5 = OID: UDP-MIB::udpMIB
SNMPv2-MIB::sysORID.6 = OID: SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup
SNMPv2-MIB::sysORID.7 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance
SNMPv2-MIB::sysORID.8 = OID: SNMP-MPD-MIB::snmpMPDCompliance
SNMPv2-MIB::sysORID.9 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance
SNMPv2-MIB::sysORDescr.1 = STRING: The MIB module to describe generic objects for network interface sub-layers
SNMPv2-MIB::sysORDescr.2 = STRING: The MIB module for SNMPv2 entities
SNMPv2-MIB::sysORDescr.3 = STRING: The MIB module for managing TCP implementations
SNMPv2-MIB::sysORDescr.4 = STRING: The MIB module for managing IP and ICMP implementations
SNMPv2-MIB::sysORDescr.5 = STRING: The MIB module for managing UDP implementations
SNMPv2-MIB::sysORDescr.6 = STRING: View-based Access Control Model for SNMP.
SNMPv2-MIB::sysORDescr.7 = STRING: The SNMP Management Architecture MIB.
SNMPv2-MIB::sysORDescr.8 = STRING: The MIB for Message Processing and Dispatching.
SNMPv2-MIB::sysORDescr.9 = STRING: The management information definitions for the SNMP User-based Security Model.
|
Опция –m ALL указывает, что нужно показать все дерево ниже выбранного OID, после -с располагается комьюнити string, затем идут версия snmp-протокола, имя машины и OID запрашиваемой ветви. Стоит отметить, что OID можно записывать разными способами. В большинстве случаев префикс iso.org.dod.internet.mgmt.mib-2. можно не писать, так как он предполагается по умолчанию, соответственно мы получим тот же самый результат, если напишем просто system. Для указания OID вместо длинных названий можно использовать цифровые идентификаторы. К примеру, этот же куст дерева можно адресовать следующей комбинацией цифр .1.3.6.1.2.1.1. Если есть желание увидеть все MIB-дерево, то можно выполнить вышеуказанную команду, вовсе не указывая OID. Думаю, вы будете впечатлены размерами листингов, которые система выведет вам. Использовать командный интерфейс полезно, но, к сожалению, это не всегда помогает получить правильное представление о строении MIB-дерева.
В этом нам помогут утилиты, называемые MIB-браузерами. Для Linux и FreeBSD лучше всего подойдет программа mbrowse. Обычно она по умолчанию входит во многие дистрибутивы. В действии эта программа выглядит следующим образом.
Для систем Windows существует достаточно много подобных утилит. О том, какую из них и почему стоит выбрать, я подробно рассказывал в предыдущей статье [1].
Конечно, обилие доступных данных поражает, но все же хотелось бы точно знать, как это использовать с наибольшей выгодой. Давайте вновь вернемся к предмету нашего разговора. Кроме стандартных ветвей, net-snmp создает свою собственную ветвь .iso.org.dod.internet.private. enterprises.ucdavis, которая содержит в себе все необходимые данные. В цифровом формате адрес этой ветви выглядит так: .1.3.6.1.4.1.2021. Стоит отметить, что в некоторых snmp-браузерах данная ветка может быть недоступна через свое символьное обозначение, но в то же время запросы, выполняемые с помощью цифровых OID, будут вполне работоспособны. Думаю, вы со мной согласитесь, что это немного неудобно, поэтому, чтобы включить распознавание символьных имен, нам нужно будет скопировать MIB-базы из /usr/share/snmp/mibs/в рабочую директорию используемого браузера.
Как показывают тесты, все работает достаточно неплохо, но, к сожалению, наша система сейчас отвечает на SNMP-запросы, приходящие с любого IP-адреса. К тому же, по умолчанию используется первая версия протокола SNMP, которая передает все данные в открытом виде. Необходимо это исправить и заодно поднять уровень безопасности. Для этого вносим в файл snmpd.conf следующие строки вместо rocommunity и rwcommunity:
com2sec nagios 10.10.21.55/32 InK12345
group MyROGroup v2c nagios
view all included .1 80
access MyROGroup "" any noauth exact all none none
Стоит отметить, что опции rocommunity и rwcommunity – всего лишь оболочки вокруг более мощного набора команд VACM (Version-based Access Control Module), которым мы воспользовались ранее.
Таким образом, мы сказали, что система, подвергаемая мониторингу, может принимать SNMP-запросы лишь от машины с адресом 10.10.21.55, которая является сервером мониторинга, и привязали этот адрес к внутреннему имени системы безопасности «nagios». Затем разрешили этому имени символизировать группу MyROGroup, а заодно закрепили за ним право передавать SNMP-команды только с помощью версии протокола 2с. Следующей строкой создали вид на определенную область SNMP-дерева. В данном случае с помощью запросов можно просматривать все, что лежит ниже .1 или .iso. Пользуясь этой опцией, можно ограничить дерево, доступное запросу до одной ветки или даже до единственного OID. И заключительной строкой указываем настройки безопасности для нашей группы MyROGroup. После этого не забываем перезапустить демон SNMP и проверить, как все работает.
# snmpwalk –m ALL -c InK12345 -v2с penguin .iso.org.dod.internet.mgmt.mib-2.system
Обратите внимание на опцию –v2c. Если все прошло нормально, выполняем ту же команду с –v1 и убеждаемся, что она не возвращает никаких сведений. Как вы, наверное, уже догадались, мы полностью отключили возможность вносить извне изменения в данные, находящиеся внутри наблюдаемого объекта. Выполняем проверку того, как работает модуль check_snmp, установленный на сервере Nagios. К примеру, неплохо было бы посмотреть Uptime системы:
# /usr/local/nagios/libexec/check_snmp -H penguin -o .1.3.6.1.2.1.3.0 -C InK12345 -P 2c
По каким-то странным причинам автор забыл включить в него возможность работы с протоколом версии 2с. Ошибка, говорящая, что эта версия не поддерживается, – не совсем то, что мы ожидали получить, поэтому давайте возьмем в руки большой напильник и самостоятельно поправим модуль check_snmp. Для этого нужно отредактировать файл /usr/ports/net-mgmt/nagios-plugins/work/nagios-plugins-1.3.1/plugins/check_snmp.c. Ищем в нем следующую строку:
-P, --protocol=[1|3]
и заменяем ее на:
-P, --protocol=[1|2c|3]
Затем, найдя условие такого вида:
if (proto == NULL || (strcmp(proto,DEFAULT_PROTOCOL) == 0) ) { /* default protocol version */
asprintf(&proto, DEFAULT_PROTOCOL);
asprintf(&authpriv, "%s%s", "-c ", community);
}
Вставляем после него вот такие строки:
else if ( strcmp (proto, "2c") == 0 ) { /* snmpv2c args */
asprintf(&proto, "%s", "2c");
asprintf(&authpriv, "%s%s", "-c ", community);
}
Проводим перекомпиляцию, а затем и замену старого модуля новым.
# make install
После этого команда с ключом -P 2c должна отработать нормально. Вписываем в файл checkcommands.cfg описание команды check_snmp_oid, с помощью которой будем проводить мониторинг и вызывать модуль check_snmp.
define command{
command_name check_snmp_oid
command_line $USER1$/check_snmp -H $HOSTADDRESS$ -o $ARG1$ -C $ARG2$ -w $ARG3$ -c $ARG4$ -u $ARG5$ -l "" -P $ARG6$
}
Затем в файле hosts.cfg рассказываем о наших серверах.
# Описываем шаблон хоста
define host{
name generic-host
notifications_enabled 1
event_handler_enabled 1
flap_detection_enabled 1
process_perf_data 1
retain_status_information 1
retain_nonstatus_information 1
max_check_attempts 10
notification_interval 120
notification_period 24x7
notification_options d,u,r
register 0
}
define host{
use generic-host
host_name Linux
alias Standard Linux Server
address penguin
check_command check-host-alive
}
define host{
use generic-host
host_name FreeBSD
alias Standart FreeBSD Server
address reddaemon
check_command check-host-alive
}
И, конечно же, не забываем причислить их к группе хостов onix-servers, внеся следующие строки в файл host groups.cfg
define hostgroup{
hostgroup_name onix-servers
alias Onix Servers
contact_groups onix-admins
members Linux, FreeBSD
}
Настройку оповещений и контактов пропускаем, так как эта тема обсуждалась ранее неоднократно. Самое время заняться описанием сервисов, за которыми мы будем следить.
# Описываем шаблон сервиса
define service{
name generic-service
active_checks_enabled 1
passive_checks_enabled 1
parallelize_check 1
obsess_over_service 1
check_freshness 0
notifications_enabled 1
event_handler_enabled 1
flap_detection_enabled 1
process_perf_data 1
retain_status_information 1
retain_nonstatus_information 1
notification_interval 120
notification_period 24x7
notification_options w,u,c,r
max_check_attempts 3
normal_check_interval 1
retry_check_interval 1
contact_groups onix-admins
register 0
}
Данный сервис показывает время работы системы с момента последней перезагрузки. Для этого используется OID .iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.0. Почти такого же эффекта можно добиться с помощью .iso.org.dod .internet.mgmt.mib-2.host.hrSystem.hrSystemUptime.0. Хотя тут стоит сделать маленькое примечание: второй OID показывает не время, прошедшее с последнего перезапуска системы, а момент последней инициализации SNMP.
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_command check_snmp_oid!.1.3.6.1.2.1.1.3.0!InK12345! ""! ""! ""!2c
}
Следующим интересным для нас моментом будет совокупность сервисов, отображающих количество занятых блоков разделов /, home, и совокупный процент использованных блоков физической и своп-памяти. Для того чтобы понять, где находятся необходимые сведения, посмотрите ветку .iso.org.dod.internet.mgmt.mib-2.host.hrStorage.hrStorage Table. Принцип анализа ветви довольно прост. В hrStorage Index содержится список уникальных идентификаторов, описывающих каждое устройство. А hrStorageType в свою очередь хранит типы устройств. hrStorageDesc заполнен текстовыми описаниями объектов. Для моей системы это выглядит так:
hrStorageDescr.2 = STRING: Real Memory
hrStorageDescr.3 = STRING: Swap Space
hrStorageDescr.4 = STRING: /
hrStorageDescr.5 = STRING: /home
hrStorageDescr.6 = STRING: /proc/bus/usb
В hrStorageAllocationUnits указан размер блока для каждого из устройств:
hrStorageAllocationUnits.2 = INTEGER: 1024 Bytes
hrStorageAllocationUnits.3 = INTEGER: 1024 Bytes
hrStorageAllocationUnits.4 = INTEGER: 4096 Bytes
hrStorageAllocationUnits.5 = INTEGER: 4096 Bytes
hrStorageAllocationUnits.6 = INTEGER: 1024 Bytes
Ну а hrStorageSize указывает, сколько блоков в каждом устройстве.
hrStorageSize.2 = INTEGER: 54156
hrStorageSize.3 = INTEGER: 216836
hrStorageSize.4 = INTEGER: 273087
hrStorageSize.5 = INTEGER: 196780
hrStorageSize.6 = INTEGER: 0
И наконец, самое интересное. Как вы уже, наверное, догадались, hrStorageUsed содержит данные о том, сколько блоков занято на каждом из устройств.
hrStorageUsed.2 = INTEGER: 52564
hrStorageUsed.3 = INTEGER: 11220
hrStorageUsed.4 = INTEGER: 235014
hrStorageUsed.5 = INTEGER: 8755
hrStorageUsed.6 = INTEGER: 0
Теперь дело за малым: высчитать, сколько блоков соответствуют заполнению устройств на 80% и 90%. И затем создать на основе этих данных правила проверки.
В качестве примера приведем описание сервиса, показывающего, как обстоят дела с заполнением корневого раздела.
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_snmp_oid!.1.3.6.1.2.1.25.2.3.1.6.4!InK12345!218470!245778!blocks!2c
}
Надеюсь, что на основе приведенного примера вы сможете создать описание всех необходимых сервисов. В мире UNIX-систем большинство задач можно решить разными способами. Сейчас вы в этом убедитесь. Давайте в очередной раз расширим функциональность демона snmpd, внеся в snmpd.conf следующие строчки.
disk / 180000
disk /home 760000
Таким образом, мы указываем, что хотим следить за свободным местом на разделах /и home еще одним способом. Вышеуказанные строки говорят демону snmp, что мы хотим установить флаг ошибки в случае, если на разделе /занято 180 Мб, а /home заполнен на 760 Мб. Впрочем, ничего страшного не случится, если ограничения не устанавливать вовсе. Кстати, стоит отметить, что ограничение можно описывать не только в килобайтах, но и в процентах. Теперь интересующие нас данные находятся внутри ветви .iso.org.dod.internet.private.enterprises.ucdavis.dskTable.dskEntry. Принцип построения таблицы стандартен. Идентификатор dskPath содержит данные об именах разделов.
dskPath.1 = STRING: /
dskPath.2 = STRING: /home
dskDevice устанавливает соответствие между разделами и физическими устройствами диска.
dskDevice.1 = STRING: /dev/sda1
dskDevice.2 = STRING: /dev/sda6
В dskMinimum dskMinPercent содержатся пороговые значения для поднятия флага ошибки. Соответственно, dskTotal, dskAvail, dskUsed отображают общее, доступное и задействованное пространство дисков. Следующая ветвь, называемая dskPercent, для нас наиболее интересна, так как содержит величину заполнения дисков в процентах.
dskPercent.1 = INTEGER: 86
dskPercent.2 = INTEGER: 4
Именно ее мы и будем контролировать. Конечно, можно контролировать состояние ветвей dskErrorFlag и dskErrorMsg.
dskErrorFlag.1 = INTEGER: 1
dskErrorFlag.2 = INTEGER: 0
dskErrorMsg.1 = STRING: /: less than 80% free (= 86%)
dskErrorMsg.2 = STRING:
Но это не очень удобно, так как в этом случае у системы есть лишь два состояния – «нормальное» и «критическое». Соответственно, нет промежуточного перехода в виде состояния «предупреждение». Разобравшись с теорией, давайте создадим сервис, который будет контролировать состояние раздела /новым способом.
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_command check_snmp_oid!.1.3.6.1.4.1.2021.9.1.9.1!InK12345!80!90!%
}
Думаю, создать сервисы, выполняющие проверку остальных разделов, вы сможете сами. Идем дальше. Если мы хотим следить за загрузкой процессора, добавляем в snmpd.conf вот это:
load 12 20 30
Этой строкой мы говорим демону, что желаем видеть статистику нагрузки на процессор за последнюю минуту, за пять и пятнадцать минут. К сожалению, интервалы жестко закодированы, и изменить их невозможно. И, как обычно, указываем необязательные пороговые ограничения в 12%, 20% и 30%, при превышении которых snmpd будет устанавливать флаг ошибки. Смотрим ветку .iso.org.dod. internet.private.enterprises.ucdavis.laTable.laEntry и понимаем, что нам наиболее интересны подветви laLoad, laLoadInt, laLoadFloat.
В этих подветках содержатся одни и те же данные, но с разным округлением. Соответственно сервис для проверки загрузки процессора за последнюю минуту будет выглядеть вот так:
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_command check_snmp_oid!.1.3.6.1.4.1.2021.10.1.5.1!InK12345!60!90!%
}
Следующей интересной для нас особенностью является возможность запускать сторонние скрипты при получении того или иного SNMP-запроса. И опять добавляем в snmpd.conf новые строки:
exec users /bin/sh /usr/bin/count_users.sh
exec mailqueue /bin/sh /usr/bin/count_mail.sh
Затем создаем файлы count_users.sh count_mail.sh:, с их помощью мы будем считать количество пользователей, работающих на данный момент в системе, и размер почтовой очереди postfix.
Содержимое файла count_users.sh:
who | wc -l
exit 0
Содержимое файла count_mail.sh:
mailq | tail -n 1 | cut -f5 -d " "
exit 0
Теперь смотрим, что у нас находится внутри ветки .iso.org.dod.internet.private.enterprises.ucdavis.extTable.extEntry.
extNames.1 = STRING: users
extNames.2 = STRING: mailqueue
extCommand.1 = STRING: /bin/sh /usr/bin /count_users.sh
extCommand.2 = STRING: /bin/sh / usr/bin/count_mail.sh
extResult.1 = INTEGER: 0
extResult.2 = INTEGER: 0
extOutput.1 = STRING: 1
extOutput.2 = STRING: 2
extErrFix.1 = INTEGER: 0
extErrFix.2 = INTEGER: 0
extErrFixCmd.1 = STRING:
extErrFixCmd.2 = STRING:
Нас интересует extOutput, в которой находится первая строка из того, что скрипт выводит на экран, и extResult с кодом возврата скрипта, переданным командой exit. Судя по приведенному выше списку значений, у нас в системе находится один пользователь, а в почтовой очереди есть два письма. Сервисы для проверки результатов работы обоих скриптов будут выглядеть так:
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_command check_snmp_oid!.1.3.6.1.4.1.2021.8.1.101.1!InK12345!20!30!users
}
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_command check_snmp_oid!.1.3.6.1.4.1.2021.8.1.101.2!InK12345!40!80!messages
}
Конечно, в реальном мире скрипты-проверки могут быть гораздо сложнее и возвращать с помощью команды exit коды, указывающие на те или иные проблемы в сети. В этом случае есть возможность с помощью добавочной опции execfix указывать на программу, запускаемую snmpd и отвечающую за попытки автоматического исправления ошибок, обнаруженных проверочным скриптом. К примеру, таким образом можно описать программу исправления аварийного положения с почтовой очередью.
execfix mailqueue /bin/sh /usr/bin/repair_mailqueue.sh
Конечно, эта возможность опциональна, но упомянуть о ней все же стоило. Любопытный читатель может спросить, а что делать, если мой скрипт выводит несколько строк полезной информации, и мне нужно считать их все до единой. Я отвечу, что это не проблема. Нужно всего лишь добавить в snmpd.conf вот такую строку:
exec .1.3.6.1.4.1.2021.50 multi_line_test /bin/sh/tmp/mytest.sh
И создать скрипт /tmp/mytest.sh следующего содержания.
echo "first line"
echo "second line"
exit 5
В результате осмотра ветви .1.3.6.1.4.1.2021.50 можно увидеть следующие данные:
.1.3.6.1.4.1.2021.50.1.1 = INTEGER: 1
.1.3.6.1.4.1.2021.50.2.1 = STRING: "multi_line_test"
.1.3.6.1.4.1.2021.50.3.1 = STRING: "/bin/sh /tmp/mytest.sh"
.1.3.6.1.4.1.2021.50.100.1 = INTEGER: 5
.1.3.6.1.4.1.2021.50.101.1 = STRING: "first line"
.1.3.6.1.4.1.2021.50.101.2 = STRING: "second line"
.1.3.6.1.4.1.2021.50.102.1 = INTEGER: 0
.1.3.6.1.4.1.2021.50.103.1 = ""
Как видите, и такой функционал нам вполне доступен. Следующая возможность, на которую хотелось бы обратить ваше внимание, – функция проверки размера файла. Итак, добавляем в snmpd.conf вот такую надпись:
file /tmp/tinka.txt 12
тем самым указывая, что файл не должен быть более 12 Кб. Затем смотрим, что хранит в себе ветка .iso.org.dod.internet .private.enterprises.ucdavis.fileTable.fileEntry:
fileIndex.1 = INTEGER: 1
fileName.1 = STRING: /tmp/tinka.txt
fileSize.1 = INTEGER: 15 kB
fileMax.1 = INTEGER: 12 kB
fileErrorFlag.1 = INTEGER: true(1)
fileErrorMsg.1 = STRING: /tmp/tinka.txt: size exceeds 12kb (= 15kb)
Написать соответствующий сервис, в общем-то, несложно, если мы хотим самостоятельно проверять размер файла.
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_command check_snmp_oid!.1.3.6.1.4.1.2021.15.1.3.1!InK12345!12!20!kbytes
}
Но есть и другой путь: можно опереться на появление кода и сообщения об ошибке в fileErrorFlag и fileErrorMsg. И все же мне кажется, что это не очень удобно.
Напоследок хотелось бы рассказать о возможности слежения за количеством процессов того или иного приложения, работающих в системе.
proc httpd 3 6
proc automount 1 1
proc csserver 2
Этими строками мы указываем snmpd, что в системе должно быть от двух до четырех процессов httpd и только один automount. В то же время программа csserver вообще может быть не запущена, но если она все же работает, то процессов не должно быть более двух. Если же минимальный и максимальный пороги не указаны, то процессов может быть сколько угодно. Давайте посмотрим, что snmpd нам скажет в ответ на такие приказания. Для этого открываем ветвь .iso.org.dod.internet.private.enterprises.ucdavis.prTable.prEntry.
prIndex.1 = INTEGER: 1
prIndex.2 = INTEGER: 2
prIndex.3 = INTEGER: 3
prNames.1 = STRING: httpd
prNames.2 = STRING: automount
prNames.3 = STRING: csserver
prMin.1 = INTEGER: 3
prMin.2 = INTEGER: 1
prMin.3 = INTEGER: 0
prMax.1 = INTEGER: 6
prMax.2 = INTEGER: 1
prMax.3 = INTEGER: 3
prCount.1 = INTEGER: 1
prCount.2 = INTEGER: 1
prCount.3 = INTEGER: 0
prErrorFlag.1 = INTEGER: 1
prErrorFlag.2 = INTEGER: 0
prErrorFlag.3 = INTEGER: 0
prErrMessage.1 = STRING: Too few httpd running (# = 1)
prErrMessage.2 = STRING:
prErrMessage.3 = STRING:
prErrFix.1 = INTEGER: 0
prErrFix.2 = INTEGER: 0
prErrFix.3 = INTEGER: 0
prErrFixCmd.1 = STRING:
prErrFixCmd.2 = STRING:
prErrFixCmd.3 = STRING:
Надеюсь, смысл приведенных данных всем ясен. Тут, как всегда, возможно два пути для слежения: самим контролировать значения из подветви prCount, либо опираться на код ошибки prErrorFlag и сообщение в prErrMessage. По аналогии с execfix можно использовать ключевое слово procfix для описания программы, запускаемой в случае, если с тем или иным процессом стряслось что-то неладное. Я думаю, что на основе примеров, приведенных выше, вы сможете легко самостоятельно написать определения нужных сервисов. Следующей интересной для нас веткой является .iso.org.dod.internet.private.enterprises.ucdavis.memory. В ней хранятся подробные данные о состоянии оперативной памяти. Для моей машины эта ветвь выглядит так:
memIndex.0 = INTEGER: 0
memErrorName.0 = STRING: swap
memTotalSwap.0 = INTEGER: 216836
memAvailSwap.0 = INTEGER: 209784
memTotalReal.0 = INTEGER: 54156
memAvailReal.0 = INTEGER: 9320
memTotalFree.0 = INTEGER: 219104
memMinimumSwap.0 = INTEGER: 16000
memShared.0 = INTEGER: 0
memBuffer.0 = INTEGER: 5728
memCached.0 = INTEGER: 13832
memSwapError.0 = INTEGER: 0
memSwapErrorMsg.0 = STRING:
Наибольший интерес вызывают OID memTotalSwap mem AvailSwap, означающие общий размер свопа и его свободную часть. Затем стоит обратить внимание на memTotalReal и memAvailReal, указывающие на размер физической памяти. Перспективнее всего следить за memAvailReal и memAvailSwap. Но тут есть определенные проблемы. Дело в том, что исчерпание физической памяти еще не означает для системы каких-то ужасных последствий, все ненужное в данный момент будет складироваться в своп. Поэтому выводить предупреждения по поводу того, что физическая память закончилась, не стоит. Сервис, следящей за этим компонентом системы, должен выглядеть так:
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_command check_snmp_oid!.1.3.6.1.4.1.2021.4.6.0!InK12345!""!""!kbytes!2c
}
И соответственно мониторинг заполнения свопа можно реализовать так же. Но это решение, на мой взгляд, не очень изящно. Можно сделать гораздо лучше. Давайте будем следить за показателем memTotalFree, который показывает общее количество свободной памяти системы. Это весьма удобно, так как он равен сумме memAvailReal и memAvailSwap. Тут возникает некоторая проблема с нетривиальностью проверки. Обычно ситуация обстоит так, что чем больше проверяемая величина, тем ближе мы к критическому порогу, но сейчас все наоборот. Необходимо сказать модулю, что, чем больше памяти нам доступно, тем лучше. Поэтому сервис будет выглядеть так:
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_command check_snmp_oid!.1.3.6.1.4.1.2021.4.11.0!InK12345!20000:10000!9999:0!kbytes!2c
}
Таким образом, сигнал «предупреждение» будет отправляться, если свободной памяти останется от двадцати до десяти тысяч байт, а критические оповещения появятся, как только планка опустится еще ниже.
Также неплохо было бы следить за сетевыми интерфейсами с помощью ветки .iso.org.dod.internet.mgmt.mib-2. interfaces.ifTable.ifEntry. Думаю, что примеров, приведенных в статье, достаточно, чтобы сделать это самостоятельно.
Разобравшись с проверками сервисов, работающих через snmp 2c, давайте посмотрим, как выполнить все то же самое с помощью третьей версии протокола. Зачем нам это нужно? Все очень просто: с точки зрения безопасности snmp 2с существенно лучше, чем версия 1, но, несмотря на это, в ней все же есть недостатки. Дело в том, что при ее использовании строки сообществ передаются по сети в открытом виде. Думаю, это не то, что нам хотелось бы получить. Изумленный читатель может сказать: «Давайте совсем откажемся от использования 2с». К сожалению, такой идеалистический подход не всегда возможно воплотить в жизнь. Иногда приходится использовать именно 2с, потому что не во всем имеющемся оборудовании есть поддержка третьей версии. К тому же, настройка snmpd для работы с третьей версией snmp – дело весьма нетривиальное. Ниже я расскажу как этого добиться «малой кровью».
Итак, приступим. В основе идеологии безопасности для третьей версии лежит понятие модуля безопасности пользователей USM (User-based Security Module). Он отвечает за хранение списка пользователей и их атрибутов. Соответственно каждый пользователь обозначается уникальным именем в терминах snmp, оно называется securityName. К нему привязываются протокол аутентификации и ключ аутентификации, соответственно, authProtocol и authKey. Вдобавок к этому существует протокол шифрования privProtocol и ключ шифрования privKey. Стоит отметить, что authKey и privKey генерируются на основе пароля, переданного пользователем. Пароль должен содержать не менее восьми символов.
Стандарт snmp версии 3 описывает три вида пакетов. Первый не подписывается и не шифруется. Второй: отправляющая сторона подписывает пакет ключем authKey с помощью протокола authProtocol. В качестве протокола генерации подписи на данный момент могут выступать алгоритмы MD5 или SHA. Третий: подписывает и плюс к этому данные пакета могут шифроваться с помощью протокола privProtocol и ключа privKey. В качестве протокола шифрования пока можно использовать только DES.
Ознакомиться подробнее с идеями, лежащими в основе USM, можно в RFC 2574.
Одной из самых странных идей, с которой приходится сталкиваться, является способ управлением пользователями, применяемый для третьей версии протокола. Для этого существует утилита snmpusm, но создать с ее помощью пользователя с нуля невозможно. Она позволяет лишь клонировать настройки существующего пользователя в атрибуты вновь создаваемого. Налицо проблема курицы и яйца. Нужно создать первого пользователя, но утилита для управления пользователями делать это не умеет.
Несколько раз перечитав man snmpusm, понимаем, что созданием легендарного первопользователя должен заниматься демон snmpd. Ничего не скажешь, весьма сильный ход и главное – какой нечеловеческой логикой это продиктовано.
Итак, нам нужно внести в snmp такие строки:
rwuser initial
rwuser nagios
rouser nagios
createUser initial MD5 t2inKES10er DES
Или их аналог с расширенным описанием VACM:
group MyRWGroup usm nagios
group MyROGroup usm nagios
group MyRWGroup usm initial
access MyRWGroup "" any noauth exact all all none
createUser initial MD5 t2inKES10er DES
Затем перезапускаем snmpd. Пользователь initial будет создан автоматически. В качестве пароля ему указано t2inKES10er, алгоритмом подписи пакетов назначаем MD5, а для шифрования данных используется DES. Создав первого пользователя, мы могли бы на этом остановиться. Но делать этого все же не стоит из соображений безопасности. Поэтому с помощью клонирования создаем нового пользователя по имени nagios.
# snmpusm -v3 -u initial -n "" -l authNoPriv -a MD5 -A t2inKES10er localhost create nagios initial
User successfully created.
|
Так как он унаследовал все настройки от initial, сразу же меняем ему пароль на что-нибудь труднозапоминаемое вроде R18nm12KDM.
# snmpusm -v3 -u nagios_user -n "" -l authNoPriv -a MD5 -A t2inKES10er localhost passwd t2inKES10er R18nm12KDM
SNMPv3 Key(s) successfully changed. |
Затем удаляем из snmpd.conf все упоминания о пользователей initial, а также все строки с MyRWGroup и rwuser. Тем самым мы лишили пользователя initial всех прав и отобрали у пользователя nagios возможность внесения изменений в данные snmp. Не забываем перезапустить демона snmpd, чтобы новые настройки вступили в силу. На сервере мониторинга для проверки выполняем команду:
# snmpget -v3 -u nagios -n "" -a MD5 -A R18nm12KDM -x DES 10.10.21.75 sysUpTime.0
system.sysUpTime.0 = Timeticks: (71318) 0:11:53.18 |
Из полученного ответа можно сделать вывод, что передача и обработка шифрованных и подписанных snmp пакетов работает как следует. Теперь давайте протестируем как модуль check_snmp умеет выполнять запросы с помощью третьей версии snmp.
# /usr/local/nagios/libexec/check_snmp -H 10.10.21.75 -o sysUpTime.0 -L authPriv -U nagios_user1 -a MD5 -A R18nm12KDM -X R18nm12KDM -P 3
system.sysUpTime.0 = Timeticks: (71352) 0:11:54.10 |
Теперь осталось создать описание своей команды check_snmp_oid_v3 в файле checkcommands.cfg. С помощью нее мы будем проводить мониторинг и вызывать модуль check_snmp.
define command{
command_name check_snmp_oid_v3
command_line $USER1$/check_snmp -H $HOSTADDRESS$ -o $ARG1$ -w $ARG2$ -c $ARG3$ -L $ARG4$ -U $ARG5$ -a $ARG6$
-A $ARG7$ -X $ARG8$ -u $ARG9$ -l "" -P $ARG10$
}
Теперь давайте создадим сервис Total Memory Free v3 для демонстрации того, как нужно использовать команду check_snmp_oid_v3. Записываем в services.cfg следующие строки:
define service{
use generic-service
host_name Linux
is_volatile 0
check_period 24x7
check_command check_snmp_oid_v3!.1.3.6.1.4.1.2021.4.11.0!20000:10000!9000:0!authPriv!nagios!MD5!R18nm12KDM!R18nm12KDM!kbytes!3
}
Теперь данные будут доставляться к нам в шифрованном виде. Напоследок стоит сказать, что все описания сервисов, предназначенные для сервера Linux, можно скопировать и, изменив имя машины, следить за FreeBSD.
На этой радостной ноте хотелось бы попрощаться, а заодно пообещать, что в следующей статье мы будем изучать настройку системы мониторинга для слежения за оборудованием знаменитой фирмы CISCO.
Литература:
- Бешков А. Мониторинг Windows-серверов с помощью Nagios. Часть 2. – Журнал «Системный администратор», №8, август 2003 г. или http://onix.opennet.ru/monitoring/nagios_win_2.html