Monit - наблюдатель за системными процессами
Monit - самостоятельный демон, работающий от пользователя root. Демон работает на Linux, Free/Net/OpenBSD, SUN Solaris и некоторых других UNIX-системах. Это OpenSource проект, у которого есть “старший брат” - коммерческий проект MMonit. Последний обладает более широким функционалом в вопросе массового мониторинга, межсетевого взаимодействия и составления отчетов. Идея авторов проста - для одиночного сервера используем Monit, для большой сетевой фермы - MMonit.
В зависимости от настроек, демон может проверять:
- Существование процесса по PID
- Работу определенного порта (TCP/UDP)
- Ответ определенного протокола по определенному порту (SMTP, SSH, HTTP…)
- Ресурсы, занимаемые процессом (CPU time/RAM)
- MD5 checksum
- Объем и свободное пространство в файловой системе
- Количество активных (и суммарное) i-node-в
- Права доступа к файлу или каталогу
Никто не запрещает комбинировать различные методы проверки. Для одного объекта проверки (тесты) зависят друг от друга, то есть сначала проводится тест1, если он прошел без ошибок - тест2, затем - тест3 и т.д.
В случае, если какой-то тест не пройден, monit может:
- Остановить, стартовать или перезапустить демона
- Подождать определенное время
- Уведомить админа (почтовым сообщением)
- Примонтировать, отмонтировать или перемонтировать файловую систему
- Запустить отдельный скрипт (заранее написаный админом), причем передать ему определенные параметры (имя процеса/текст ошибки и т.д.)
Действия также никто не запрещает комбинировать, например: Если HTTPd занимает более 200 мегабайт - ждать минуту, если ничего не изменилось - перезапустить сервис, если это также не помогло - прождать пять минут. Если и это не помогло - остановить сервис и уведомить админа письмом.
И еще. У Monit есть собственный http-сервер. Злоупотреблять им не стоит, так как работает он с рутовыми привелегиями, но иметь доступ к веб-консоли может быть крайне полезным. Вебсервер будет рассмотрен отдельно, в этой же статье.
Установка и настройка
Монит есть практически во всех широко распространенных дистрибутивах. В Debian, CentOS и Suse он так и называется. Во FreeBSD лежит в {PORTS}/sysmgmt/monit. Ставится он стандартным для операционной системы способом, и я не буду на нем остонавливатся. Результатом установки будет собственно демон (monit) и файл конфигурации, который живет тут:
# Linux, Solaris:
/etc/monit/monitrc
# FreeBSD/OpenBSD/NetBSD
/usr/local/etc/monit/monitrc
Конфиг очень подробно документирован, его рекомендуется почитать. Там есть подробные примеры и вообще много чего интересного. В принципе большую часть дефолтных настроек можно не трогать, ограничившись только необходимыми изменениями:
# процесс работает как демон, цикл проверки - 120 секунд.
# длительность цикла можно менять, это основная еденица времени для monit.
# Раз в цикл срабатывают проверки и выполняются команды от админа,
# присланые через веб-интерфейс
set daemon 120
# сервера, через которые пойдет почтовое уведомление.
# Можно делать несколько, очередность срабатывания повторяет очередность внесения
set mailserver mail.zooclub.ru 10025,
localhost
# кто получит уведомление?
set alert [email protected]
Информацию о том, что monit должен проверять, можно хранить и в отдельном файле (файлах), которые подключаются в основной конфиг командой include:
# один файл
include /etc/devel/monitcheck.monitconf
# все файлы с расширением из папки.
include /etc/stable/monit/*
Мне кажется, что удобнее хранить проверку каждого сервиса в отдельном файле - это облегчает отладку и упрощает администрирование.
Мониторим состояние сервера в целом:
check system ws1.zooclub.ru
if loadavg (1min) > 4 then alert
if loadavg (5min) > 2 then alert
if memory usage > 75% then alert
if cpu usage (user) > 90% then alert
if cpu usage (system) > 40% then alert
if cpu usage (wait) > 20% then alert
Файловые системы:
# /etc/stable/monit/filesystem.conf
# проверяем устройство по точке монтирования.
# Можно проверять диски напрямую (/dev/hda).
# C LVM и прочими логическими "дисками" этот фокус не прокатит,
# их проверять можно только по точке монтирования и никак иначе.
check device homefs with path /home
start program = "/bin/mount /home"
stop program = "/bin/umount /home"
if failed permission 755 then alert
if failed uid root then alert
# Если места остается меньше 20% минимум пять проверок за последние 15
# бить в набат и больше ничего не делать.
# При любой своей активности monit будет предупреждать админа письмом.
if space usage > 80% for 5 times within 15 cycles then alert
# Место кончилось, отмонтировать файлсистему
if space usage > 99% then stop
# аналогично про i-nodes.
if inode usage > 80% then alert
if inode usage > 99% then stop
group server
check device rootfs with path /
start program = "/bin/mount /"
# Потерять / во время работы сервера - безрадостная перспектива.
# По этому если дело плохо - просто перемонтируем его в read-only
stop program = "/bin/mount -o remount,ro /"
if failed permission 755 then unmonitor
if failed uid root then unmonitor
if space usage > 80% for 5 times within 15 cycles then alert
if space usage > 99% then stop
if inode usage > 80% then alert
if inode usage > 99% then stop
group server
check device bootfs with path /boot
start program = "/bin/mount /boot"
stop program = "/bin/mount -o remount,ro /boot"
# эта конструкция "отключит" тестирование файлсистемы, если права на папку - не 755
if failed permission 755 then unmonitor
if failed uid root then unmonitor
if space usage > 80% for 5 times within 15 cycles then alert
if space usage > 99% then stop
if inode usage > 80% then alert
if inode usage > 99% then stop
group server
Теперь проверим работу веб-сервера apache:
# /etc/stable/monit/apache.conf
# проверка файла (размер, права доступа и тп):
check file apache_bin with path /usr/local/apache/bin/httpd
if failed checksum and
# sum - это стандартный md5-хэш.
# Его можно получить, натравив программу md5sum на нужный файл
expect the sum 8f7f419955cefa0b33a2ba316cba3659 then unmonitor
if failed permission 755 then unmonitor
if failed uid root then unmonitor
if failed gid root then unmonitor
# отдельное письмо на отдельный адрес и с отдельным содержимым.
alert [email protected] on {
checksum, permission, uid, gid, unmonitor
} with the mail-format { subject: Alarm! }
group server
# проверка процесса осуществляется по pid-файлу. Путь к pid-файлу всегда абсолютный
check process apache with pidfile /var/run/apache2.pid
start program = "/etc/init.d/apache2 start"
stop program = "/etc/init.d/apache2 stop"
if cpu > 60% for 2 cycles then alert
# если вебсервер сожрал 80% процессрного времени
# и не отдает его пять циклов проверки подряд - рестартуем его
if cpu > 80% for 5 cycles then restart
# аналогично по суммарной памяти, которую он поглотил.
if totalmem > 500.0 MB for 5 cycles then restart
if children > 250 then restart
# если load average сервера за 5 минут больше 10 8 циклов подряд - вырубаем.
if loadavg(5min) greater than 10 for 8 cycles then stop
# вот тут самое интересное - многоэтапная проверка:
# первый шаг - подключение на 80 порт, протокол http
if failed host 127.0.0.1 port 80 protocol http
# если получилось - запрашиваем файл /index.html
and request "/index.html"
with timeout 15 seconds
# а если что-то из цепочки не получилось - рестартуем демон
then restart
# проверка HTTP-SSL.
# Монит отдельно рассматривает SSL, и отдельно - защищаемый протокол.
# Для того, чтобы иметь возможность проводить такие проверки -
# нужно собрать monit с поддержкой SSL.
# Любители FreeBSD - будьте внимательны при сборке!
if failed port 443 type tcpssl protocol http
and request "/test.html"
with timeout 15 seconds
then restart
# если за последние пять циклов проверки было три рестарта или больше
# - пропускаем один цикл проверки.
if 3 restarts within 5 cycles then timeout
# проверку имеет смысл проводить только,
# если пройдена первая проверка (которая права доступа и проч).
# В противном случае все тесты безсмысленны.
depends on apache_bin
group server
OpenSSHD:
check process sshd with pidfile /var/run/sshd.pid
start program "/etc/init.d/ssh start"
stop program "/etc/init.d/ssh stop"
if failed port 22 protocol ssh then restart
if 5 restarts within 5 cycles then timeout
group server
OpenVPN. Проверяем только наличие процесса:
check process openvpn with pidfile /var/run/openvpn.link1.pid
group system
start program = "/etc/init.d/openvpn start"
stop program = "/etc/init.d/openvpn stop"
if 5 restarts within 5 cycles then timeout
PostgreSQL. Проверяем доступность через TCP-порт и сокет
check process postgres with pidfile /var/run/postgresql/main.pid
group database
start program = "/etc/init.d/postgresql start"
stop program = "/etc/init.d/postgresql stop"
if failed unixsocket /tmp/.s.PGSQL.5432 protocol pgsql then restart
if failed host 127.0.0.1 port 5432 protocol pgsql then restart
if 5 restarts within 5 cycles then timeout
group database
Исчерпывающий список протоколов и вариантов проверки можно почерпнуть в документации. Правда, она на англ языке.
Веб-интерфейс
Как я уже писал во вступлении, у monit есть небольшая, но довольно полезная вебморда. Пример настройки:
#включить веб-интерфейс на определенный порт
set httpd port 10001 and
#включить SSL
ssl enable
#где взять pem-файл. Нужен для ssl, подробно ниже
pemfile /etc/monit/monit.pem
#на каком адресе (интерфейсе) слушать.
#если адрес не указать - слушать будет на всех
use address 10.10.10.21
#разрешить доступ только с определенных адресов
#строго рекомендуется!
allow 10.10.10.22/32
allow 10.10.12.0/24
#разрешить доступ только знающим пароль.
#пароль, к сожалению, хранится в открытом виде
allow senegami:aoLouch0aingahce
allow logan:Jefae2Othaitae1S
Теперь о pem-файле. Веб-сервер monit довольно примитивный, и ему нужно иметь ssl сертификат, ключ от него и DH-файл в одном объекте. Собственно, он и называется pem-файлом. Готовится следующим образом. Сначала создадим шаблон для сертификата:
----- BEGIN:monit.cnf -----
RANDFILE = ./openssl.rnd
[ req ]
default_bits = 1024
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type
[ req_dn ]
countryName = Country Name (2 letter code)
countryName_default = RU
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = NorthWest
localityName= Locality Name (eg, city)
localityName_default= Saint Petersburg
organizationName= Organization Name (eg, company)
organizationName_default= AnyOne LLC
organizationalUnitName= Organizational Unit Name (eg, section)
organizationalUnitName_default= Net
commonName= Common Name (FQDN of your server)
commonName_default= ws1.zooclub.ru
emailAddress= Email Address
emailAddress_default= [email protected]
[ cert_type ]
nsCertType = server
----- END:monit.cnf -----
Разумеется, нужно поменять значения под необходимые конкретно вам
Затем соберем из шаблона сертификат:
openssl req -new -x509 -days 720 -nodes \
-config ./monit.cnf -out /etc/monit/monit.pem \
-keyout /var/certs/monit.pem
#Генерируем число Диффи-Хеллмана и прячем его в тот же файл
openssl gendh 512 >> /etc/monit/monit.pem
#проверяем читаемость сертификата
openssl x509 -subject -dates -fingerprint -noout -in /etc/monit/monit.pem
#Поскольку в файле лежит серкретный ключ сертификата - уменьшим права доступа
chmod 400 /etc/monit/monit.pem
openssl gendh 512 >> /etc/monit/monit.pem
После чего перезапускаем монит и любуемся :)