Инкрементальный бекап на Amazon S3
После переезда моего сайта с shared-хостинга на виртуальный сервер в облаке вплотную встал вопрос об архивации данных: если раньше о ежедневном бэкапе беспокоился хостер, то теперь эти заботы целиком легли на плечи администратора. Так как хранить большие архивы на своем сервере не только небезопасно, но и (иногда) накладно, было решено копировать основную массу файлов на сервис S3 от Amazon. Под катом описывается мой способ реализации инкрементального бэкапа. Способ достаточно нубовский, но желающие повторить его без труда найдут пути тонкой настройки под свои нужды.
Сначала определимся с задачами
Нам необходимо:
- Делать ежедневные архивы веб-серверов (каталоги сайтов и базы данных). Необходимо хранить архивы за последний месяц.
- Делать инкрементальные архивы — для экономии дискового пространства. Делать полный архив еженедельно, потом 6 архивов измененных файлов, потом цикл повторить.
- Хранить копии архивов на стороннем сервере (Amazon S3). На локальном сервере будем оставлять архив за неделю, остальные архивы будут присутствовать только на сервере.
Мой сервер работает под ОС Debian, для других операционных систем, возможно, нужно будет внести соответствующие поправки в команды установки и пути файлов.
Необходимые компоненты
backupninja: программа служит удобной оберткой для других утилит, позволяет централизованно управлять процессом архивации.
Установка: apt-get install backupninja
duplicity: утилита для создания инкрементальных бэкапов. Умеет работать с удаленными серверами.
Установка: apt-get install duplicity
boto: API для работы с сервисами Amazon Web Services. Используется duplicity для архивации напрямую на сервис AWS S3
Установка: apt-get install python-boto
s3cmd: утилита для работы с сервисом Amazon S3 из командной строки.
Установка: apt-get install s3cmd
Реализация
Начать необходимо с регистрации на AWS. Процесс не представляет никаких сложностей, хорошо описан maxout в топике Быстрая реализация резервного копирования в Amazon S3. В Урюпинске регистрация прошла на ура с картой местного отделения сбера, значит и в других городах и селах проблем не возникнет.
Далее настраиваем backupninja. Главный конфигурационный файл программы — /etc/backupninja.conf Все опции в файле очевидны, приводить их здесь нет смысла. В простейшем случае там даже не нужно ничего менять, разве что настроить уровень записи в логи (от фатальных ошибок до отладочной информации) и состав отчета о выполненных заданиях, отсылаемого на почту админу.
Настройки для каждого отдельного задания backupninja хранит в отдельных файлах в каталоге /etc/bckup.d (по умолчанию). Имени файла предшествует числовой префикс, задающий порядок выполнения задания. Задания в файлах без префикса и с префиксом 0 выполняться не будут. Задания в файлах с одинаковым префиксом будут выполняться параллельно, каждое задание с префиксом больше чем у предыдущего будет выполняться после завершения заданий с меньшим префиксом. Таки образом мы имеем возможность, задавая префикс файла, контролировать очередность выполнения заданий.
Кроме префикса, файлы заданий должны иметь расширение, соответствующее типу задания.
Backupninja имеет оболочку для настройки и тестирования конфигурации заданий ninjahelper. Мне кажется, что создавать и изменять задания удобнее в текстовом редакторе, а тестировать — из оболочки.
Итак, файл конфигурации задания архивации баз данных. Я архивирую БД в два шага: сначала делаю дампы всех баз, затем из дампов делаю инкрементальные архивы. Шаг первый, файл 20-all.mysql (я копировал болванки файлов из /usr/share/docs/backupninja/examples и вносил в них необходимые изменения)
backupninja MySQL config file ###
hotcopy = < yes | no > (default = no)
make a backup of the actual database binary files using mysqlhotcopy.
hotcopy = no
sqldump = < yes | no > (default = no)
make a backup using mysqldump. this creates text files with sql commands
sufficient to recontruct the database.
#
sqldump = yes
sqldumpoptions =
(default = lock-tables complete-insert add-drop-table quick --quote-na
arguments to pass to mysqldump
sqldumpoptions = add-drop-table quick --quote-names
compress = < yes | no > (default = yes)
if yes, compress the sqldump output.
compress = yes
dbhost = (default = localhost)
backupdir = (default: /var/backups/mysql)
where to dump the backups. hotcopy backups will be in a subdirectory
‘hotcopy’ and sqldump backups will be in a subdirectory ‘sqldump’
backupdir = /home/backups/mysql
databases = < all | db1 db2 db3 > (default = all)
which databases to backup. should either be the word ‘all’ or a
space separated list of database names.
databases = all
user = root
В конфигурации я указал что:
— необходимо делать дамп с помощью mysqlfump;
— дамп необходимо сжать;
— сжатые файлы сохранить в каталоге /home/backups/mysql
— необходимо сделать бэкап всех баз данных
После выполнения задания в каталоге /home/backups/mysql появятся файлы с именами баз данных, сжатые gzip’ом.
Следующим заданием мы делаем инкрментальный архив баз с помощью duplicity, файл 30-databases.dup (я приведу лишь измененные мною опции; вам необходимо скопировать файл конфигурации полностью из /usr/share/docs/backupninja/examples/example.dup и сделать изменения в нем, иначе задание не выполнится)
дополнительные опции для duplicity
я не шифрую архив, увеличиваю размер тома до 512 мегабайт,
задаю путь и имя для кэща duplicity
options = no-encryption volsize 512 archive-dir /home/backups/duplicity name vds1.databases
временный каталог. учтите, что backupninja требует на диске
свободное место не менее чем размер тома
tmpdir = /home/backups/tmp
[source]
что включаем в бэкап. можно задать несколько источников, по одному в каждой строке
include = /home/backups/mysql/sqldump
если необходимо что-то исключить из архива -указываем здесь
#exclude = /www/urup.ru/sxd/backup
[dest]
инкрементальный бэкап (это значение по умолчанию)
incremental = yes
Сколько дней делать инкрементальные бэкапы перед тем как опять сделать полный бэкап
increments = 7
Сколько всего дней хранить бэкапы. Мы храним на локальном сервере архивы за 7 последних дней.
keep = 7
Куда складывать бэкапы. duplicity умеет сохранять на разные сервисы,
в том числе напрямую на AWS, но нам нужно хранить часть архивов на
локальном диске, поэтому копировать файлы на Amazon будем
в отдельном задании
desturl = file:///home/backups/mysql
Еще раз замечу, что я привел только измененные строки конфигурационного фала. Для того чтобы задание работало необходимо скопировать конфигурацию полностью из /usr/share/docs/backupninja/examples/example.dup и уже в этом файле сделать необходимые изменения.
Аналогичным образом делаем задания для архивации директорий веб-серверов. Не забываем о возможности задавать несколько источников для включения в архив и несколько для исключения, по одному на строчку конфигурации. Я архивирую каждый сайт в отдельном задании, каждый архив складываю в отдельный каталог с именем сайта в /home/backups/files/www/
При создании архивов, если для вас это важно, вы можете зашифровать файлы с помощью GnuPG. В этом случае необходимо убрать опцию --no-encryption.
Последнее задание будет копировать созданные файлы архивов на сервер AWS S3. Файл называется 50-upload.sh и представляет из себя обычный shell-скрипт:
#!/bin/sh
синхронизируем локальные копии архивов с копиями на амазоне
s3cmd sync \
--bucket-location=EU \
--exclude ‘sqldump/*’ \
/home/backups/files \
/home/backups/mysql \
s3://vds1.backup
удаляем архивы старше 30 дней на амазоне
duplicity no-encryption s3-use-new-style archive-dir /home/backups/duplicity name vds1.databases.s3 --force remove-older-than 30D s3+http://vds1.backup/mysql
Для корректной работы duplicity с сервисами амазона необходим установить и настроить boto. Настройка заключается в указании учетных данных в файле /etc/boto.cfg
[Credentials]
aws_access_key_id = *
aws_secret_access_key = *
Восстановление из архивов
Получаем сведения об архиве:
duplicity no-encryption s3-use-new-style collection-status s3+http://vds1.backup/mysql
Распаковываем локальный архив:
duplicity --no-encryption file:////home/backups/mysql /home/backups/mysql/sqldump
Первый параметр — URL архива, второй — каталог, в который будут распакованы файлы. Существующие файлы не будут перезаписаны, если только не указана опция --force
Распаковываем архив с сервера Amazon:
duplicity no-encryption s3-use-new-style s3+http://vds1.backup/mysql /home/backups/mysql/sqldump
Извлекаем один файл из архива.
duplicity no-encryption file-to-restore home/backups/mysql/sqldump/mysql.sql.gz --force file:///home/backups/mysql /home/backups/mysql/sqldump/mysql1.sql.gz
Файл, который необходимо распаковать, указывается ключом file-to-restore вместе с полным относительным путем (без лидирующего слэша). Первый параметр — URL архива, второй — полный путь к распаковываемому файлу. Если файл уже существует то он не будет перезаписан, если только не указана опция force