АЛЕКСЕЙ ГРИНЬКО
Архивируем данные с помощью Bacula
Bacula – это мощное средство создания и управления резервными копиями данных, а также восстановления информации при необходимости. Имея модульную архитектуру, Bacula легко масштабируется и может быть использована как на нескольких, так и на сотнях компьютеров. Кому будет полезен этот инструментарий? Как сказано в документации, «... если вы используете такие программы, как tar, dump, bru для создания резервных копий, и хотели бы иметь удобное средство для сетевой работы, то Bacula, скорее всего, имеет полный набор необходимых вам функций». Что ж, проверим это утверждение разработчиков.
Начнем с описания компонентов, из которых состоит эта система. Bacula имеет клиент-серверную архитектуру, ее схема представлена ниже.
Рисунок 1
Взаимодействие служб в Bacula
Сердцем системы является «центр управления» (Director), в его функции входит хранение заданий, их запуск, ведение журнала всего происходящего. Эта часть на данный момент реализована только для FreeBSD и Linux. Для хранения журналов создания архивных копий и их содержимого используется SQL Server (служба хранения каталога). В его роли может выступать PostgreSQL, MySQL и SQLite. Созданные архивные копии передаются в «хранилище» (Storage Server), где они записываются в «тома» (Volume). Тома физически могут записываться в простейшем случае в файл, но Bacula поддерживает работу с накопителями на магнитной ленте, в том числе и устройства с автоматической сменой кассеты. Если выбран вариант хранения томов в виде файлов, то после достижения файлом длины 650-700 Мб (CD) или же 4.5 Гб (DVD), целесообразно закончить работу с этим томом и записать его на носитель CD/DVD. Еще одним элементом системы является «Служба файлов» (File Daemon). Это клиентская часть, которая устанавливается на компьютеры, хранящие данные для архивации. Вся прелесть в том, что данная часть реализована для различных платформ: FreeBSD, Linux и Windows. Таким образом, собирать данные для размещения в архив можно вне зависимости от того, какая операционная система установлена на компьютер. Остался еще один элемент – «Консоль» (Bacula Console). Он также существует в версиях для различных ОС, его целью является создание, управление и контроль выполнения архивных копий, а также менеджмент томов и пулов.
Как видно, поместить службу хранения каталогов, хранилище и центр управления разумнее всего на одном сервере. В FreeBSD есть следующие порты для установки:
- /usr/ports/sysutils/bacula-server
- /usr/ports/sysutils/bacula-client
Нам понадобятся оба, так как компьютер, на котором будет запущен центр управления Bacula, тоже будет выступать в роли клиента. После установки необходимо настроить три конфигурационных файла, находящихся в $PREFIX/etc/: bacula-fd.conf (служба файлов), bacula-dir.conf (центр управления), bacula-sd.conf (хранилище). Начнем с самого простого – bacula-fd.conf:
Director { # описание центра управления,
Name = main-dir # которому разрешено обращаться
Password = "bacula" # к этой службе файлов
}
FileDaemon { # описание службы файлов
Name = main-fd # имя клиента
FDport = 9102 # используемый порт
WorkingDirectory = /var/lib/bacula # рабочий каталог
Pid Directory = /var/run # файл с номером процесса
}
Messages { # описание канала сообщений
Name = Standard # имя канала
director = main-dir = all, !skipped # где он находится
}
Конфигурационные файлы состоят из объектов (директив), параметры каждого объекта находятся внутри фигурных скобок {}. Здесь приведены следующие объекты: Director (центр управления), FileDaemon (служба файлов) и Messages (канал сообщений). Описанием первого объекта мы разрешаем центру управления с именем main-dir подключаться и передавать задания. Второй объект задаёт параметры работы самой службы файлов. В третьем же задается имя канала сообщений, в который будут передаваться отчеты о проделанной работе, состояние, ошибки.
Для оповещения о ходе работы, поставленных задачах и результатах их выполнения используются каналы сообщений. Можно задействовать несколько каналов, к примеру, по числу заданий, и отправлять отчеты пользователям, чьи данные были заархивированы. Мы же создадим один канал для отправки всех сообщений администратору. Также по почте будут приходить уведомления о смене кассеты или подключении нового файлового тома, если текущий заполнен. Для отправки сообщения Bacula использует собственный инструментарий – bsmtp, который может отправлять сообщения не только локально, но и на удаленный smtp-сервер.
Следующий конфигурационный файл описывает настройки хранилища:
Storage { # определение хранилища
Name = main-sd # имя
SDPort = 9103 # используемый порт
WorkingDirectory = "/var/lib/bacula" # рабочий каталог
Pid Directory = "/var/run" # файл с номером процесса
}
Director { # описание центра управления,
Name = main-dir # которому разрешено обращаться
Password = "bacula" # к этому хранилищу
}
Messages { # описание канала сообщений
Name = Standard # имя канала
director = main-dir = all, !skipped
# передавать сообщения в центр управления
}
Device { # устройство хранения томов
Name = FileStorage # имя
Media Type = File # тип носителя (файловый)
Archive Device = /tmp # путь к устройству
LabelMedia = yes # давать томам метки
Random Access = Yes # устройство с позиционированием
AutomaticMount = yes # автоматическое подключение тома
RemovableMedia = no # является ли съемным носителем
AlwaysOpen = no # блокировка извлечения носителя
}
Device { # устройство хранения томов
Name = DDS-4 # имя
Description = "DDS-4" # описание
Media Type = DDS-4 # тип носителя (кассета стриммера)
Archive Device = /dev/nsa1 # пусть к устройству
AutomaticMount = yes # автоматическое подключение тома
AlwaysOpen = yes # блокировка извлечения носителя
Offline On Unmount = no # извлекать кассету при размонтировании
Hardware End of Medium = no # аппаратное определение конца кассеты
BSF at EOM = yes # ставить метку в конце (для FreeBSD)
Backward Space Record = no # настройки для устройств
Fast Forward Space File = no # с непроизвольным позиционированием
TWO EOF = yes # помечать конец кассеты двумя EOF
}
В этом файле описываются следующие объекты: Storage (хранилище), центр управления, имеющий право работать с данным хранилищем, канал сообщений и, наконец, два устройства для архивирования – файловое и накопитель на гибкой магнитной ленте (стриммер).
Перед тем как приступить к последнему, самому сложному файлу конфигурации, необходимо подготовить службу каталога. Подойдет PostgreSQL, MySQL или SQLite.
Я остановил свой выбор на MySQL, это довольно распространенный SQL-сервер, присутствующий почти в каждой UNIX-системе. В комплекте с Bacula есть скрипты для конфигурирования базы данных: создание пользователя и установка необходимых прав (grant_mysql_privileges), (create_mysql_database) и таблиц (make_mysql_tables), находящихся в $PREFIX/bacula. Для создания пользователя и назначения ему необходимых прав, лучше использовать скрипт, поставляемый по умолчанию. Поэтому создаем новую базу данных ./create_mysql_database и затем выполняем следующее:
mysql -u root -p
mysql> grant all privileges on bacula.* to bacula@localhost identified by "baculapwd" with grant option;
mysql> flush privileges;
Далее запуском скрипта ./make_mysql_tables создаем необходимые для работы Bacula таблицы. На этом подготовка службы каталога завершена и можно приступать к настройке центра управления.
Файл конфигурации имеет несколько частей:
- описание центра управления;
- описание заданий;
- клиенты, графики запуска;
- доступные хранилища;
- набор файлов;
- служба каталога;
- каналы сообщений;
- пулы хранения томов.
Некоторые директивы нам уже знакомы, но есть и новые – описание заданий (Job), набор файлов (FileSet), график запуска (Schedule). Начнем с описания заданий (Job) и шаблона задания (JobDefs). Задание может быть нескольких типов (Type) – архивирование данных (Backup), восстановление данных (Restore), проверка целостности данных (Verify) и обслуживание каталога (Admin). С первыми двумя вопросов возникнуть не должно. Verify используется для проверки, изменялись ли данные с момента последнего архивирования. Тип задания Admin используется для удаления устаревших записей из каталога. Задание обязательно должно содержать следующие элементы: имя (Name), тип (Type), типы архивирования (только для заданий Backup), какие файлы архивировать (FileSet), с какого клиента (Client), в какое хранилище (Storage), какой пул (Pool – группа томов) использовать, приоритет задания (Priority). Целесообразно часть этих опций описать в шаблоне задания и создавать задания на его основе. В этом случае не нужно каждый раз указывать одни и те же опции. Если же мы хотим использовать значение элемента, отличное от приведенного в шаблоне, достаточно его переопределить в описании задания. Ниже приведен пример шаблона и описания задания архивирования:
JobDefs { # шаблон задания
Pool = Default # пул с томами
# описание пулов для разных типов архивирования
Full Backup Pool = FullBackups
Differential Backup Pool = DiffBackups
Incremental Backup Pool = IncBackups
Name = DefaultJob # имя
Type = Backup # тип задания
Level = Full # тип архивирования
Client=main-fd # клиент
Storage = File # хранилище
Messages = Standard # канал сообщений
Priority = 10 # приоритет
Reschedule On Error = yes # повторять ли при ошибке
Reschedule Interval = 6h # интервал для повтора
Reschedule Times = 3 # количество повторов
}
Job { # описание задания
Name = "UnixCfg" # имя
JobDefs = DefaultJob # используемый шаблон
FileSet="UnixCfg" # набор файлов
Storage = File # используемое хранилище
}
Как видно, в шаблоне мы описали используемый по умолчанию пул, указали, что для каждого типа архивирования будем использовать свой пул, – это довольно удобно. Делать полные копии большого количества файлов еженедельно неразумно. Гораздо удобнее сделать раз в месяц (или реже) полные копии, а еженедельно создавать инкрементальные (Incremental) копии, в которых будут храниться только измененные с момента последней архивации файлы. Приведу еще одно немаловажное задание:
Job {
Name = "BackupCatalog" # имя задания
JobDefs = DefaultJob # используемый шаблон
FileSet="Catalog" # набор файлов
# запускать по графику, выполнить перед заданием и после него
Schedule = "WeeklyCycleAfterBackup"
RunBeforeJob = "/usr/local/etc/bacula/make_catalog_backup -u bacula -pbaculapwd"
RunAfterJob = "/usr/local/etc/bacula/delete_catalog_backup"
Write Bootstrap = "/var/lib/bacula/BackupCatalog.bsr"
Storage = FileStorage # используем файловое хранилище
Priority = 11 # приоритет
}
Использование этого задания очень важно, ведь оно создает дамп SQL-базы службы каталога. Делать это необходимо для того, чтобы застраховать себя от сбоев на самом сервере. Если что-то случится со службой каталога, то, имея на руках одни кассеты с архивами, восстановить данные будет совсем непросто. Поэтому данные записываются в другое хранилище (файловое). Хранить эти файлы после их заполнения рекомендуется на другом сервере или на носителях CD/DVD. Кроме того, здесь используются новые элементы RunBeforeJob и RunAfterJob и, как ясно из названия, это скрипты, которые необходимо запустить до и после начала архивирования. Перед запуском задания создается дамп базы, с помощью скрипта make_catalog_ backup (входящего в дистрибутив Bacula). Дамп помещается в файл /var/lib/bacula/bacula.sql. Элемент Schedule (график запуска) показывает, что это задание необходимо выполнять периодически. Выбранный график запуска «Weekly CycleAfterBackup», как будет рассмотренно позже, указывает на то, что архивирование будет запускаться ежедневно, после выполнения всех основных резервных заданий. Заметим, добились мы этого установкой приоритета ниже обычного. По умолчанию значение приоритета для задания равно 10.
Если мы хотим повысить приоритет задания, его необходимо назначить меньше 10, и наоборот. Если в одно и то же время запланировано несколько задач, то первой будет выполнена задача с более высоким приоритетом, остальные будут поставлены в очередь на ожидание. Задание, поступившее в очередь позже, но имеющее приоритет выше, будет выполнено в обход тех, что уже стоят в очереди. При этом работа выполняемого архивирования не прерывается даже при поступлении в очередь задания с более высоким приоритетом.
Переходим к следующим объектам – описание набора файлов для архивирования. В задании с именем UnixCfg мы указали, что будем использовать набор файлов UnixCfg. Расшифруем, что мы имели в виду:
FileSet {
Name = "UnixCfg" # имя набора файлов
Include = signature=MD5 { # опции – посчитать суммы MD5 для файлов
/etc # архивировать каталог /etc
/usr/local/etc # а также /usr/local/etc
}
Exclude = { # файлы-исключения
*.bak # исключить из архива файлы по маске
}
}
FileSet {
Name = "Catalog"
Include = signature=MD5 {
/var/lib/bacula/bacula.sql
}
}
Все интуитивно понятно. Описаны два набора файлов – соответственно для двух вышесозданных заданий. Добавлю только то, что при использовании файлового хранилища, а не стриммера, будет полезным добавить вслед за опцией «signature=MD5» опцию «compression=GZIP», которая указывает на необходимость архивирования файлов перед помещением в том. В случае со стриммером это не имеет смысла – большинство устройств имеют аппаратную поддержку сжатия.
На очереди следующий элемент – описание графика выполнения заданий. Делается это для того, чтобы можно было сконфигурировать автоматический запуск архивирования. Если в описании задания не указана директива Schedule, то оно будет запускаться только вручную.
Запуск задания в этом режиме осуществляется из консоли Bacula.
Schedule {
Name = "WeeklyCycle"
Run = Full 1st sun at 1:05
Run = Differential 2nd-5th sun at 1:05
Run = Incremental mon-sat at 1:05
}
Schedule {
Name = "WeeklyCycleAfterBackup"
Run = Full sun-sat at 1:10
}
Первый график запуска определяет выполнение полного архивирования файлов в первое воскресенье месяца в 1.05. Инкрементальное архивирование осуществляется с понедельника по субботу в 1.05. А дифференционное архивирование в каждое воскресенье, кроме первого, в 1.05. Второй график будет запускать задания каждый день, после того как будут выполнены дневные архивирования.
Теперь настала очередь описания клиентов и параметров обращения в службе каталогов. Настройки клиента (службы файлов, которой будут отправляться задания) и службы каталогов прокомментированы и должны быть интуитивно понятны.
Client {
Name = main-fd # имя клиента
Address = localhost # его адрес, имя DNS
FDPort = 9102 # используемый порт
Catalog = MyCatalog # используемая служба каталога
Password = "bacula" # пароль для доступа
File Retention = 30 days # срок хранения файлов в архиве
Job Retention = 6 months # срок хранения записей в каталоге
AutoPrune = yes # удалять старые записи и файлы
}
Catalog {
Name = MyCatalog # имя каталога
# имя SQL-базы данных, пользователь и пароль
dbname = bacula; user = bacula; password = "baculapwd"
}
Ниже приведены описания настроек устройств, используемых в качестве хранилища. Его имя, а также тип носителя обязательно должны быть такими же, как и те, что указаны в bacula-sd.conf.
Storage {
Name = File # имя хранилища
Address = localhost # IP-адрес или DNS-имя
SDPort = 9103 # используемый порт
Password = "bacula" # пароль
Device = FileStorage # устройство (такое же, как в bacula-sd.conf)
Media Type = File # тип носителя (такое же, как в bacula-sd.conf)
}
Storage {
Name = DDS-4 # имя хранилища
Address = localhost # IP-адрес или DNS-имя
SDPort = 9103 # используемый порт
Password = "bacula" # пароль
Device = DDS-4 # устройство (такое же, как в bacula-sd.conf)
Media Type = DDS-4 # тип носителя (такой же, как в bacula-sd.conf)
}
Подробно стоит остановиться на системе информирования о ходе выполнения заданий. Ниже приведено описание канала сообщений с именем Standard, в который мы будем передавать сообщения со всех служб Bacula. Команда оповещения о результате выполнения задается с помощью mailcommand. Для отправки сообщений, не дожидаясь окончания задания, используется команда, определенная с помощью operatorcommand. Для информативности можно использовать следующие переменные:
- %c – имя клиента;
- %d – имя центра управления;
- %e – код завершения задания;
- %i – номер задания;
- %n – имя задания;
- %l – тип архивирования;
- %r – получатель;
- %t – тип задания.
Запись, определяющая передачу сообщений, может иметь два формата:
<путь> = <тип сообщений1>, <тип сообщений2>,...
<путь> = <адресат> = <тип сообщений1>, <тип сообщений2>,...
В первом варианте в качестве <путь> может быть стандартный взвод (stdout), стандартный поток ошибок (stderr) или консоль Bacula (console). При использовании второго типа формата путь может принимать следующие значения:
- центр управления (director);
- файл (file);
- добавление в существующий файл (append);
- системный лог (syslog);
- сообщение по почте (mail);
- сообщение по почте при ошибке (mail on error);
- немедленное сообщение (operator).
Отличие пути «operator» от «mail» состоит в том, что поступившее сообщение будет отправлено немедленно, а не после завершения задания. Это удобно для отправки сообщения о том, что текущий том заполнен, и для продолжения выполнения задания необходимо подключение нового.
Bacula имеет следующие типы сообщений:
- информационное (info);
- предупреждение (warning);
- ошибка (error);
- критическая ошибка (fatal);
- остановка службы (terminate);
- сохранение без ошибок(saved);
- файл не сохранен (notsaved);
- необходимо подключение нового тома (mount);
- файл восстановлен (restored);
- все типы (all).
Если перед типом сообщения указать модификатор «!», то это будет означать, что данный тип сообщений включать не нужно. Исключение определенных сообщений используется совместно с типом «all».
Messages {
Name = Standard # имя канала сообщений
# команда отправки отчета
mailcommand = "bsmtp -h localhost \"\(Bacula\) %r\" -s \"Bacula: %t %e of %c %l\" %r"
# команда отправки запроса смены носителя
operatorcommand = "bsmtp -h localhost \"\(Bacula\) %r\" -s \"Bacula: Intervention needed for %j\" %r"
# отправлять по почте все типы сообщений, за исключением пропущенных файлов
mail = root@localhost = all, !skipped
# адрес оператора смены носителя
operator = root@localhost = mount
# продублировать все типы сообщений в консоль Bacula, за исключением пропущенных и несохраненных файлов
console = all, !skipped, !saved
# записывать сообщения в файл
append = "/var/lib/bacula/log" = all, !skipped
}
Как видно выше, мы направляем на адрес root@localhost все типы сообщений, за исключением пропуска файлов. Все эти сообщения будут продублированы в файл /var/lib/bacula/log. Пропущенными могут быть файлы, попавшие под маску исключения в описании набора файлов или в случае инкрементального архивирования, если эти файлы со времени последнего резервирования не изменялись. В консоль Bacula будут направляться все сообщения, кроме пропущенных по желанию пользователя файлов (!skipped), а также ошибок при сохранении файлов (!saved). Если мы не хотим получать сообщения по почте и записывать отчеты в файл, достаточно закомментировать эти строки. Но хоть один из видов уведомления рекомендуется оставить, иначе не будет видно возникновения ошибок или запроса на смену носителя.
Последний элемент, который необходимо рассмотреть, – это описание пула томов. Приведено описание только одного пула, но нам необходимо для работы еще три – для полного, дифференционного и инкрементального архивирования. Имена им необходимо дать те, что были использованы при описании шаблона задания (FullBackups, Diff Backups, IncBackups).
Pool {
Name = Default # имя тома
Pool Type = Backup # тип пула
Recycle = yes # стирать ли помеченные на удаление тома
AutoPrune = yes # помечать на удаление старые тома
Volume Retention = 3m # срок хранения тома 3 месяца
LabelFormat = "File-" # формат маркировки тома
}
Теперь можно проверить правильность созданных конфигурационных файлов. Сделать это можно, запустив по очереди каждого из демонов с ключами -t -c /$PREFIX/bacula/bacua-.conf:
bacula-fd -t -c bacula-fd.conf
bacula-sd -t -c bacula-sd.conf
bacula-dir -t -c bacula-dir.con
Задав нужное количество заданий, периодически запускаемых планировщиком, мы получим удобную систему по созданию резервных копий данных. Вмешательство со стороны администратора будет необходимо в случае, если закончится место на кассете и нужно будет ее сменить, о чем Bacula уведомит по почте. В следующей части статьи пойдет речь о консольных командах работы с этой системой – запуск заданий вручную, проверка целостности данных, восстановление информации из архивов и управлением томами и пулами.