2015-12-01

Zabbix и мониторинг состояния баз Exchange 2010 (с использованием Low Level Discovery)

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

В этом посте я расскажу как решил задачу, а также постараюсь доступно рассказать как работает Zabbix Low Level Discovery (LLD), так как интернет не особо пестрит примерами самостоятельных решений для этого функционала заббикса.

Отталкиваться я предлагаю от консоли Exchange Management Shell и команды 
Get-MailboxDatabaseCopyStatus -Identity *

Данная команда выполняется на любом из серверов Exchange и выводит список всех баз с указанием принадлежности к серверам.


Из вывода нам важно поле Status - "Mounted" или "Healthy" в нем означает, что с базами все ок. В противном случае на базу нужно обратить внимание.

Выгружаем данные на сервере

Набрасываем скрипт.

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010


$jsonhead = '{"data":['
$jsontail = ']}'
$jsonbody=""

$statusbody = ""
    
Get-MailboxDatabaseCopyStatus -Identity * | ForEach-Object {
    $base = $_.Name -replace "\\", "/"
    $status = $_.Status.value__

    $jsonbody += '{ "{#BASENAME}":"' + $base + '"}, '
    
    $statusbody += $base + ' ' + $status + "`r`n"
}



$json = $jsonhead +  $jsonbody + $jsontail
$json = $json -replace "}, ]", "}]"


$json  | Out-File -Encoding "Default"  C:\zabbix_MailDB_status_discovery.txt
$statusbody | Out-File -Encoding "Default" C:\zabbix_MailDB_status_result.txt
Данный скрипт выгружает информацию о базах в двух представлениях:
  1. В файл zabbix_MailDB_status_discovery.txt кладется список баз в формате JSON. Это нужно для настройки Low Level Discovery (LLD) - механизма заббикса, который позволит не настраивать проверку статуса для каждой базы, а автоматизировать добавление/удаление баз в список мониторинга при их создании/удалении на серверах Exchange. Выглядит выгрузка примерно так:
    {"data":[{ "{#BASENAME}":"mdb3/EXCH01"}, { "{#BASENAME}":"mdb4/EXCH01"}, { "{#BASENAME}":"mdb5/EXCH01"}, { "{#BASENAME}":"mdb1/EXCH01"}, { "{#BASENAME}":"mdb2/EXCH01"}, { "{#BASENAME}":"mdb2/EXCH04"}, { "{#BASENAME}":"mdb3/EXCH04"}, { "{#BASENAME}":"mdb5/EXCH06"}, { "{#BASENAME}":"mdb4/EXCH07"}, { "{#BASENAME}":"mdb1/EXCH08"}]}
  2. В файл zabbix_MailDB_status_result.txt выгружаются пары "база/сервер" - "статус" - этот файл впоследствии будет опрашиваться заббиксом.
    mdb3/EXCH01 11
    mdb4/EXCH01 11
    mdb5/EXCH01 11
    mdb1/EXCH01 6
    mdb2/EXCH01 11
    mdb2/EXCH04 6
    mdb3/EXCH04 6
    mdb5/EXCH06 6
    mdb4/EXCH07 6
    mdb1/EXCH08 11
    Как можно заметить, поле статуса на деле имеет числовое представление, где 11=Mounted, а 6=Healthy.
Суем скрипт в планировщик (задание нужно выполнять с повышенными полномочиями) и теперь у нас есть данные по базам. 

Настраиваем агент Zabbix на передачу данных

Для работы с данными, которые мы получили на предыдущем шаге, потребуются (по крайней мере я не нашел способа обойтись без них) 2 дополнительные утилиты: cut и iconv - порты одноименных линуксовых утилит. Первая выбирает значение в указанном столбце и служит для парсинга файла zabbix_MailDB_status_result.txt, вторая - конвертирует JSON-файл zabbix_MailDB_status_discovery.txt в UTF-8. И да, я знаю что Powershell умеет выгружать в файл в указанной кодировке, в т.ч. UTF-8, но делает он это так, что zabbix перестает понимать, что выгружается JSON, и будет ругаться, что вы подсунули неправильный формат. 

Кладем cut в каталог с виндой (так он окажется в поле переменно PATH), а iconv (все его файлы) - например в папку с установленным агентом. После этого у меня образовались 2 строки в zabbix_agent.conf:
UserParameter=exchange.MailDBStatus.discovery,cmd /c type c:\zabbix_MailDB_status_discovery.txt | %windir%\zabbix_agent\win\x64\iconv.exe -f 866 -t utf-8

UserParameter=exchange.MailDBStatus.getstatus[*],cmd /c type c:\zabbix_MailDB_status_result.txt | find /i "$1" | cut -d " " -f 2
 
Первый параметр - exchange.MailDBStatus.discovery - будет передавать наш JSON. 
Второй - exchange.MailDBStatus.getstatus[*] - будет принимать вместо астериска имя базы данных/сервера (я упомяну об этом ниже) и передавать в конструкцию find /i "$1". Таким образом второй параметр будет передавать состояние базы исходя из ее имени.

Настраиваем Zabbix-сервер

На сервере нам нужно создать Discovery Rule с одним Item prototype и одним Trigger prototype.

(Кликабельно)
Я создал это правило в темплейте, который в моем случае применяется для серверов Exchange, но можно это сделать и для конкретного сервера, с которого будет читаться информация.

Настройки самого Discovery Rule


Как можно видеть, в качестве ключа (Key) указан параметр exchange.MailDBStatus.discovery -  через этот параметр, как мы помним, агент отдает наш JSON-файл со списком "имя_базы/имя_сервера". Если быть точнее, то, посмотрев в файл, мы увидим что передаются пары вида:
{ "{#BASENAME}":"mdb3/EXCH01"}т.е. переменная с именем "{#BASENAME}" и значение - "имя_базы/имя_сервера". Странное имя переменной обусловлено тем, что оно должно выглядеть как заббиксопонятное имя шаблона - {#имя}.

Итак, согласно этим настройкам, раз в час сервером будет перезапрашиваться JSON. Чтобы на основе этого JSON'а сформировались итемы, нам нужно создать Item Prototype для этого Discovery Rule.


Вот здесь вступает в дело второй параметр нашего конфига агента - exchange.MailDBStatus.getstatus[*]. В настройках Item prototype этот параметр принимает вид exchange.MailDBStatus.getstatus[{#BASENAME}]. Отмечу, что само название итем прототипа тоже должно содержать шаблон {#BASENAME}, так как в комплексе это работает следующим образом: 
  1. Discovery Rule получает JSON 
  2. В JSON через переменную {#BASENAME} передаются имена баз
  3. Item prototype генерит Items, подставляя вместо {#BASENAME} реальные имена баз - как в название итема, так и в параметр Key, через которых осуществляется связь с агентом.
Таким образом, если мы не укажем {#BASENAME} в имени прототипа, то при наличии нескольких баз заббикс не сможет сгенерить итемы - имена итемов должны быть уникальны.

Едем дальше - создаем Trigger prototype


Аналогично, в имени указываем  {#BASENAME}, чтобы для каждой базы смог сгенерироваться триггер с уникальным именем. В "выражении" проверяем чтобы наш ключ (exchange.MailDBStatus.getstatus[{#BASENAME}])  был не равен 6 И не равен 11 - то есть не равен значениям, которые соответствуют нормальным статусам баз. Замечу, также, что при добавлении Trigger expression нужно давить на Select prototype, потому что мы создаем триггер на основе не уже готового итема, а итемов, которые будут создаваться из прототипа.


Резюме

  1. Мы по шедулеру на сервере Exchange выгружаем JSON с именами баз и пары "имя базы"-"статус"
  2. Мы создали Discovery rule, которое читает JSON через ключ на агенте. 
  3. Мы создали итем и триггер прототипы, которые используют полученные значения переменной {#BASENAME}
  4.  На основе имен баз из прототипов генерятся итемы и триггеры. 
  5. Созданные итемы обращаются по ключу к агенту
  6. Агент, сверив имя запрашиваемого ключа с описанным у себя, подставляет имя базы вместо астериска передает его в  командную строку отвечающую за вывод значения
    UserParameter=exchange.MailDBStatus.getstatus[*],cmd /c type c:\zabbix_MailDB_status_result.txt | find /i "$1" | cut -d " " -f 2
  7. Таким образом один юзерпараметр с астериском обслуживает все ключи с конкретными именами баз, выдавая статус.
  8. Триггер реагирует на "неправильный" статус.

4 комментария:

  1. Спасибо за статью.
    Без iconv можно обойтись используя кодировку unicode или же как-нибудь еще избавляться от BOM в начале файла.
    Без cut обойтись сложнее, я переписал ваш пример с использованием PowerShell на скорую руку. Работает, но выглядит страшненько:
    powershell -Command "& {$(&'get-content' -Path c:\TEMP\zabbix_mailbox_status.txt) -match '$1' -replace '^[\w\s]+/[\w]+\s'}"

    ОтветитьУдалить
    Ответы
    1. Главное что работает =) Спасибо за дополнение =)

      Удалить
    2. Привет опять. )
      Я вот сам заморочился с LLD Exchange. Немного переиначил ваше вариант, если интересно, вот ссылка:
      http://it-asnd.rhcloud.com/nizkourovnievoie-obnaruzhieniie-baz-dannykh-ms-exchange-v-zabbix-chast-1-pravilo-lld/
      Там две статьи и один перевод на английский язык первой части.

      Удалить
    3. Спасибо! Если не мне, то другим пригодится =) По LLD в инете вообще инфы маловато, и в мануале тоже (если ничего не добавляли со времен 2.0) не густо. Так чтобы пошагово объяснить как его готовить под себя.

      Удалить