main

И ещё раз про бэкапы

И ещё одно продолжение этой же темы.

Около полугода назад я начал постепенный отход от бакулы в сторону чего полегче. В прошлый раз я говорил, в чем преимущества boxbackup'а в сравнении с бакулой. В этот раз поговорим о том, в чём, собственно, недостатки их обоих.

boxbackup:

  • Принудительное и неотключаемое шифрование. Радует конечно, что оно есть и работает, но не для всего же поголовно!
  • Головняк с настройкой сертификатов. Используется кросс-авторизация, с собственными и ненастраевыми центрами сертификации. Скрипты настройки подразумевают, что CN клиентского сертификата ОБЯЗАН быть вида BACKUP-[0-9a-f]+
  • доступ к файлам - только через bbackupquery tool, поскольку со стороны сервера всё зашифровано. Нельзя просто взять и вытащить файл из бэкапа в случае падения сервера.
  • нет pre-/post- скриптов (вот это реально жопа). бампить базы по крону и потом бэкапить - как-то нехочется. Бэкап может отработать, а крон нет, в результате - якобы всё хорошо.
  • Написано на c++ в стиле "обработка исключений - для лохов". При неправильной настройке часто вываливается с трейсом, и без внятного сообщения об ошибке. И начинается гадание по внутренностям ритуального животн^W^W^W названиям функций из трейса, простите, что собственно не так в настройке1
  • в программу зачем-то запихана реализация софтварного рейда.

Как вы уже догадываетесь, я пишу это не просто так, а потому, что нашёл что-то получше, с моей точки зрения. Именно. Вот этот замечательный проектик кажется мне разумным компромиссом между сложностью, безопасностью и настраиваемостью.

Рассмотрим некоторые аспекты подробнее.

Хранение файлов

bacula - один или несколько файлов (томов) наподобие архива, но не tar, как можно было бы предположить, что-то своё. Плюсы - компактность, низкий расход инодов, простота в обращении. Минусы - при использовании тома больше чем для одного задания - их переиспользование под большим вопросом. Сложно быстро найти и вытащить нужный файл при повреждении или полной потере каталога файлов (который хранится отдельно). При размазывании одного задания на несколько томов - это тот ещё сцуко квест. Сильная ориентация на ленточное хранение.

boxbackup - Дерево со множеством шифрованных файлов с порядковыми номерами в имени. (подробно разбиралось в предыдущей части) Плюсы - разве что переиспользование места - сильно упрощается. Минусы - практически невозможно восстановить что-либо при повреждении каталога. Полностью невозможно - при потере ключа хоста.

burp - Дерево обычных файлов. С опциональным пофайловым шифрованием. Минусы - высокий расход инодов. Плюсы - лёгкость восстановления, независимость от каталога, работает даже обычный find. Искоробочная дедупликация (!), которой нет и не будет ни в одном вышеприведённом решении.

Шифрование и передача данных

Здесь можно выделить 2 момента - шифрование передаваемых данных / хранимых данных.

bacula - шифрование там прикручивается опционально, и рассчитано на использование существующего ЦС, либо, создание отдельного ЦС под бэкапы. Надо отдать должное, требование там только одно - CN должен совпадать с адресом подключения. В остальном - вороти что хочешь. Поддержка DH есть и сильно рекомендована к включению. Отдельно настраивается шифрование передачи данных и шифрование самих данных перед отправкой в хранилище. Более того, аутентификация клиента настраиватся отдельно от аутентификации сервера, и то и другое можно докрутить позже2

Маленькое отступление - с cert-based аутентификацией всегда есть проблема - смена адресов. Если сменился адрес директора, включен 'allowed cn' на клиентах и вы поленились настроить reverse-dns / прописали ip в CN - вас ждёт обход всех клиентов с исправлением конфига. Истёк или нужно переделать корневой сертификат? -> Обновление вообще всех сертификатов, кроме ключей.

Думаю мне следует расписать схему работы бакулы отдельно, поскольку тема достаточно большая и интересная. (да блин, по ней диссертацию можно написать!)

