Организация резервного копирования веб-проекта — проблемы, грабли, стратегия
Тема резервного копирования кажется довольно простой и не требующей особых пояснений и историй, однако в ней лежит огромное количество подводных камней и граблей, на которые важно не наступить.
Главная проблема заключается в том, чтобы организовать такую систему резервного копирования, которая будет соответствовать требованиям актуальности зарезервированных данных, требованиям быстродействия восстановления и требованиям изолированности площадки, на которой содержатся резервные копии.
Проще говоря, резервная копия должна иметь актуальные данные, должна быть возможность запуститься из нее (хотя бы в минимальном варианте) без наличия основной площадки, и процесс восстановления не должен занимать при этом слишком много времени
Что же может случиться с простой и понятной процедурой бэкапа, которая настроена один раз и стабильно работает? Хотя резервное копирование и не включено в нашу услугу техподдержки, мы стараемся следить за резервными копиями наших клиентов, контролировать процесс их создания, следить за тем, что резервные копии создаются, что из них можно восстановиться, и вот лишь некоторые из проблем, которые регулярно возникают при резервировании:
- Процесс дампа базы данных не запускается - бэкап базы данных не создается: например, скрипт создания резервной копии оказался с ошибкой, либо же используемый в нем пароль был сменен и в настоящий момент просто не подходит.
- Статический контент не резервируется - организовано резервное копирование базы данных, но статика не копируется. Это вполне приемлемый подход на небольших простых сайтах, однако уже давно интернет-магазины насыщены большим количеством фотографий товаров, регулярно обновляемых при выгрузках, сайты - контентом, который пользователи загружали долгое время.
- Дамп базы данных копирует не ту базу данных: скрипт резервирует базы поименно, а в момент выкладки новой версии была создана новая база данных, которая критична для работы проекта, но не резервируется. Во время резервного копирования заканчивается место на диске - скрипты резервного копирования отрабатывают, но в момент работы они используют диск, где свободного места недостаточно для размещения временной резервной копии, бэкап прерывается и не создается.
- Бэкап создается с неактуального резервного сервера: в процессе эксплуатации проекта создание резервных копий довольно часто организуется на резервном сервере для снижения нагрузки на основной машине. Если со временем синхронизация с резервным сервером “ломается”, то бэкап продолжает резервировать уже неактуальный проект, не сходный данными с основной площадкой.
- Резервная копия делается реже, чем необходимо. Для примера: файловый архив карточек товаров или пользовательского контента создается раз в неделю - в воскресенье - авария произошла в субботу. Таким образом, максимальной можно считать потерю 5 дней работы сотрудников/пользователей.
- Резервная копия сохраняется на той же площадке/на том же сервере, где создается. Удаление данных на сервере, фатальная авария на сервере, авария в датацентре - приведут к ситуации, когда основной сайт не будет работоспособен и, при этом, нельзя будет восстановиться и из резервной копии.
- Резервная копия создается сложным способом (например, с помощью инкрементальных бэкапов) и невосстановима. Довольно редко мы видим регулярные процедуры по проверке актуальности инкрементальных бэкапов - они сложны, при этом потеря одного из элементов набора инкрементальных бэкапов приводит к непригодности всех последующих инкрементальных копий.
Любую систему вы создаете, исходя из требований к ней, это же относится и к системе резервного копирования. Постановка задачи в виде "Хочу, чтобы были резервные копии" может привести к неверному ее решению - копии будут, но будут не там или будут неакутальны. Для того, чтобы правильно поставить эту задачу и организовать корректную систему резервного копирования, нужно ответить, как минимум, на эти три вопроса:
1. Насколько актуальными должны быть данные при восстановлении на заданный момент времени?
2. Какое максимальное время может занимать процесс восстановления резервной копии? Базы? Статики? Проекта полностью?
3. Где будут храниться резервные копии? Насколько эта площадка не связана с основной?
Для примера, давайте рассмотрим с технической точки зрения проект на типичном наборе ПО - Linux/MySQL/PHP. В этом случае, мы, скорее всего, говорим о необходимости резервирования базы данных, статики сайта и пользовательских данных и не забываем о конфигурационных файлах.
База данных:
Если база не очень большая и есть возможность прервать работу сайта, то можно снять дамп с помощью mysqldump. Полную копию без остановки базы можно снять с помощью Xtrabackup, как мы уже писали в этой статье.
Удобно снимать бэкап не с боевого сервера, а с реплики (если она есть) - как mysqldump'ом, так и Xtrabackup, и таким образом не создавать никакой нагрузки на продакшн.
Если для вас не критична потеря нескольких часов данных, то можно просто ограничиться регулярной полной копией БД интервалами, в зависимости от нагрузки на сервере и требований:
- Можно потерять до 24 часов новых данных: резервная копия - раз в день, каждую ночь.
- Можно потерять до 4 часов новых данных: резервная копия - каждые 4 часа.
Более сложным является вопрос сохранности данных, если терять их совсем нельзя.
Минимальной защитой от человеческого фактора на сервере (аварий на основном сервере, случайных удалений файлов и т.п.) может служить работающая реплика на резервном, однако не стоит забывать, что сама по себе она не является бэкапом базы - все операции, проведенные на основной базе данных будут проведены и на ней.
Если все же использовать ее для резерва, то можно организовать преднамеренную задержку репликации (pt-slave-delay или CHANGE MASTER TO MASTER_DELAY) - если кто-то на продакшене сделал DROP, можно успеть спасти реплику.
Более надежным методом является сочетание регулярного полного резервного копирования базы с резервированием binlog-ов MySQL - журналов всех операций, проведенных с базой. В случае необходимости восстановления базы на заданный момент времени, восстанавливается полная база (например, созданная в 12 ночи, а следом на ней проигрываются все операции из binlog-ов до заданного момента времени). Подробнее об использовании для этого утилиты mysqlbinlog можно прочитать здесь - https://www.percona.com/blog/2012/01/18/backing-up-binary-log-files-with-mysqlbinlog/
В идеальном окружении реплика базы данных, резервирование бинлогов и само хранилище бэкапов находятся на отдельном, от основной площадки, окружении (например, в другом датацентре).
Статика и пользовательские данные
Резервное копирование статических файлов кажется простой операцией, однако она становится довольно нудной и тяжелой в момент, когда статика разрастается, когда у интернет-магазина становится большое количество карточек товара, пользователи загружают свои фотографии, и т.д.
Здесь также следует отталкиваться от требований актуальности. Если файлы обновляются нечасто (к примеру, происходит выгрузка новых товаров по ночам), а повторить последние загрузки несложно - достаточно ограничиться созданием регулярной полной копии раз в сутки, например. Если же файлы загружаются в реальном времени, а терять их нельзя - по аналогии с репликацией базы данных, стоит подумать о синхронизации статики на внешний резервный сервер.
Проблемой полного бэкапа часто является размер директории с данными. На деле, необязательно складывать отдельную копию на том же сервере перед ее отправкой на резервный (это, к тому же, создает нагрузку на жесткий диск). В своей работе для таких задач мы используем потоковую отправку архива сразу на резервный сервер.
tar czhf - /home/bitrix/www/ --exclude=bitrix/managed_cache --exclude=bitrix/stack_cache --exclude=bitrix/cache | ssh $SSH "cat -> ${RPATH}/${FN}" \; >> $LOG 2>&1 || exit $TAR_FAIL
Для онлайн копирования мы применяем lsyncd. Это демон, связывающий события inotify, извещающие об изменении файлов на файловой системе и вызывающий для этих файлов rsync. Lsyncd удобная, но опасная утилита - это важно учесть. На старте, lsyncd запускает rsync по всей директории, которую вы хотите "реплицировать" - как минимум, это создает нагрузку. Но главное - в зависимости от того, как собрали пакет в вашем репозитории, в lsyncd может быть по умолчанию включено удаление файлов при "репликации". Таким образом, если вы решите синхронизировать пустую директорию с директорией с данными - rsync, запущенный с ключом delete=true, удалит все файлы, которых нет на источнике, то есть очистит директорию целиком.
Также важно заметить, что процесс разархивирования большого архива будет долгим, в том числе для извлечения одного файла. По этой причине, даже если вам не нужна актуальность резервных данных в реальном времени, мы рекомендуем включить в план резервного копирования регулярный rsync статических данных для быстрого доступа к ним.
Резервное копирование конфигурационных файлов
Это довольно простая в применении, но часто упускаемая процедура. Грамотный системный администратор, конечно же, скажет, что правильным является построение продуманной системы конфигурации, однако, во многих случаях, до этого очень далеко. Практически постоянно в скриптах резервного копирования мы видим отсутствие копирования конфигурационных файлов системы.
В качестве минимальной и хорошо работающей практики мы рекомендуем создание в /etc git репозитория c регулярной автоматической фиксацией изменений по крону. В итоге, можно смотреть всю историю изменений конфигов, что важно при разворачивании бэкапа, когда что-то не так с конфигурацией, но не понятно что именно. Далее, директория /etc вместе с .git добавляется в бэкапный архив.
Мониторинг и проверки резервного копирования
По нашей статистике, бэкап ломается раз в 29 дней. Если вы его ни разу не проверяли, весьма вероятно, что из него изначально невозможно было восстановиться. Работа с бэкапами подразумевает мониторинг сервера в момент снятия бэкапа, проверку успешности и корректности снятого бэкапа.
Успешное снятие бэкапа - это только первый шаг. Важно проверить, что бэкап корректный. В минимальный план по проверке работоспособности бэкапов должно входить следующее:
- Мониторинг сервера во время создания бэкапов: нагрузка на сервер, доступность сайта, место на дисках.
- Мониторинг вывода скриптов резервного копирования: успешное завершение утилит резервного копирования.
- Мониторинг размера загруженных резервных копий: если резервная копия слишком мала или слишком велика - на это надо отреагировать.
- Мониторинг изменения размера загруженных резервных копий: если размер файлов нового бэкапа не изменился, по сравнению с размером прошлого бэкапа - возможно, бэкап делается с неактуального резервного сервера.
- Мониторинг последней даты загруженных резервных копий: если файлы старые - резервные копии не загрузились.
В план резервного копирования обязательно должна входить процедура проверки возможности восстановиться из резервной копии. В качестве минимальной процедуры - проверка возможности распаковать архив, проверка возможности восстановить базу данных. В идеальном плане - в процедуры должен входить запуск полноценной копии сайта из резервной копии.
Наконец, самое важное, что хотелось бы объяснить этой статьей - процесс организации резервного копирования никак не может быть единовременной процедурой. Бэкапы могут ломаться, конфигурация системы, ее структура, ПО, которое на ней работает - все это может постоянно изменяться. Регулярный контроль - основа работающей резервной копии, актуальных данных и душевного спокойствия.