Bacula + Zabbix

OS: "Linux Debian 8/9 (Jessie/Stretch)", "Linux Ubuntu 16/18 (Xenial/Bionic) LTS".
Application: "Bacula Director v7", "Zabbix v3.4".

Задача:
 наладить посредством системы мониторинга "Zabbix" отслеживание текущего
 состояния компонентов и задач централизованной системы резервного 
копирования "Bacula", хранения истории отработанных заданий и 
уведомления о сбоях в процессе их исполнения.

Общий принцип действия выработанного решения таков:

1. Каждый час «Zabbix» обращается за списком актуальных задач к «Zabbix Agent»-у на стороне сервера «Bacula», ожидая его в JSON-массиве.
2. Для полученного перечня объектов мониторинга сервером «Zabbix», в соответствии с заготовками в специализированном шаблоне, в соответствии со спецификацией «Low-Level Discovery (LLD)», создаются необходимые элементы и подэлементы.
3. Практически все запросы обрабатываются запускаемыми «Zabbix Agent»-ом самодельными скриптами, извлекающими данные через CLI-интерфейс «Bacula».
Получившееся полностью автоматизированное решение отслеживает состояние системы резервного копирования по следующим позициям:

Наличие сервисов «Bacula Dir», «Bacula SD» & «Bacula DB» (item/trigger, every 30sec);
Статус задач (item, every 5min);
Длительность исполнения задач (item/graph, every 2hour);
Объём загруженных при исполнении задач данных (item/graph, every 2hour);
Количество загруженных при исполнении задач файлов (item/graph, every 2hour);
Уведомление о неудачном завершении задач (trigger);
Уведомление об активности задач в данный момент (trigger);
Уведомление о длительном отсутствии данных о статусе задач (trigger, 6hour);
Уведомление о длительном перерыве в исполнении задач (trigger, 15 day).

Предварительная подготовка.

На
 стороне сервера резервного копирования должен быть установлен "Zabbix 
Agent" и CLI-интерфейс для "Bacula", а также утилита проверки синтаксиса
 JSON:

# aptitude install zabbix-agent bconsole jq
Перед
 всеми дальнейшими работами потребуется применить заранее подготовленный
 мною специализированный шаблон для системы мониторинга:

Очень
 желательно сразу проверить возможность прохождения запроса от сервера 
мониторинга "Zabbix" к запущенному на стороне системы резервного 
копирования "Zabbix Agent"-у:

# sudo -u zabbix -s zabbix_get -s bacula.example.net -k «proc.num[bacula-dir]»
Настраиваем аутентификацию между компонентами.

Прежде
 чем приступать к выстраиванию логики сбора данных, обеспечим к таковым 
ограниченный доступ (только "на чтение", и не ко всем подсистемам) 
агенту мониторинга "Zabbix".

В конфигурации "Bacula Director" 
заведём отдельную точку входа со своими параметрами аутентификации для 
утилиты "bconsole", через которую к "Bacula" будет подключатся "Zabbix 
Agent":

# vi /etc/bacula/bacula-dir.conf

….
# # Блок описания подсистем управления и мониторинга:

Console {
Name = «zabbix-agent.local»
Password = «zabbixConsolePassword»

# Разрешаем исполнение только перечисленных команд
Command ACL = show,list,llist,quit

# Явно разрешаем получать данные о любых задачах и обращаться к любым каталогам хранения метаданных
Job ACL = *all*
Catalog ACL = *all*
}
….

Проверяем корректность конфигурации средствами самого "Bacula" и применяем таковую:

# bacula-dir -c /etc/bacula/bacula-dir.conf -t
# /etc/init.d/bacula-director reload
Мне
 представляется естественным, что клиентский конфигурационный файл 
утилиты "bconsole" должен быть расположен поближе к источнику запросов -
 в директории настроек "Zabbix Agent"-а:

# vi /etc/zabbix/bconsole.conf && chown zabix:zabbix /etc/zabbix/bconsole.conf && chmod o-rwx /etc/zabbix/bconsole.conf

#
# Bacula Console Configuration File, intended for Zabbix-Agent
#