Примерная схема взаимодействия компонентов, кто к кому подключается:

[DIR] -- <control> --.
   |                 v
<control>           [SD]
   v                 ^
[FD] --- <data> -----'

Всё это может быть тремя разными хостами. В этом случае нам нужно следить за совпадением до 6 разных CN'ов для одного хоста, с которого снимается бэкапы.

boxbackup - принудительное шифрование всего и вся. Кросс-аутентификация клиента и сервера. ЦС свой и не настраивается. Данные и управляющие команды шифруются на стороне клиента, передаются на сервер и в таком виде складываются в архив.

С подключениями всё просто: [client] -> [server].

burp - Принудительное шифрование управляющих команд и передаваемых данных, но с важной оговоркой: есть возможность автоматического управления сертификатами3 . Выглядит это так: при первом запуске сервера генерируется свой корневой сертификат, ключи и прочие необходимые файлы (srl, expire-list). Далее, этот корневой сертификат перекидывается на клиента, и подкладывается в нужное место (это, пожалуй, единственная рутинная операция). На сервере создаётся файл с именем будущего CN клиента, с единственной строчкой password = <bla-bla-bla> Этот же CN и пароль указывается в конфиге клиента. И при первом подключении к серверу, будет выпущен новый сертификат, подписан и передан клиенту, который его тут же начнёт использовать. Последующие подключения с этим CN, с правильным паролем, но без сертификата уже ничего не дадут. Конечно, можно выключить эту автоматизацию, и настроить всё руками, но это можно сделать и после полного развёртывания системы.

С подключениями тоже всё тривиально - одно соединение по tcp на сторону сервера. (даже проще чем boxbackup, там, ЕМНИП, 2 соединения в сторону сервера, как для ftp в пассивном режиме).

Планирование бэкапов

bacula - система авторитарная, директор там решает всё. Что, когда и куда бэкапить. Развитая (даже черезчур) система расписаний, пулов томов и типов заданий позволит потешить своё ЧСВ и очень выгодно смотрятся в отчётах для начальства.

boxbackup - напротив, не имеет практически никаких средств планирования со стороны сервера, а со стороны клиента - рубильник "не бэкапить", "бэкапить через определённое время" и "бэкапить постоянно". Притом имеет ровно две резервные копии - собственно данные на клиенте и архив на сервере (с удалёнными файлами в том числе).

burp:

  • бэкап может инициировать сервер, при следующем подключении клиента, если это не запрещено настройками клиента
  • бэкап может инициировать клиент, если это не запрещено настройками сервера
  • сервер сам может решить, нуждается ли клиент в бэкапе

Надо отметить, что расписание на уровне самой программы не гибкое, только вида "бэкапить, если прошло > N часов, хранить X последних копий", но! Есть возможность передать управление произвольному скрипту, который будет решать, надо ли бэкапить сейчас. И вот там можно наворотить любую логику.

Список файлов

При рассказе о системах бэкапа частенько забывают о немаловажном практическом аспекте: формировании списка "что бэкапить".

bacula тут впереди планеты всей с логикой, воистину инопланетной. Реальный фрагмент файла:

Include {
  Options {
    signature = MD5
    compression = GZIP
    honor nodump flag = yes
  }

  Options {
    Wild = "*.core"
    Wild = "*.sample"
    Exclude = yes
  }

  File = /etc
  File = /usr/local/etc
}

Exclude {
  File = /etc/.svn
  File = /etc/.bzr
  File = /etc/.bzrignore

  File = /usr/local/etc/.bzr
  File = /usr/local/etc/.svn
  File = /usr/local/etc/.bzrignore
}

Читать это - ещё куда ни шло, но писать - упаси б-же. Удобного способа забэкапить ТОЛЬКО директорию вида /tmp/dump_YYYY-MM-DD, где дата постоянно меняется - нет. Разве что примерно так:

Include {
  Options {
    Wild = "*"
    Exclude = yes
  }
  Options {
    Wild = "dump_20*-*-*"
    Exclude = no
  }
  File = /tmp
}

