Как гласит старинная шутка, системные администраторы делятся на две группы: те, которые не делают бэкапы, и те, которые уже делают бэкапы. Систем резеревного копирования существует великое множество, от простейшего самописного скрипта до огромных монстров ценой в “боинг”. Все системы нужны для разных целей и выполняют разные задачи.

Основная, самая известная и популярная система в мире unix и linux – это, безусловно, bacula. Умеет bacula очень много - сложные расписания и политики хранения, шифрование данных и клиент-серверного трафика, управление операциями “на ходу”, десятки способов упаковки и проверки данных. Полный список возможностей bacula занимает несколько страниц мелкого текста. Основной минус бакулы находится ровно там, где находится ее плюс. Внедрение и настройка бакулы - это приключение, как минимум, на неделю. Документации очень много (но ее все равно не хватает). Бакула состоит из 4 самостоятельных компонентов (director, storage, filedaemon, console), каждый из которых настраивается и живет отдельно. Все эти компоненты имеют сложные взаимоотношения и должны быть доступны друг другу напрямую, что тоже жизнь не облегчает. Элементарный конфиг bacula легко может весить десятки килобайт (и bacula очень трепетно относится к опечаткам в конфиге - он в лучшем случае вообще не прочитается, а в худшем сервис упадет). В случае, если нужно делать резервные копии с одного-двух серверов - bacula - явный оверкилл. Вместо сложного комбайна нужен простой и понятный молоток. И такой молоток есть - он называется duplicity.

Duplicity - это очень просто. Это одна-единственная команда, которая запускается на том сервере, откуда будут копироваться данные. Все, что она может:

  • сделать резервную копию. Резервная копия пакуется в блоки (назывются тома), и, по желанию, шифруются. Резервная копия может быть или полной, или инкрементальной. Уровень определяется возрастом копии - если последняя полная копия старше определенного возраста - будет сделана полная, если нет - инкрементальная копия.
  • отправить резервную копию на удаленный сервер. Удаленный сервер может быть rsync, ftp, scp, s3 (вариантов много). Можно хранить прямо в файловой системе. Устройства хранения (ленточные библиотеки, дисковые массивы) – не поддерживатюся.
  • найти расходждения между каталогом и определенной версией бекапа. Полезно, чтобы понять, что изменилось с момента бэкапа.
  • показать список файлов в бэкапе.
  • восстановить файлы из бэкапа (или весь бэкап целиком).
  • почистить удаленный сервер от старых бэкапов.

На этом функционал duplicity заканчивается. Ничего сложного, головоломного, неочевидного. Система, понятная, как кирпич.

Установка и настройка

Duplicty входит в пакет с одноименным названием, и устанавливается традиционно для вашей операционной системы:

#debian, ubuntu
apt-get install duplicity

#centos, redhat, fedora
yum install duplicity

Теперь нужно решить, куда будут отправляться пакеты. Duplicty не может работать с удаленным сервером самостоятельно - в зависимости от типа удаленного сервера ему потребуется тот или иной пакет. Сам duplicity только “дирижирует процессом”. Самые ходовые типы серверов и пакеты:

  • ftp, ftps (ftp over TLS): ncftp
  • rsync: rsync
  • s3 (aws S3, openstack swift, ceph object gateway, minio): boto

Если планируется шифровать и/или подписывать бэкап - нужно сгенерировать gpg-ключ. Шифровать бэкап рекомендуется, если нет доверия серверу хранения. Правило хорошего тона гласят, что доверия нет никогда и никому. Помните о том, что бэкап, по сути – отложеное по времени нарушение безопасности. Ключ генерируется вполне традиционым способом:

gpg --gen-key

Параметры ключа (размер, алгоритм) менять не обязательно, они вполне разумны. После окончания генерации GPG вернет идентификатор ключа. Его так же можно посмотреть вот так:

gpg --list-keys

/root/.gnupg/pubring.gpg
------------------------
pub   2048R/F6822D5F 2017-01-28
uid                  Paul I Rudnitskiy (bck server) <[email protected]>
sub   2048R/292EB891 2017-01-28

ID нам чуть дальше пригодится, рекомендую его запомнить.

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

gpg --export-secret-keys -a F6822D5F  > backup.asc

Резервное копирование

Общий принцип - duplicity [args] {source} {destination}. Аргументов множество, ниже я приведу пример и распишу, что означает каждый. Проще всего сделать shell-скрипт с командой и типовыми аргументами, чтобы не вспоминать их каждый раз

duplicity --verbosity notice \
    --encrypt-key "F6822D5F" \
    --full-if-older-than 14D \
    --num-retries 3 \
    --asynchronous-upload \
    --volsize 100 \
    --archive-dir /var/tmp/.duplicity \
    --log-file /var/log/duplicity.log \
    --exclude "/var/lib/postgresql/9.5/main/archive" \
    "/var/lib/postgresql/9.5/main/" \
    "ftp://bckuser:[email protected]/pgsql"

На что обратить внимание:

  • verbosity - уровень “говорливости” при работе. Рекомендуется info при отладке (показывает файлы и текущие операции) и notice в production (кратко сообщает о текущем этапе работы)
  • encrypt-key - ID ключа для шифрования. Важен, если ключей несколько. Если шифровать не нужно - используйте аргумент --no-encryption. При шифровании gpg спросит пароль ключа шифрования. Побеждается или настройкой gpg-agent или созданием переменной PASSPHRASE с паролем.
  • full-if-older-than - через срок после создания полной копии нужно сделать не инкрементальную, а снова полную копию. В данном примере - 14 дней.
  • volsize - размер одного тома в мегабайтах. Каждый том пакуется и загружается на сервер отдельно, это отдельный файл.
  • archive-dir - папка, где duplicity локально хранит метаданные (информацию о томах и их содержимом). Копия метаданных лежит на сервере. Если по какой-то причине метаданные пропадут - duplicity придется скачать копию метаданных с сервера перед началом бэкапа. Размер папки метаданных пропорционально зависит от количества файлов и количества бэкапов, так что стоит выделить ей побольше места.
  • exclude - позволяет исключить папку из бэкапа. аргументов exclude может быть несколько.
  • destination - последний аргумент, куда копируем данные. Задается в виде классического url. URL для копии в локальную файловую систему имеет вид file:///path/to/folder

Проверка состояния бэкапов на удаленном сервере:

duplicity collection-status "ftp://bckuser:[email protected]/pgsql" \
    --archive-dir /var/tmp/.duplicity

Пример ответа:

NcFTP version is 3.2.5
Local and Remote metadata are synchronized, no sync needed.
Last full backup date: Fri Sep 15 04:10:03 2017
Collection Status
-----------------
Connecting with backend: FTPBackend
Archive dir: /var/tmp/.duplicity/c9edc22d8a99b972fdf4bd3cec26e19f

Found 1 secondary backup chain.
Secondary chain 1 of 1:
-------------------------
Chain start time: Thu Aug 31 04:10:03 2017
Chain end time: Thu Sep 14 04:10:02 2017
Number of contained backup sets: 15
Total number of contained volumes: 252
 Type of backup set:                            Time:      Num volumes:
                Full         Thu Aug 31 04:10:03 2017               137
         Incremental         Fri Sep  1 04:10:02 2017                 6
----------------------------CUT----------------------------------------
-------------------------


Found primary backup chain with matching signature chain:
-------------------------
Chain start time: Fri Sep 15 04:10:03 2017
Chain end time: Fri Sep 29 04:10:03 2017
Number of contained backup sets: 15
Total number of contained volumes: 245
 Type of backup set:                            Time:      Num volumes:
                Full         Fri Sep 15 04:10:03 2017               142
         Incremental         Sat Sep 16 04:10:02 2017                 8
----------------------------CUT----------------------------------------
         Incremental         Fri Sep 29 04:10:03 2017                 7
-------------------------
No orphaned or incomplete backup sets found.

Duplicity не позволяет помечать бэкап как устаревший автоматически (retention в терминологии “взрослых” систем). Чистить ненужные бэкапы придется в ручном режиме:

duplicity --verbosity notice \
--archive-dir /var/tmp/.duplicity \
--force \
remove-all-but-n-full 4 \
"ftp://bckuser:[email protected]/pgsql"

Эта команда удалит все бэкапы старше 4 последних полных бэкапов. В примере выше мы делали полный бекап каждые 2 недели, то есть duplicity удалит бэкапы старше 2 месяцев (8 недель). Если убрать ключ --force – duplicity найдет старые бэкапы, но не будет их удалять - только выведет на консоль. Забывать о чистке не рекомендуется - место на сервере для резервных копий может неожиданно кончится и оставить вас без свежих бэкапов. Выясняется это весьма болезненно.

Проверка и восстановление

Посмотрим файлы, которые у нас есть в бэкапе:

duplicity --archive-dir /var/tmp/.duplicity list-current-files \
    "ftp://bckuser:[email protected]/pgsql"

Пример ответа:

NcFTP version is 3.2.5
Local and Remote metadata are synchronized, no sync needed.
Last full backup date: Sat Sep 29 04:10:03 2017
Mon Oct  2 04:10:02 2017 .
Mon Aug 29 21:07:04 2016 PG_VERSION
Mon Oct  2 04:10:02 2017 backup_label
-----------------------CUT---------------------------------

Команда выше покажет состояние на момент последнего бэкапа. Чтобы получить информацию из более старых бэкапов, нужно использовать ключ -t. К примеру, -t6D вернет информацию о бэкапе, сделаном 6 дней назад.

Восстановление данных выглядит ровно так же, как бэкап, нужно просто поменять местами source (откуда брать данные) и destination:

duplicity --verbosity notice \
    --encrypt-key "F6822D5F" \
    --archive-dir /var/tmp/.duplicity \
    --log-file /var/log/duplicity.log \
    "ftp://bckuser:[email protected]/pgsql" \
    "/var/lib/postgresql/9.5/main/"

На что обратить внимание:

  • Если нужно восстановить бэкап на определенную дату - выручает ключ -t
  • Для восстановления определенного файла нужно использовать ключ --file-to-restore. Таких ключей может быть несколько.
  • Восстановление возможно только в совершенно пустую папку
  • Для восстановления duplicity вытащит с сервера резервных копий весь полный бэкап и все инкрементальные бэкапы с момента полного до точки восстановления. Места уйдет много.