# Указываем на сервис «Director Daemon», к которому нужно подключится:
Director {
Name = bacula.example.net
Address = bacula.example.net
DIRport = 9101

# (несмотря на то, что в действительности аутентификация осуществляется в контексте блока «Console», в блоке описания «Director» тоже требуется указание параметра «Password» — он не должен ничему соответствовать, просто необходимо присутствие его определения)
Password = «XXXXXXXXXXX»
}

# Параметры аутентификации клиента при подключении к «Director Daemon»:
Console {
Name = zabbix-agent.local
Password = «zabbixConsolePassword»
Director = bacula.example.net
}

Проверяем корректность конфигурации средствами самого CLI-агента "Bacula":

# bconsole -c /etc/zabbix/bconsole.conf -t
Есть смысл сразу удостовериться, действуют ли ограничения - уж не буду здесь о методике.

Настраиваем "Zabbix Agent".

Учитывая
 то, что процедуры сбора данных и отправки их на сервер мониторинга 
осуществляется клиентом "Zabbix", то конфигурационные файл и скрипты 
расположим в его директории:

# mkdir -p /etc/zabbix/scripts
# mkdir -p /etc/zabbix/zabbix_agents.conf.d

# vi /etc/zabbix/zabbix_agentd.conf.d/bacula.conf

UserParameter=bacula.jobs.discovery, /etc/zabbix/scripts/bacula_discovery.sh
UserParameter=bacula.jobs.check[*], /etc/zabbix/scripts/bacula_check_job.sh $1 $2 $3 $4
Подстраховываясь, закрываем к настройкам и скриптам "Zabbix" доступ посторонним:

# chown -R zabbix:zabbix /etc/zabbix
# chmod o-rwx /etc/zabbix
Для применения изменений в конфигурации "Zabbix Agent" необходимо перезапустить:

# /etc/init.d/zabbix-agent restart
Пишем и тестируем скрипт "Zabbix Auto Discovery (LLD)".

Подготовим
 простейший Bash-скрипт, по запросу подключающийся к "Bacula", 
запрашивающий перечень разрешённых к исполнению задач резервного 
копирования и формирующий соответствующий требования "Zabbix Auto 
Discovery" JSON-массив:

# cd /etc/zabbix/scripts
# vi ./bacula_discovery.sh && chown zabix:zabbix ./bacula_discovery.sh && chmod ug+x ./bacula_discovery.sh

#!/bin/bash
# usage: ./bacula_discovery.sh

# Задаём переменные рабочего окружения
BCON=»bconsole -c /etc/zabbix/bconsole.conf»
LOG=»/var/log/zabbix-agent/zabbix-bacula-error.log»
DATE=$(date +»%Y-%m-%d.%H:%M:%S»)

# Проверяем наличие ожидаемых утилит
[ -x «$(command -v bconsole)» ] && [ -x «$(command -v jq)» ] || { echo «${DATE}: Не обнаружены необходимые для работы утилиты. Процедура создания списка активных заданий резервного копирования прервана.» >> ${LOG}; exit 1; }

# Формируем список имён активных заданий «Bacula»
JOBS=$(echo -e «show job\n.\nquit» | ${BCON} | grep -i -E «^job:.*enabled[ \t]*=[ \t]*1» | awk ‘{print $2}’ | grep -i -E «^name[ \t]*=[ \t]*.*$» | awk -F «=» ‘{print $2}’)

# Если список имён заданий не пуст, то формируем JSON для «Zabbix Low-Level Discovery (LLD)»
if [ ! -z «${JOBS}» ] ; then