Если эту директорию перед бэкапом ещё нужно сгенерить - тушите свет, ибо, штатной возможности прочитать либо передать переменную - нет. "Странного хочешь ты"? Отнюдь, это вам не сферично-вакуумные условия. Не всегда можно подогнать задачу под решение.

Фух, ладно, посмотрим как с этим делом у boxbackup. Возможности описаны здесь. Вышеописанный случай превращается здесь в

BackupLocations {
  tmp-dump {
     Path = /tmp
     ExcludeFilesRegex = .*
     ExcludeDirsRegex = .*
     AlwaysIncludeDirsRegex = /tmp/dump_[0-9]{4}-[0-9]{2}-[0-9]{2}
  }
}

Ящитаю, это значительно лучше, чем та наркомания с блоками Include/Exclude/Options выше. Минусы - нет никакой возможности оценить, что же оно реально будет бэкапить. ('estimate <...> listing' в бакуле). Вот этот 'tmp-dump' лучше сразу делать абстрактным и не переименовывать, иначе будет мозолить глаза до скончания времён. Нет ограничений на размеры файлов. Нет ограничений на cross-fs

Отмечу, что принцип остался тот же - 'обозначить корень', 'заигнорить всё', 'добавить только нужное'. Это в случае, если точное имя заранее неизвестно.

burp - "вместо тысячи слов"

Вышеописанный случай: include_glob = /tmp/dump_????-??-??

Полный бэкап /home/etc до кучи):

include = /etc
include = /home
exclude_regex = /home/.*/.local
exclude_regex = /home/.*/.wine
cross_filesystem = /home
nobackup = .nobackup
exclude_ext = avi
exclude_ext = flac
exclude_ext = mkv
exclude_ext = mp3
exclude_ext = ogg
cross_all_filesystems = 0
read_all_fifos = 0
min_file_size = 0
max_file_size = 31457280

Замечу, что всё это может переопределятся на стороне сервера. Опять же, вместо тысячи слов, посмотрите на маны

Estimate есть, с клёвой табличкой итогов в конце (-a e). Verify тоже есть (-a v)

Веб- и прочие морды

А вот здесь у всех, кроме бакулы - плохо. Более того, у всех трёх, встроенного машиночитаемого rpc нет, поэтому "прямое" решение невозможно. Ну и чёрт с ними, раз уж зашла речь, вспомним что есть у бакулы:

  • bacula-web -- readonly, написана на php + smarty, тянет немного, но в том числе gd. Медленно, но развивается, мой патч был обработан в багзилле за двое суток.
  • webacula -- вебморда с возможностью базового управления. php + zend-framework первой ветки. Судя по всему - заброшена. Тянет сильно больше, чем предыдущий пункт, но реально использует столько же. Зависит от версии базы данных бакулы. Некоторые операции работают через запуск bconsole и разбор выхлопа.
  • bat -- в дебиане называется bacula-console-qt, писана на qt, иногда глючит. Сильно не пользовался, только ставил "на посмотреть".
  • bacula-traymonitor - простенький read-only апплет в трей. Можно настроить на опрос статуса произвольного количества узлов сети. Имеет поганую привычку виснуть намертво, если один из хостов недоступен. Интерфейс отмирает только когда соединение отваливается по таймауту и тут же фризится снова. Однопоточность, сэр.
  • bconsole -- штатный консольный клиент с автодополнением всего что только там есть. Не ncurses, только readline.

В завершение

И одной из этих фич нет ни в бакуле, ни в boxbackup'е:

  • Network rate limiting.4
  • Delta differencing with librsync. (здесь подразумеваются большие файлы)
  • Automatic SSL certificate authority and client certificate signing.
  • Storage data deduplication.
  • Automatic client upgrade (для винды, но всё же).

  1. в документации есть скурпулёзно составленный список, но удобства это не прибавляет ↩

  2. под сервером здесь понимается любой демон, к которому идёт подключение - DIR, SD, FD ↩

  3. баг ↩

  4. в бакуле оно было, но втихаря выпилено в community-версии ↩