Піднімаємо мікро моніторинг на icinga2 з мінімальними витратами

Іноді є бажання контролювати ситуацію в різнорідних мережах, окремих хостах за натом або просто моніторити комп'ютери батьків або друзів, але ресурсів для цього майже немає. Будемо шукати рішення з допомогою icinga2. Зараз у VDS провайдерів є пропозиції VDS серверів в мінімальних конфігураціях за смішні гроші. Що ж, скористаємося цим.

Наприклад, сервер з одним ядром, 512 Мб оперативної пам'яті і жорстким диском на 10 Гб обійдеться всього в 90 рублів в місяць. Встановимо icinga2 на такий сервер. Але для економії ресурсів не будемо зберігати дані і замість стандартного веб-інтерфейсу (icingaweb2) зробимо свій який буде звертатися до API icinga2.

Установка icinga2 вже не одноразово описувалася і не викликає великих труднощів. Коротко пробіжимося по основних етапів установки. Будемо встановлювати на ubuntu.

wget -O - http://debmon.org/debmon/repo.key 2>/dev/null | apt-key add -
echo 'deb http://debmon.org/debmon debmon-jessie main' >/etc/apt/sources.list.d/debmon.list
apt-get update
apt-get install icinga2


Запускаємо візард:

icinga2 node wizard

Ми хочемо налаштувати майстер хост, тому відповідаємо «ні» на перше питання візарда. Помічник по налаштуванню генерує сертифікат, робить початкову настройку конфігураційних файлів і включає функціональність api, яка за замовчуванням вимкнено.

Після внесення змін у конфігурацію, якщо ми хочемо, щоб вони вступили в силу необхідно перезавантажити сервіс:
service icinga2 reload


Якщо щось пішло не так, дивимося що не подобається нашій системі і розбираємося з помилками:

service icinga2 checkconfig


Сервер готовий до здійснення моніторингу. Приступаємо до установки icinga2 на Windows хост, який буде моніторити. З установкою Windows клієнта не повинно виникнути проблем, потрібен NET. Framework. Запускаємо візард, при бажанні можна змінити ім'я хоста (реєстр в імені має значення), додаємо сервер, вказуємо, що ми хочемо приймати команди і конфігурацію з майстра.

image

На сервері генеруємо інсталяційний квиток для клієнта і вводимо в клієнтському візарді:

icinga2 pki ticket --cn TS01E.PSHOME.local


Після закінчення роботи клієнтського візарда і запуску сервісу, перевіряємо створену ноду на сервері і оновлюємо конфігурацію:

icinga2 node list
icinga2 node update-config
service icinga2 reload

Аналогічним чином встановлюємо інші клієнти. Тепер наші хости моніторяться.

Приступаємо до додаткових налаштувань конфігурації. В першу чергу пропишемо свій email у файлі /etc/icinga2/conf.d/users.conf, на який будуть надходити сповіщення:

object User "icingaadmin" {
import "generic-user"
display_name = "Icinga 2 Admin"
groups = [ "icingaadmins" ]
email = "icingaadmin@yandex.ru"
}
object UserGroup "icingaadmins" {
display_name = "Icinga 2 Admin Group"
}


Налаштуємо smtp на сервері, якщо це ще не зроблено:

apt-get install ssmtp

Зазначимо пошту для користувача з під якого працює icinga2:
echo nagios:icingarobot@yandex.ru >> /etc/ssmtp/revaliases


Приблизний вміст файлу /etc/ssmtp/ssmtp.conf для відправки пошти через smtp Яндекса:

root=postmaster
mailhub=smtp.yandex.ua:465
hostname=icinga-failover
FromLineOverride=YES
AuthUser=icingarobot@yandex.ru
AuthPass=password
UseTLS=YES


Так як у нас моніторинг не зберігає дані, нам потрібно щось більш оперативний, ніж email. Налаштуємо pushover. Для цього створимо скрипт /etc/icinga2/scripts/pushovernotify.sh:

#!/bin/sh
curl -F "token=$PUSHOVERTOKEN" \
-F "user=$PUSHOVERUSER" \
-F "title=$PUSHOVERTITLE" \
-F "message=$PUSHOVERMESSAGE" \
-F "html=$PUSHOVERHTML" \
https://api.pushover.net/1/messages
exit 0


Додамо в файл /etc/icinga2/conf.d/commands.conf наступні рядки:

object NotificationCommand "pushover-host-notification" {
import "plugin-notification-command"
command = [ SysconfDir + "/icinga2/scripts/pushovernotify.sh" ]
env = {
PUSHOVERUSER = "$user.vars.pushover_user$"
PUSHOVERTOKEN = "$user.vars.pushover_token$"
PUSHOVERTITLE = "Icinga2 Host Notification"
PUSHOVERMESSAGE = " <b>$notification.type$</b> <a href='http://наш_веб_сервер/host.php?host=$host.display_name$'>$host.display_name$</a> <b>$host.state$</b> $icinga.long_date_time$"
PUSHOVERHTML = "1"
}
}

object NotificationCommand "pushover-service-notification" {
import "plugin-notification-command"
command = [ SysconfDir + "/icinga2/scripts/notifybypushover2.sh" ]
env = {
PUSHOVERUSER = "$user.vars.pushover_user$"
PUSHOVERTOKEN = "$user.vars.pushover_token$"
PUSHOVERTITLE = "Icinga2 Notification Service"
PUSHOVERMESSAGE = " <b>$notification.type$</b> <a href='http://наш_веб_сервер/host.php?host=$host.display_name$'>$host.display_name$</a> $service.display_name$ <b>$service.state$</b> $icinga.long_date_time$"
PUSHOVERHTML = "1"
}
}


Додамо в файл /etc/icinga2/conf.d/templates.conf наступні рядки:

template Notification "pushover-host-notification" {
command = "pushover-host-notification"
states = [ Up, Down ]
types = [ Problem, Acknowledgement, Recovery, Custom,
FlappingStart, FlappingEnd,
DowntimeStart, DowntimeEnd, DowntimeRemoved ]
period = "24x7"
}
template Notification "pushover-service-notification" {
command = "pushover-service-notification"
states = [ OK, Warning, Critical, Unknown ]
types = [ Problem, Acknowledgement, Recovery, Custom, FlappingStart, FlappingEnd, DowntimeStart, DowntimeEnd, DowntimeRemoved ]
period = "24x7"
}


Додамо в файл /etc/icinga2/conf.d/notifications.conf наступні рядки:

apply Notification "pushover-icingaadmin" to Host {
import "pushover-host-notification"
user_groups = host.vars.notification.mail.groups
users = host.vars.notification.mail.users 
assign where host.vars.notification.mail
interval = 0 // disable re-notification
}
apply Notification "pushover-icingaadmin" to Service {
import "pushover-service-notification"
user_groups = host.vars.notification.mail.groups
users = host.vars.notification.mail.users
assign where host.vars.notification.mail
interval = 0 // disable re-notification
}


Додамо ключі pushover у файлі /etc/icinga2/conf.d/users.conf
object User "icingaadmin" {
import "generic-user"
display_name = "Icinga 2 Admin"
groups = [ "icingaadmins" ]
email = "icingaadmin@yandex.ru"
vars.pushover_user = "1111111111111111111111111111111"
vars.pushover_token = "1111111111111111111111111111111"
}


На даному етапі ми вже чуємо, коли щось не в порядку з нашими об'єктами моніторингу, звичайно, хотілося б бачити загальну картину. Для цього нам знадобиться веб сервер з php, який, наприклад, можна розмістити на домашньому комп'ютері або на тому ж VDS, що і icinga2.

Отже, малюємо веб-морду для запитів до API icinga2. Візард налаштування так-же створив файл /etc/icinga2/conf.d/api-users.conf з якого беремо ім'я користувача і пароль для доступу до api. Проект веб інтерфейсу складається з сторінки відображає список всіх хостів і сторінки детальних відомостей окремого хоста. З ходячи з припущень, що розміщення веб інтерфейсу може бути на окремому сервері, використовуємо написаний на швидку руку php скрипт для проксі серверів крос-доменних запитів.
Текст скрипта icinga-proxy.php:
<?php
require_once( "config.php" );

if (!empty($_GET['host'])) {
$host = trim($_GET['host']); 
$json_url = "https://".ICINGA2_HOST.":5665/v1/objects/hosts/".$host."/";

try {
$ch = curl_init();

if (FALSE === $ch)
throw new Exception('failed to initialize');
curl_setopt($ch, CURLOPT_URL, $json_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
$content = curl_exec($ch);
echo $content;

if (FALSE === $content)
throw new Exception(curl_error($ch), curl_errno($ch));

} catch(Exception $e) {
trigger_error(sprintf(
'Curl failed with error #%d: %s',
$e->getCode(), $e->getMessage()),
E_USER_ERROR);
}

} else {

if (!empty($_GET['domain'])) {
$domain = trim($_GET['domain']);
$json_url = "https://".ICINGA2_HOST.":5665/v1/objects/hosts?filter=match%28%22*" . $domain . "*%22%2Chost%2Ename%29";
} else {
$json_url = "https://".ICINGA2_HOST.":5665/v1/objects/hosts";
}

try {

$ch = curl_init();

if (FALSE === $ch)
throw new Exception('failed to initialize');
curl_setopt($ch, CURLOPT_URL, $json_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
$content = curl_exec($ch);
echo $content;

if (FALSE === $content)
throw new Exception(curl_error($ch), curl_errno($ch));

} catch(Exception $e) {
trigger_error(sprintf(
'Curl failed with error #%d: %s',
$e->getCode(), $e->getMessage()),
E_USER_ERROR);
}
}

?>


Список всіх хостів хочеться бачити в актуальному стані і бажано без перезавантаження сторінки, для цього скористаємося jQuery.GetJSON().

Текст скрипта icinga-get-host.js:
$(document).ready(function () {

$('#get-data').click(function () {
var showData = $('#show-data');


var www_path = "";
var json_url = 'icinga-proxy.php?domain=' + domainFilter.value;

$.getJSON(json_url, function (data) {

var data0 = data.results;
var items = data0.map(function (item) {

var hostdown = item.attrs.state;
var icon_image_src = item.attrs.icon_image;
var hostdown_bage;
var hostdown_bage_span;

if (hostdown == 1) {

hostdown_bage = "<span class='mdl-badge mdl-badge--overlap' data-badge='!'>";
hostdown_bage_span = "</span>";
icon_image_src = item.attrs.icon_image.slice(0, -4) + "_gray.png";

} else {

hostdown_bage = "";
hostdown_bage_span = "";

if (item.attrs.icon_image) {
icon_image_src = item.attrs.icon_image;


} else {
icon_image_src = "img/my/dot.png";
}

}

return "<td class='mdl-data table__cell--non-numeric'><img src='" + www_path
+ icon_image_src + "' id='host" + item.attrs.display_name.split('.')[0] + "' />"
+ "<div class='mdl-tooltip' for='host" + item.attrs.display_name.split('.')[0] + "'>" + item.attrs.display_name + "</div>"
+ hostdown_bage_span + "</td><td class='mdl-data table__cell--non-numeric' onclick='location=\"host.php?host=" + item.attrs.__name + "\"'>"
+ hostdown_bage + hostdown_bage_span + item.attrs.display_name + "</td>"
+ "<td class='mdl-data table__cell--non-numeric'>" + item.attrs.vars.domain_name + "</td>"
//+ "<td class='mdl-data table__cell--non-numeric'>" + item.attrs.vars.os + "</td>"
;

});

showData.empty();

if (items.length) {
var content = '<tr>' + items.join('</tr><tr>') + '</tr>';
var list = $('<table class="mdl-data table mdl-js-data table" style="margin: auto; width: 100%" />').html(content);
showData.append(list);
}
});

showData.text('Loading the JSON file.');
});


$('#get-data').click();

setInterval(function(){$('#get-data').click();},60*1000);

});


Репозиторій проекту веб інтерфейсу можна знайти на тут.

З застосуванням стилів Material Design Lite наш веб інтерфейс буде виглядати так:

Список хостівСписок хостів

Список хостів з відображенням не доступності одного з нихСписок хостів з відображенням не доступності одного з них

Детальна інформація по хостуДетальна інформація по хосту


Для такого варіанту з мінімальною функціональністю icinga2 можна придумати багато областей застосування. Наприклад, не великі проекти, супровід не пов'язаних комп'ютерів приватною особою, або інтеграція в існуючі системи технічної підтримки (HelpDesk). Можливо, наступного разу ми навчимо наші Windows хости завантажувати підписані нами powershell скрипти і виконувати їх на нашу вимогу, моніторити інші комп'ютери без встановленого агента, мережеве активне обладнання і все це з мінімальними витратами, але з великим потенціалом масштабування і розширення функціональності.

Посилання

Офіційна документація icinga2 — Установка
Офіційна документація icinga2 — API
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.