воскресенье, 15 декабря 2013 г.

Установка и настройка Zabbix 2.2.0 в Debian Wheezy

Недавно вышел новый релиз Zabbix 2.2, в котором, по словам разработчиков, была существенна увеличена производительность, в 2-5 раз. Достигнуто это было, видимо, за счёт удаления столбцов lastvalue и prevvalue из таблицы items.

Кроме того, в настройках сервера теперь нельзя выключить Housekeeper - процессы Zabbix, удаляющие из базы данных устаревшие значения. Теперь эта настройка перенесена в веб-интерфейс, где можно выключить Housekeeper лишь для определённых видов данных, а не целиком. Это полезно, если настроено секционирование лишь части таблиц. При этом часть таблиц по-прежнему будут очищаться Housekeeper'ом, а часть будет очищаться настроенной в планировщике задач MySQL хранимой процедурой, которая будет удалять устаревшие секции таблиц.

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

Другим важным для меня изменением стало изменение настроек опроса по SNMP. Раньше использовались настройки опроса по умолчанию, из библиотеки SNMP. По умолчанию таймаут опроса составлял 1 секунду, а в случае неудачи делалось до 5 дополнительных попыток опроса. В Zabbix 2.2 для опроса по SNMP используется значение настройки Timeout, заданное в файле конфигурации и делается только одна попытка опроса.

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

В случае небольшой инсталляции может помочь увеличение количества процессов для опроса - процессов Poller. В случае большой инсталляции количество процессов придётся увеличить настолько, что может потребоваться слишком много оперативной памяти, которая используется процессами Poller и потоками MySQL, обслуживающими подключение к базе данных от каждого Poller'а.

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

1. Исправление исходников и сборка deb-пакетов

Добавим официальные репозитории с файлами для сборки пакетов в файл /etc/apt/sources.list:
deb-src http://repo.zabbix.com/zabbix/2.2/debian wheezy main
Установим ключ репозитория Zabbix и обновим список доступных пакетов:
# wget http://repo.zabbix.com/zabbix-official-repo.key -O - | apt-key add -
# apt-get update
Установим необходимые для сборки пакетов Zabbix зависимости и скачаем файлы для сборки пакетов:
# apt-get build-dep zabbix
# apt-get source zabbix
Ставим дополнительную сборочную зависимость, которую разработчики забыли прописать в файлы для сборки пакетов и пакет devscripts, из которого нам пригодится утилита dch:
# apt-get install unixodbc-dev
Переходим в каталоги zabbix-2.2.0, скачиваем и накладываем заплатку:
# cd zabbix-2.2.0
# wget http://stupin.su/files/zabbix220_snmp_timeout_retries.diff
# patch -Np0 < zabbix220_snmp_timeout_retries.diff
Текст самой заплатки:
diff -Naur src/zabbix_proxy/proxy.c new/zabbix_proxy/proxy.c
--- src/zabbix_proxy/proxy.c    2013-11-12 13:16:44.000000000 +0600
+++ new/zabbix_proxy/proxy.c    2013-12-07 13:29:39.283703310 +0600
@@ -42,6 +42,7 @@
 #include "housekeeper/housekeeper.h"
 #include "../zabbix_server/pinger/pinger.h"
 #include "../zabbix_server/poller/poller.h"
+#include "../zabbix_server/poller/checks_snmp.h"
 #include "../zabbix_server/poller/checks_ipmi.h"
 #include "../zabbix_server/trapper/trapper.h"
 #include "../zabbix_server/snmptrapper/snmptrapper.h"
@@ -407,6 +408,10 @@
 #endif
                {"Timeout",                     &CONFIG_TIMEOUT,                        TYPE_INT,
                        PARM_OPT,       1,                      30},