# Задаём начало JSON
JSONZLLD=»{\»data\»:[»
FIRST=1

# Перебираем имена заданий
for JOB in ${JOBS} ; do

# Пропускаем обработку некоторых задач (заготовку для «восстановления», например)
[ $(echo ${JOB} | grep «restore») ] && continue

# Проставляем разделитель между элементами JSON
if [ ${FIRST} == 0 ] ; then
JSONZLLD=${JSONZLLD}»,»
fi
FIRST=0

# Вводим имя задания в качестве элмента JSON
JSONZLLD=${JSONZLLD}»{\»{#JOB}\»:\»${JOB}\»}»

done

# Завершаем JSON
JSONZLLD=${JSONZLLD}»]}»

# Проверяем синтаксическую корректность JSON
if jq -e . 1>/dev/null 2>&1 <<< «${JSONZLLD}» ; then

# Отдаём JSON на STDOUT
echo ${JSONZLLD}
fi
fi

exit ${?}

Пример получаемого в ответ на запрос JSON-файла для "Zabbix LLD", с обнаруженными активными задачами:

{
«data»:[
{«{#JOB}»:»client0.example.net»},
{«{#JOB}»:»clientX.example.net»}
] }
Есть смысл сразу проверить корректность срабатывания скрипта "Auto Discovery (LLD)":

# sudo -u zabbix -s zabbix_get -s bacula.example.net -k «bacula.jobs.discovery»
Пишем и тестируем скрипт получения запрашиваемых параметров.

Создаём
 специализированный Bash-скрипт, принимающий от "Zabbix Agent"-а запросы
 на получение данных по ряду интересующих нас параметров, обращающийся к
 CLI-утилите "Bacula" и нормализующий их перед выдачей:

# cd /etc/zabbix/scripts
# vi ./bacula_check_job.sh && chown zabix:zabbix ./bacula_check_job.sh && chmod ug+x ./bacula_check_job.sh

#!/bin/bash
# usage: ./bacula_check_job.sh «jobName» «jobParam» {jobLevel}

# Задаём переменные рабочего окружения
BCON=»bconsole -c /etc/zabbix/bconsole.conf»
LOG=»/var/log/zabbix-agent/zabbix-bacula-error.log»
DATE=$(date +»%Y-%m-%d.%H:%M:%S»)

# Проверяем наличие ожидаемых утилит
[ -x «$(command -v bconsole)» ] || { echo «${DATE}: Не обнаружены необходимые для работы утилиты. Процедура запроса статуса задания резервного копирования прервана.» >> ${LOG}; exit 1; }

# Проверяем корректность вводимых данных и выводим подсказку в журнал событий при необходимости
#
JINAME=»${1}»
JIPARAM=»${2}»
JILEVEL=»${3}»
#
[ ! «${JINAME}» ] && { echo «${DATE}: Запрос: \»$(basename $0) $@\». Не указано имя задания резервного копирования. Процедура запроса статуса задания резервного копирования прервана.» >> ${LOG}; exit 1; }
#
[ ! «${JIPARAM}» ] && { echo «${DATE}: Запрос: \»$(basename $0) $@\». Не указан запрашиваемый параметр задания резервного копирования. Процедура запроса статуса задания резервного копирования прервана.» >> ${LOG}; exit 1; }
#
[ «${JILEVEL}» ] && [[ «${JILEVEL}» != «F» && «${JILEVEL}» != «D» && «${JILEVEL}» != «I» ]] && { echo «${DATE}: Запрос: \»$(basename $0) $@\». Некорректно указан уровень задания резервного копирования. Процедура запроса статуса задания резервного копирования прервана.» >> ${LOG}; exit 1; }

# Запрашиваем упрощённую статистику задания, опираясь на его имя
JOBLINE=$(echo -e «list job=${JINAME}\n.\nquit» | ${BCON})

# Первым отрабатываем самые простые запросы о статусах текущего (последнего в списке) задания
if [ «${JIPARAM}» == «jobstatus» ] ; then
ANSWER=$(echo -e «${JOBLINE}» | grep ‘^|’ | tail -n1 | awk -F «|» ‘{print $9}’ | sed -e ‘s/[ ]*//g’)

elif [ «${JIPARAM}» == «lastexecution» ] ; then
STARTTIME=$(echo -e «${JOBLINE}» | grep ‘^|’ | tail -n1 | awk -F «|» ‘{print $4}’ | xargs -I{} date -d «{}» +%s)
let «ANSWER = $(date +%s) — STARTTIME»

# (для дальнейшей выгрузки статистики по отработанным задачам необходимо указание их уровня)
elif [ ! -z «${JILEVEL}» ] ; then

# Для получения статистики выясняем идентификатор последнего успешно завершённого задания
JOBID=$(echo -e «list job=${JINAME}\n.\nquit» | ${BCON} | grep ‘^|’ | grep -i -E «.*\|[ \t]*B[ \t]*\|[ \t]*${JILEVEL}[ \t]*\|.*\|[ \t]*T[ \t]*\|[ \t]*$» | tail -n1 | awk -F «|» ‘{print $2}’ | sed -e ‘s/[ \t]*//g’ | sed -e ‘s/,//g’)
if [ ! -z «${JOBID}» ] ; then

# Запрашиваем расширенную статистику задания, опираясь на его идентификатор
JOBLONG=$(echo -e «llist jobid=${JOBID}\n.\nquit» | ${BCON})

# Формируем запросы и обрабатываем ответы с вычленением значений запрашиваемых параметров
if [ ! -z «${JOBLONG}» ] ; then
case «${JIPARAM}» in
«jobbytes»)
ANSWER=$(echo -e «${JOBLONG}» | grep -i -E «^[ \t]*jobbytes:» | awk -F «:» ‘{print $2}’ | sed -e ‘s/[ \t]*//g’ | sed -e ‘s/,//g’)
;;
«jobfiles»)
ANSWER=$(echo -e «${JOBLONG}» | grep -i -E «^[ \t]*jobfiles:» | awk -F «:» ‘{print $2}’ | sed -e ‘s/[ \t]*//g’ | sed -e ‘s/,//g’)
;;
«duration»)
STARTTIME=$(echo -e «${JOBLONG}» | grep -i -E «^[ \t]*starttime:» | awk -F «starttime:» ‘{print $2}’ | xargs -I{} date -d «{}» +%s)
ENDTIME=$(echo -e «${JOBLONG}» | grep -i -E «^[ \t]*endtime:» | awk -F «endtime:» ‘{print $2}’ | xargs -I{} date -d «{}» +%s)
let «ANSWER = ENDTIME — STARTTIME»
;;
*) echo «${DATE}: Запрос: \»$(basename $0) $@\». Некорректно указан запрашиваемый параметр задания резервного копирования. Процедура запроса статуса задания резервного копирования прервана.» >> ${LOG}; exit 1; ;;
esac

else
echo «${DATE}: Запрос: \»$(basename $0) $@\». Не получен ответ на запрос идентификатора и расширенного описания задания от подсистемы резервного копирования. Процедура запроса статуса задания резервного копирования прервана.» >> ${LOG}; exit 1;
fi
fi

else
echo «${DATE}: Запрос: \»$(basename $0) $@\». Не указан уровень задания резервного копирования. Процедура запроса статуса задания резервного копирования прервана.» >> ${LOG}; exit 1;
fi

# Отдаём значение запрашиваемого параметра (или ничего не делаем если запрашиваемый параметр отсутствует)
[ ! -z «${ANSWER}» ] && echo ${ANSWER}

exit ${?}

Аналогично предыдущим этапам проверяем корректность прохождения запросов к "Bacula" от сервера мониторинга "Zabbix":

# sudo -u zabbix -s zabbix_get -s bacula.example.net -k «bacula.jobs.check[client0.example.net,jobbytes,F]»
Оптимизация оборота файлов журналов событий.

Наши
 самодельные скрипты пишут в свой файл журнала событий, а кроме того 
конфигурационный файл "Logrotate" для "Zabbix Agent" несовременный - 
заменяем его на свой, всеобъемлющий:

# vi /etc/logrotate.d/zabbix-agent

/var/log/zabbix-agent/*.log {
weekly
rotate 7
compress
delaycompress
missingok
notifempty
copytruncate
su zabbix zabbix
}
Проверяем корректность конфигурации "Logrotate":

# logrotate -d /etc/logrotate.d/zabbix-agent

16 комментариев на Bacula + Zabbix

  1. [9315]Nhà Cái (kj8) — Link Vào KJ8 Casino & Cá Cược Uy Tín,KJ8 là nhà cái cá cược uy tín số 1. Cập nhật link vào KJ8 Casino chính thức, trải nghiệm kho trò chơi đa dạng, an toàn và tỷ lệ thưởng cực cao. Đăng ký tham gia ngay! visit: kj8

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *