Содержание статьи
Система мониторинга — один из ключевых компонентов сложных вычислительных систем, состоящих из множества серверов и сервисов. На протяжении многих лет стандартом де-факто в этой области был разработанный еще в прошлом веке Nagios, который прекрасно справляется со своей работой, но имеет явные проблемы с разрозненным API, медленным discovery и общей сложностью. Sean Porter решил исправить эти недочеты, написав новую систему мониторинга с нуля.
Sensu?
Sensu представляет собой monitoring router, то есть фреймворк, обеспечивающий механизмы, необходимые для сбора и накопления статистики работы серверов. На каждом сервере запускается агент (клиент) Sensu, использующий набор скриптов для проверки работоспособности сервисов, их состояния и сбора любой другой информации. С помощью RabbitMQ вся эта информация передается скриптам-обработчикам (handler) на сервере, которые решают, что с ней делать. Обработчик может отправлять информацию в Pagerduty, IRC, Twitter, отдавать ее другой системе мониторинга/визуализации (Graphite, например) или сохранять в базу данных. Все скрипты проверки и обработки могут быть написаны на любом языке и обычно состоят из нескольких строк.
Sensu написан на Ruby и задействует в своей работе RabbitMQ и Redis. Он имеет простую, ориентированную на обмен сообщениями (вместо пулинга, как в Nagios) масштабируемую архитектуру с акцентом на облачные окружения. Sensu поддерживает API плагинов Nagios, что открывает доступ к огромному количеству разных видов проверок, а также из коробки умеет работать с системами автоматической конфигурации Puppet и Chef. Код системы насчитывает всего несколько тысяч строк кода.
INFO
Sensu можно конфигурировать, описав все необходимые опции в одном файле /etc/sensu/config.json или раскидав их по нескольким конфигам внутри каталога /etc/sensu/conf.d, как показано в этой статье.
Большинство стандартных плагинов Sensu имеют набор опций командой строки, а также справку, которая либо находится в начале исходника, либо доступна с помощью опции -h.
Компоненты Sensu и терминология
Код Sensu разделен на несколько простых компонентов, каждый из которых в идеале должен работать на «своей» машине:
- Sensu-server — центральный компонент Sensu. Задача сервера — сбор и хранение информации, полученной от клиентов (агентов), установленных на серверах, подлежащих мониторингу. Сервер инициирует соединение с каждым агентом и ждет от них сообщений с информацией, которую затем добавляет в базу данных Redis. По-хорошему sensu-server должен работать на выделенной машине.
- Sensu-client — агент, собирающий информацию. Клиент должен быть запущен на каждой машине, которую необходимо мониторить. Его задача проста — запускать скрипты проверки и отправлять результат их работы серверу. Периодичность проверок может быть как задана сервером, так и определяться агентом (так называемые независимые проверки).
- Sensu-api — сервер, реализующий REST API. Нужен для отдачи накопленных сервером данных, а также данных топологии Sensu-сети для их последующей обработки и отображения. API может быть использован для принудительного запуска проверок и удаления агентов из сети. Обычно запускается на одной машине с сервером.
- Sensu-dashboard — веб-панель управления. Необходима для отображения информации о структуре сети Sensu и данных мониторинга в удобном виде. Может быть запущена либо рядом с сервером, либо на выделенной машине. Использует Sensu-api для коммуникации с сервером.
Для безопасного обмена данными между компонентами Sensu использует SSL-соединение поверх RabbitMQ и базовую HTTP-аутентификацию для доступа к API. Соединение между сервером и Redis не защищено, поэтому, если в сети предполагается использование нескольких Sensu-серверов и Redis будет вынесен на отдельную машину, потребуется ограничение доступа с помощью брандмауэра.
Установка
К сожалению, Sensu нет в официальных репозиториях Debian и Red Hat, но зато его авторы любезно подготовили DEB-, RPM- и даже MSI-пакеты. Рассмотрим установку на примере Debian/Ubuntu.
Добавляем ключ репозитория Sensu:
$ wget -q http://repos.sensuapp.org/apt/pubkey.gpg -O- | sudo apt-key add -
Добавляем репозиторий:
$ sudo -s
# echo "deb http://repos.sensuapp.org/apt sensu main" > /etc/apt/sources.list.d/sensu.list
Обновляем базу пакетов и устанавливаем:
# apt-get update
# apt-get install sensu
RabbitMQ и Redis
В результате установки пакета мы должны получить полный комплект компонентов Sensu в каталоге /opt/sensu, а также набор init-скриптов в /etc/init.d. Операцию установки необходимо выполнить как на машине-сервере (где будет работать sensu-server), так и на серверах, подлежащих мониторингу (где будет запущен sensu-client). Далее на машину-сервер следует установить RabbitMQ и Redis.
Устанавливаем Erlang и RabbitMQ:
$ sudo -s
# apt-get -y install erlang-nox
# wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
# apt-key add rabbitmq-signing-key-public.asc
# apt-get update
# apt-get install rabbitmq-server
# update-rc.d rabbitmq-server defaults
# /etc/init.d/rabbitmq-server start
Устанавливаем Redis:
# apt-get install redis-server
SSL-сертификаты
На машине-сервере необходимо сгенерировать SSL-сертификаты, которые будут использоваться для общения с клиентами. Сделать это можно с помощью скрипта ssl_certs.sh:
# cd /tmp
# wget http://sensuapp.org/docs/0.12/tools/ssl_certs.tar
# tar -xvf ssl_certs.tar
# cd ssl_certs
# ./ssl_certs.sh generate
Копируем сертификаты в каталог /etc/rabbitmq/ssl:
# mkdir -p /etc/rabbitmq/ssl
# cp sensu_ca/cacert.pem /etc/rabbitmq/ssl
# cp server/cert.pem /etc/rabbitmq/ssl
# cp server/key.pem /etc/rabbitmq/ssl
Создаем конфиг RabbitMQ (/etc/rabbitmq/rabbitmq.config), который заставит его ожидать SSL-соединения на 5671-м порту:
[
{rabbit, [
{ssl_listeners, [5671]},
{ssl_options, [{cacertfile,"/etc/rabbitmq/ssl/cacert.pem"},
{certfile,"/etc/rabbitmq/ssl/cert.pem"},
{keyfile,"/etc/rabbitmq/ssl/key.pem"},
{verify,verify_peer},
{fail_if_no_peer_cert,true}]}
]}
].
Перезапускаем RabbitMQ:
# /etc/init.d/rabbitmq-server restart
Создаем vhost /sensu внутри RabbitMQ и ответственного за него юзера sensu
rabbitmqctl add_vhost /sensu
rabbitmqctl add_user sensu ПАРОЛЬ
rabbitmqctl set_permissions -p /sensu sensu ".*" ".*" ".*"
WWW
Официальный сайт Sensu: sensuapp.org
Презентация с примерами использования Sensu: goo.gl/Odfz9a
Репозиторий плагинов: goo.gl/IaCFgs
Chef cookbook для быстрого развертывания Sensu: goo.gl/HaLurp
Sensu-CLI, утилита для управления Sensu из командной строки: goo.gl/wSVHKf
Настройка
Теперь у нас есть все необходимое, чтобы запустить сервер и агенты Sensu. Однако сначала нам необходимо создать конфиги. Их будет два: /etc/sensu/config.json — основной конфигурационный файл сервера, в котором достаточно прописать порты и адреса RabbitMQ, Redis, Sensu-api и Sensu-dashboard. В нашей конфигурации все эти компоненты будут работать на одной машине. Второй конфиг: /etc/sensu/conf.d/client.json. Его необходимо поместить как на Sensu-сервер, так и на машины-агенты. Содержимое первого конфига:
{
"rabbitmq": {
"ssl": {
"private_key_file": "/etc/sensu/ssl/key.pem",
"cert_chain_file": "/etc/sensu/ssl/cert.pem"
},
"port": 5671,
"host": "localhost",
"user": "sensu",
"password": "ПАРОЛЬ",
"vhost": "/sensu"
},
"redis": {
"host": "localhost",
"port": 6379
},
"api": {
"host": "localhost",
"port": 4567
},
"dashboard": {
"host": "localhost",
"port": 8080,
"user": "admin",
"password": "ПАРОЛЬ"
}
}
Здесь все стандартно, просто адреса, порты и пароли. Сертификаты, описанные в секции rabbitmq, были сгенерированы еще на прошлом шаге и доступны в каталогах /tmp/client/cert.pem и /tmp/client/key.pem. Их нужно всего лишь скопировать в каталог /etc/sensu/ssl/. Конфиг клиента совсем простой:
{
"client": {
"name": "ПРОИЗВОЛЬНОЕ-ИМЯ",
"address": "IP-АДРЕС",
"subscriptions": [ "all" ]
}
}
Этот конфиг нужно скопировать также на машины-агенты и придумать внятные имена для каждого (можно, например, использовать имя виртуальной машины или имя домена). Когда все будет сделано, активируем серверные компоненты Sensu на машине-сервере.
# update-rc.d sensu-server defaults
# update-rc.d sensu-client defaults
# update-rc.d sensu-api defaults
# update-rc.d sensu-dashboard defaults
Запускаем:
# /etc/init.d/sensu-server start
# /etc/init.d/sensu-api start
# /etc/init.d/sensu-client start
# /etc/init.d/sensu-dashboard start
На машинах-агентах запускаем только клиент:
# update-rc.d sensu-client defaults
# /etc/init.d/sensu-client start
Для проверки работы заходим по адресу http://admin:ПАРОЛЬ@IP-АДРЕС-СЕРВЕРА:8080.
INFO
Большинство стандартных плагинов Sensu имеют набор опций командой строки, а также справку, которая либо находится в начале исходника, либо доступна с помощью опции -h.
Мониторинг
Sensu запущен и готов к работе, но из-за отсутствия скриптов проверки на агентах и обработчиков на сервере его КПД равен нулю. Чтобы это исправить, мы должны либо написать скрипты самостоятельно, либо воспользоваться уже готовыми плагинами. Первый вариант мы рассмотрим позже, а пока попробуем выполнить проверку с помощью плагинов. Для этого сначала установим на машину-агент набор хелперов, необходимых для их работы:
# gem install sensu-plugin --no-rdoc --no-ri
Далее выберем подходящий для нашей задачи плагин. Все официальные плагины Sensu располагаются в репозитории на GitHub. Среди них есть, например, плагин apache-graphite.rb, который собирает статистику работы сервера с помощью mod_status и преобразует ее в формат Graphite; плагин check-dns.rb, который выполняет проверку работы DNS-резолвинга с помощью dig; check-http.rb для проверки доступности веб-сайтов и множество других.
Плагин check-procs.rb — один из самых простых и универсальных. Он проверяет наличие в системе процесса с заданным именем и возвращает информацию о нем обратно. Основная область применения данного плагина — проверка сервисов на жизнеспособность. Попробуем использовать его для реализации простой проверки на то, что nginx еще не упал. Скачиваем плагин из репозитория на машину-агент:
# wget -O /etc/sensu/plugins/check-procs.rb \
https://raw.github.com/sensu/sensu-community-plugins/master/plugins/processes/check-procs.rb
# chmod 755 /etc/sensu/plugins/check-procs.rb
Далее возвращаемся на машину-сервер и создаем новый конфиг. Дадим ему имя /etc/sensu/conf.d/check_nginx.json:
{
"checks": {
"nginx_check": {
"handlers": ["default"],
"command": "/etc/sensu/plugins/check-procs.rb -p nginx -C 1 ",
"interval": 60,
"subscribers": [ "webservers" ]
}
}
}
В целом все это означает, что каждые 60 секунд сервер будет отправлять клиентам, подписанным на канал "webservers", запрос на выполнение команды «/etc/sensu/plugins/check-procs.rb -p nginx -C 1» и ожидать от них результат исполнения, который будет обработан дефолтовым скриптом-обработчиком. Чтобы машина-агент начала принимать эти запросы и обрабатывать их, мы должны немного изменить ее клиентский конфиг (/etc/sensu/conf.d/client.json), добавив в него такую строку:
"subscriptions": [ "webservers" ]
Перезапускаем Sensu-сервер:
# /etc/init.d/sensu-server restart
и клиент на машине-агенте:
# /etc/init.d/sensu-client restart
В логах /var/log/sensu/sensu-server.log (на сервере) и /var/log/sensu/sensu-client.log (на агенте) должна появиться информация об активности, содержащая строки типа «[subscribe] -- received check request» и «[publisher] -- publishing check request». В том случае, если nginx упадет, в панели управления сразу появится предупреждающее сообщение, однако никаких оповещений по почте или другим средствам связи мы не получим. Это потому, что в качестве обработчика мы указали default, который, по сути, не делает ничего.
Чтобы получать уведомления удобным для нас способом, мы должны создать обработчик (handler). Как и в случае с проверками, это может быть скрипт, уже готовый плагин или даже просто консольная команда. Все официальные плагины хранятся во все том же репозитории на GitHub. Среди них можно найти, например, mailer.rb, позволяющий отправлять письма через указанный SMTP-сервер, irc.rb, отсылающий уведомления в указанный IRC-канал, twitter.rb и десятки других. Кроме оповещений, плагины могут формировать вывод для Graphit, Librato и других систем мониторинга.
Самый простой обработчик — это обычная консольная команда, которой через канал передается информация о событии. Можно, например, использовать команду mail, чтобы предупреждения уходили на указанный почтовый ящик. Для этого достаточно создать новый конфиг на сервере (/etc/sensu/conf.d/handler_email.json):
{
"handlers": {
"email": {
"type": "pipe",
"command": "mail -s 'sensu alert' your@address"
}
}
}
Наверное, это самый простой обработчик из всех возможных. Чтобы наш плагин проверки nginx использовал его, достаточно изменить конфиг /etc/sensu/conf.d/check_nginx.json, поставив вместо строки
"handlers": ["default"]
такую:
"handlers": ["default", "email"]
и перезапустить сервер Sensu:
# /etc/init.d/sensu-server restart
Таким же образом можно подключать любой из доступных в репозитории Sensu плагинов. Большинство из них используют канал (опция "pipe") для передачи данных, но можно указать "tcp" или "udp" для отдачи информации на удаленный хост, а также "ampq" для отправки сообщений через RabbitMQ.
Независимые проверки
Кроме проверок, инициируемых сервером, Sensu также поддерживает так называемые standalone checks. Это проверки, которые запускает сам агент и сам же отправляет результат серверу. Они почти не отличаются от стандартных проверок, кроме того, что агент не должен быть подписан ни на какой канал, чтобы инициировать их. Например, независимая проверка на жизнеспособность cron будет выглядеть так:
{
"checks": {
"cron_check": {
"handlers": ["default"],
"command": "/etc/sensu/plugins/check-procs.rb -p crond -C 1 ",
"interval": 60,
"standalone": true
}
}
}
Собственные скрипты
Как ты уже понял, роль скриптов проверки и обработки в Sensu могут выполнять любые команды и скрипты на любых языках. В случае с обработчиками это просто команда, способная принимать данные через канал STDIN. Скрипты проверки несколько сложнее, они используют API Nagios, следуя которому скрипт должен генерировать вывод в STDOUT или STDERR, а для индикации успешности проверки использовать exit code, где 0 — это «все ОК», 1 — предупреждение, а 2 — критическая ошибка.
Кроме этого, Sensu позволяет использовать проверки для получения статистических данных (опция "type": "metric"). В этом случае тоже используется API Nagios, но формат вывода будет содержать не просто сообщение об ошибке, а отформатированный набор данных. Например, в случае с плагином load-metrics.rb, возвращающим текущий loadavg, он будет выглядеть примерно так:
absinthe.local.load_avg.one 0.89 1365270842
absinthe.local.load_avg.five 1.01 1365270842
absinthe.local.load_avg.fifteen 1.06 1365270842
Какого-то особого стандарта по формирования вывода здесь нет, и он зависит от используемого обработчика.
Выводы
Sensu — отличный конструктор для построения сложных систем мониторинга, который не требует специальных знаний, изучения языков программирования и долгого чтения документации. Простота — один из основных козырей Sensu, и как только фреймворк будет интегрирован в популярные дистрибутивы, а среди плагинов появится все, что только может понадобиться, мы получим прекрасный инструмент для быстрого создания самых разных систем мониторинга.