+               {"SNMPTimeout",                 &CONFIG_SNMP_TIMEOUT,                   TYPE_INT,
+                       PARM_OPT,       1,                      30},
+               {"SNMPRetries",                 &CONFIG_SNMP_RETRIES,                   TYPE_INT,
+                       PARM_OPT,       1,                      10},
                {"TrapperTimeout",              &CONFIG_TRAPPER_TIMEOUT,                TYPE_INT,
                        PARM_OPT,       1,                      300},
                {"UnreachablePeriod",           &CONFIG_UNREACHABLE_PERIOD,             TYPE_INT,
diff -Naur src/zabbix_server/poller/checks_snmp.c new/zabbix_server/poller/checks_snmp.c
--- src/zabbix_server/poller/checks_snmp.c      2013-11-12 13:16:49.000000000 +0600
+++ new/zabbix_server/poller/checks_snmp.c      2013-12-07 12:50:31.062073112 +0600
@@ -33,6 +33,9 @@
 }
 zbx_snmp_index_t;
 
+int CONFIG_SNMP_TIMEOUT;
+int CONFIG_SNMP_RETRIES;
+
 static zbx_snmp_index_t        *snmpidx = NULL;
 static int             snmpidx_count = 0, snmpidx_alloc = 16;
 
@@ -268,10 +271,10 @@
                        break;
        }
 
-       session.retries = 0;                            /* number of retries after failed attempt */
-                                                       /* (net-snmp default = 5) */
-       session.timeout = CONFIG_TIMEOUT * 1000 * 1000; /* timeout of one attempt in microseconds */
-                                                       /* (net-snmp default = 1 second) */
+       session.retries = CONFIG_SNMP_RETRIES - 1;              /* number of retries after failed attempt */
+                                                               /* (net-snmp default = 5) */
+       session.timeout = CONFIG_SNMP_TIMEOUT * 1000 * 1000;    /* timeout of one attempt in microseconds */
+                                                               /* (net-snmp default = 1 second) */
 
 #ifdef HAVE_IPV6
        if (SUCCEED != get_address_family(item->interface.addr, &family, err, MAX_STRING_LEN))
diff -Naur src/zabbix_server/poller/checks_snmp.h new/zabbix_server/poller/checks_snmp.h
--- src/zabbix_server/poller/checks_snmp.h      2013-11-12 13:16:48.000000000 +0600
+++ new/zabbix_server/poller/checks_snmp.h      2013-12-07 12:50:31.062073112 +0600
@@ -26,7 +26,8 @@
 #include "sysinfo.h"
 
 extern char    *CONFIG_SOURCE_IP;
-extern int     CONFIG_TIMEOUT;
+extern int     CONFIG_SNMP_TIMEOUT;
+extern int     CONFIG_SNMP_RETRIES;
 
 int    get_value_snmp(DC_ITEM *item, AGENT_RESULT *value);
 
diff -Naur src/zabbix_server/server.c new/zabbix_server/server.c
--- src/zabbix_server/server.c  2013-11-12 13:17:04.000000000 +0600
+++ new/zabbix_server/server.c  2013-12-07 13:29:22.605760996 +0600
@@ -43,6 +43,7 @@
 #include "housekeeper/housekeeper.h"
 #include "pinger/pinger.h"
 #include "poller/poller.h"
+#include "poller/checks_snmp.h"
 #include "poller/checks_ipmi.h"
 #include "timer/timer.h"
 #include "trapper/trapper.h"
@@ -360,6 +361,10 @@
 #endif
                {"Timeout",                     &CONFIG_TIMEOUT,                        TYPE_INT,
                        PARM_OPT,       1,                      30},
+               {"SNMPTimeout",                 &CONFIG_SNMP_TIMEOUT,                   TYPE_INT,
+                       PARM_OPT,       1,                      30},
+               {"SNMPRetries",                 &CONFIG_SNMP_RETRIES,                   TYPE_INT,
+                       PARM_OPT,       1,                      10},
                {"TrapperTimeout",              &CONFIG_TRAPPER_TIMEOUT,                TYPE_INT,
                        PARM_OPT,       1,                      300},
                {"UnreachablePeriod",           &CONFIG_UNREACHABLE_PERIOD,             TYPE_INT,
Если всё прошло успешно, то можно внести комментарии к изменениям. Запускаем команду для редактирования журнала изменений:
# dch -i
И приводим последнюю запись к подобному виду:
zabbix (1:2.2.0-2+stupin) UNRELEASED; urgency=low

  * Non-maintainer upload.
  * Added parameters SNMPTimeout and SNMPRetries to config of Zabbix-server
    and Zabbix-proxy

 -- Vladimir Stupin <wheel69@yandex.ru>  Sat, 07 Dec 2013 13:08:13 +0600
Теперь можно собрать deb-пакеты:
# dpkg-buildpackage -us -uc -b -rfakeroot
В каталоге выше появятся собранные пакеты, которые можно установить при помощи dpkg.

2. Установка Zabbix

Установим необходимые для работы Zabbix пакеты:
# apt-get install lighttpd php5-cgi snmp-mibs-downloader mysql-server mysql-client
После этого можно установить сам сервер Zabbix, веб-интерфейс, агент и утилиты. Если вы собирали пакеты самостоятельно, можете воспользоваться dpkg. Можно также воспользоваться моим репозиторием, в который я выложил собранные пакеты. Для этого нужно вписать в файл /etc/apt/sources.list строку:
deb http://deb.stupin.su/ wheezy main
И обновить список пакетов:
# apt-get update
Ставим Zabbix из пакетов:
# dpkg -i zabbix-server-mysql_2.2.0-2+stupin_amd64.deb zabbix-agent_2.2.0-2+stupin_amd64.deb zabbix-frontend-php_2.2.0-2+stupin_all.deb zabbix-get_2.2.0-2+stupin_amd64.deb zabbix-sender_2.2.0-2+stupin_amd64.deb
Или из репозитория:
# apt-get install zabbix-server-mysql zabbix-agent zabbix-frontend-php zabbix-get zabbix-sender
Zabbix-агент позволит наблюдать за самим компьютером, на котором мы устанавливаем Zabbix.

Утилита zabbix-get может пригодиться для отладки пользовательских параметров Zabbix-агента: скриптов, которые вызываются Zabbix-агентом при запросе этого параметра. Скрипт должен выводить результат на стандартный вывод, а Zabbix-агент вернёт выведенное значение Zabbix-серверу или утилите zabbix-get.

Утилита zabbix-sender может пригодиться для скриптов, запускаемых из планировщика задач. Эти скрипты могут отправлять результаты измерений на Zabbix-сервер при помощи утилиты zabbix-sender.

3. Настройка базы данных

В процессе установки Zabbix-сервера будет выведено предложение настроить базу данных. Если вы ставите Zabbix в первый раз, то можно согласиться с предложением и настроить новую базу. Если же у вас имеется база данных, стоит ответить на предложение отрицательно и настроить подключение к базе данных вручную, в файле /etc/zabbix/zabbix_server.conf. Диалог настройки выглядит следующим образом:



Можно те же самые действия проделать и вручную. Подключаемся консольным клиентом к СУБД и создаём базу данных для Zabbix:
$ mysql -uroot -p
> CREATE DATABASE zabbix DEFAULT CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI;
Создаём пользователя, от имени которого Zabbix будет подключаться к MySQL:
> INSERT INTO user(host, user, password) VALUES('localhost', 'zabbix', PASSWORD('zabbix_password'));
> FLUSH PRIVILEGES;
Даём пользователю zabbix полный доступ к базе данных zabbix:
> GRANT ALL ON zabbix.* TO 'zabbix'@'localhost';
> FLUSH PRIVILEGES;

Подключаемся к свежесозданной БД, создаём структуру БД и наполняем её данными:
> USE zabbix;
> SOURCE /usr/share/zabbix-server-mysq/schema.sql
> SOURCE /usr/share/zabbix-server-mysq/data.sql
> SOURCE /usr/share/zabbix-server-mysq/images.sql
Задаём пароль администратора системы мониторинга и выходим из MySQL:
> UPDATE users SET passwd=MD5('zabbix_admin_password') WHERE alias='admin';
> QUIT
4. Настройка SNMP

Удобно при опросе оборудования по SNMP в качестве OID'ов указывать не их числовое значение, а текстовое представление, взятое из соответствующего MIB-файла. Никто не запрещает использовать и другие MIB-файлы, но обычно мне бывает достаточно одного лишь IF-MIB'а. Файл IF-MIB скачивается в процессе установки пакета snmp-mibs-downloader, осталось лишь прописать его использование в файл конфигурации /etc/snmp/snmp.conf, вписав в него следующую строчку:
mibs +IF-MIB
5. Настройка сервера Zabbix

Настроим Zabbix-сервер, чтобы он мог подключаться к БД. Если вы воспользовались средствами автоматической настройки базы данных, этот шаг можно пропустить.

Отредактируем файл конфигурации /etc/zabbix/zabbix_server.conf, установив значения соответствующих опций. В случае если Zabbix-сервер и сервер MySQL находятся на одном компьютере, желательно использовать Unix-сокет:
DBHost=localhost
DBSocket=/var/run/mysqld/mysqld.sock
DBName=zabbix
DBUser=zabbix
DBPassword=zabbix_password

Другие полезные настройки, на которые следует обратить внимание:
ListenIP=127.0.0.1 

StartPollers=5
StartPollersUnreachable=1
StartPingers=1
Timeout=3

SNMPTimeout=1
SNMPRetries=3
Назначение настроек:
  • ListenIP указывает IP-адрес, на котором Zabbix-сервер будет принимать подключения от веб-интерфейса и утилиты zabbix-sender. Может оказаться проще оставить эту настройку закомментированной, ограничив допустимые адреса клиентов при помощи пакетного фильтра.
  • StartPollers задаёт количество процессов, занимающихся SNMP-проверками, проверками при помощи скриптов внешнего опроса и т.п. Если в меню веб-интерфейса "Администрирование" - "Очередь" не наблюдается отставания в опросе, то всё можно оставить как есть.
  • StartPollersUnreachable задаёт количество процессов, занимающихся опросом не отвечающего оборудования. Обычно стоит сделать запас на случай крупных аварий, когда неотвечающего оборудования становится очень много.
  • StartPingers - количество процессов, занимающихся опросом по ICMP. Для опроса используется утилита fping, для которой во временном каталоге формируются списки IP-адресов. Если опрашиваемых по ICMP узлов очень много, стоит увеличить эту настройку. Возможно также поможет использование в качестве временного каталога раздела tmpfs, т.к. при этом временные файлы будут создаваться в памяти. А может быть это и не поможет, потому что дисковый кэш на практике может нивелировать накладные расходы по записи и чтению этих файлов.
  • Timeout - тот самый период ожидания ответа, значение которого в моём случае не подходило для опроса по SNMP. Для того, чтобы скрипты внешнего опроса успевали отрабатывать, я обычно задаю значение 30 секунд.
  • SNMPTimeout и SNMPRetries - настройки, добавленные путём правки исходных текстов Zabbix. Задают период ожидания ответа по SNMP и количество попыток. Поскольку протокол SNMP работает поверх протокола UDP, который не гарантирует доставку, всё-же стоит делать несколько попыток опроса, а не прекращать опрос сразу после первой же неудачи. Я задал 1 секунду и 3 попытки соответственно. Считаю это оптимальными настройками.

По мере роста количества наблюдаемых узлов и элементов данных может потребоваться увеличивать размеры кэшей и выставить в /etc/sysctl.conf настройку, ограничивающую максимальной размер одного сегмента разделяемой памяти, увеличивая её по мере необходимости:
kernel.shmmax = 268435456
Изменить эту настройку в процессе работы системы можно запустив команду вида:
# sysctl kernel.shmmax=268435456
6. Настройка веб-сервера

Настроим Lighttpd для обслуживания веб-интерфейса Zabbix. Для этого создадим файл /etc/lighttpd/conf-available/20-zabbix.conf со следующим содержимым:
alias.url += (
  "/zabbix/" => "/usr/share/zabbix/"
)

$HTTP["url"] =~ "^/zabbix/conf/" {
  url.access-deny = ("")
}

$HTTP["url"] =~ "^/zabbix/api/" {
  url.access-deny = ("")
}

$HTTP["url"] =~ "^/zabbix/include/" {
  url.access-deny = ("")
}

$HTTP["url"] =~ "^/zabbix/include/classes/" {
  url.access-deny = ("")
}
Если хочется, чтобы веб-интерфейс Zabbix был доступен по адресу с собственным доменным именем, этот файл может выглядеть следующим образом:
$HTTP["host"] == "zabbix.domain.tld" {

  alias.url += (
    "/" => "/usr/share/zabbix/"
  )

  $HTTP["url"] =~ "^/conf/" {
    url.access-deny = ("")
  }

  $HTTP["url"] =~ "^/api/" {
    url.access-deny = ("")
  }

  $HTTP["url"] =~ "^/include/" {
    url.access-deny = ("")
  }

  $HTTP["url"] =~ "^/include/classes/" {
    url.access-deny = ("")
  }
}
Затем откорректируем настройки PHP, так чтобы он удовлетворял требованиям веб-интерфейса Zabbix. Для этого создадим файл /etc/php5/mods-available/zabbix.ini и пропишем в него следующие настройки:
max_execution_time=300
memory_limit=128M
post_max_size=16M
upload_max_filesize=2M
max_input_time=300
date.timezone=Asia/Yekaterinburg
Включим использование этого файла при обработке CGI-сценариев PHP:
# cd /etc/php5/cgi/
# ln -s ../mods-available/zabbix.ini conf.d/30-zabbix.ini
Осталось включить поддержку PHP в режиме FastCGI в веб-сервере, а также включить веб-интерфейс Zabbix и попросить веб-сервер применить новые настройки:
# lighty-enable-mod fastcgi-php
# lighty-enable-mod zabbix
# /etc/init.d/lighttpd force-reload
7. Настройка веб-интерфейса

Зайдём в веб-интерфейс Zabbix и проследуем по страницам мастера настроки веб-интерфейса:

Вместо использования мастера можно просто создать вручную файл conf/zabbix.conf.php со следующим содержанием:
<?php
// Zabbix GUI configuration file
global $DB;

$DB['TYPE']     = 'MYSQL';
$DB['SERVER']   = 'localhost';
$DB['PORT']     = '0';
$DB['DATABASE'] = 'zabbix';
$DB['USER']     = 'zabbix';
$DB['PASSWORD'] = 'zabbix_db_password';

// SCHEMA is relevant only for IBM_DB2 database
$DB['SCHEMA'] = '';

$ZBX_SERVER      = 'localhost';
$ZBX_SERVER_PORT = '10051';
$ZBX_SERVER_NAME = '';

$IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG;
?>
8. Настройка клиента точного времени

Настраивать точное время полезно всегда. В случае системы мониторинга это особенно полезно, поскольку происходящие в системе события и исторические данные имеют привязку ко времени. Для синхронизации системного времени я использую демон OpenNTPd, разработанный в рамках проекта OpenBSD. Он не перегружен функционалом и легко настраивается. Установим пакет openntpd:
# apt-get install openntpd
И пропишем в файл конфигурации /etc/openntpd/ntpd.conf опцию servers, которая использует в качестве серверов все IP-адреса, возвращаемые по доменному имени:
servers ntp.ufanet.ru
9. Настройка почтового релея

Для отправки уведомлений системы мониторинга на почту можно воспользоваться Postfix, настроив его в режиме простейшего почтового релея. Для этого можно воспользоваться одной из моих прошлых заметок: Простейший почтовый релей на основе Postfix

Заключение

Здесь рассмотрена лишь установка системы мониторинга. Её настройка - отдельная большая тема. Чтобы получить начальное представление об устройстве системы, рекомендую обратиться к статье: FreeBSD: Установка и начальная настройка системы мониторинга Zabbix. Более подробное описание можно найти на официальной вики-странице проекта: Руководство по Zabbix 2.2.

Дополнение от 11 июня 2014 года.

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

воскресенье, 8 декабря 2013 г.

Настройка сервера VNC и RDP совместно с LightDM

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

Всё оказалось довольно просто: дисплейный менеджер LightDM умеет работать совместно с VNC-сервером, позволяя авторизоваться в системе и начать новый X-сеанс.

Установка и настройка VNC-сервера

Для начала устанавливаем пакет с VNC-сервером TightVNCServer:
# apt-get install tightvncserver
В файле конфигурации /etc/lightdm/lightdm.conf находим секцию VNCServer и приводим её к следующему виду:
[VNCServer]
enable=true
port=5900
width=1024
height=768
depth=8
Смысл всех настроек очевиден:
  • enable включает возможность подключиться к LightDM по протоколу VNC,
  • port задаёт номер TCP-порт, на котором VNC-сервер будет ожидать подключений,
  • width задаёт ширину экрана для VNC-сервера,
  • height задаёт высоту экрана для VNC-сервера,
  • depth задаёт глубину цвета для точки - 8 бит, 16 бит, 24 бита,
Осталось перезапустить дисплейный менеджер LightDM. Учтите, что при перезапуске LigthDM будут завершены все открытые X-сеансы, поэтому лучше завершить их вручную и выполнить следующую команду из текстовой консоли:
# /etc/init.d/lightdm restart
Теперь LightDM будет ожидать подключений на TCP-порту 5900 и при подключении клиента будет запускать VNC-сервер. Узнать, какой VNC-сервер будет запускаться, можно при помощи следующей команды:
# update-alternatives --list vncserver
Выбрать используемый VNC-сервер можно при помощи следующей команды:
# update-alternatives --config vncserver
Если в системе установлен только один VNC-сервер, будет использоваться он. При удалении используемого VNC-сервера система переключится на использование другого.

Лучше использовать клиент наиболее совместимый с сервером. В нашем случае - это TightVNCViewer из пакета xtightvncviewer. VNC-сервер одновременно будет выступать в роли X-сервера, который будет взаимодействовать с LightDM. При подключении мы увидим обычный экран LightDM с указанным разрешением и глубиной цвета, в котором можно ввести имя пользователя и пароль для создания нового X-сеанса.

Установка и настройка RDP-прокси

Для подключения к компьютеру с VNC-сервером по протоколу RDP можно установить и настроить специальный прокси-сервер XRDP, который принимает подключения по протоколу RDP, а сам устанавливает подключения по протоколу VNC к VNC-серверу (на самом деле в данном случае соединения будет принимать LightDM, запуская для их обслуживания VNC-сервер). Прокси будет одновременно выступать в роли RDP-сервера и VNC-клиента.

Установим пакет с прокси:
# apt-get install xrdp
Приведём файл конфигурации /etc/xrdp/xrdp.ini к следующему виду:
[globals]
bitmap_cache=yes
bitmap_compression=yes
port=3389
crypt_level=low
channel_code=1

[xrdp1]
name=default
lib=libvnc.so
username=
password=
ip=127.0.0.1
port=5900
На самом деле этот RDP-прокси может выступать и в роли RDP-клиента, может устанавливать подключения к произвольным компьютерам в сети, самостоятельно запускать X-серверы и использовать различные схемы аутентификации. В данном случае из файла конфигурации удалены все остальные варианты подключения и добавлен только один вариант с названием default, который позволяет подключиться к VNC-серверу, запущенному на том же компьютере, что и сам RDP-прокси. Подключение будет устанавливаться на TCP-порт 5900, а RDP-прокси не будет спрашивать у пользователя имя и пароль.

Теперь перезапустим прокси, чтобы настройки вступили в силу:
# /etc/init.d/xrdp restart
Теперь можно подключаться к VNC-серверу при помощи обычного RDP-клиента из Windows. При этом можно не думать об установке VNC-клиента, который не всегда может оказаться под рукой во "враждебной" среде Windows :)

Вот снимок экрана при подключении по VNC при помощи Remmina: