Есть проверенный способ узнать, как в компании обстоят дела с бэкапами. Спросите не «делаете ли вы резервные копии», а «когда последний раз вы восстанавливались из копии на чистый сервер и сколько это заняло». В ответ обычно наступает пауза.
Резервное копирование — та область, где ощущение защищённости появляется гораздо раньше реальной защищённости. Скрипт настроен, файлы в хранилище лежат, место занимается — значит, всё в порядке. Проверить это утверждение можно только один раз, и обычно этот раз происходит в очень неудачный день.
Разберём, как собрать схему бэкапов в объектное хранилище S3, которая действительно работает, и на чём чаще всего спотыкаются.
Почему именно объектное хранилище
Классический вариант «копировать на второй диск того же сервера» защищает ровно от одного сценария: вы случайно удалили файл. От выхода из строя сервера, от шифровальщика, от ошибки провайдера, от компрометации через уязвимость в веб-приложении — не защищает вообще. Копия, доступная с той же машины под тем же пользователем, разделит её судьбу.
Объектное хранилище решает главную проблему: копия физически лежит в другом месте, доступ к ней отделён от сервера и управляется отдельными ключами. Если сервер скомпрометирован, злоумышленник получит те ключи, что лежат на сервере, — и вот здесь важна деталь, которую почти все пропускают: ключи должны позволять только запись, но не удаление.
У всех S3-совместимых хранилищ есть политики доступа. Ключ, которым сервер отправляет бэкапы, не должен уметь удалять объекты и менять политики жизненного цикла. Иначе первое, что сделает грамотный шифровальщик, — почистит ваше хранилище перед тем, как зашифровать диски. Это не паранойя, это стандартный сценарий последних лет.
Если хранилище поддерживает версионирование и блокировку объектов на запись — включайте. Это превращает «копия лежит в облаке» в «копию физически невозможно уничтожить в течение N дней».
Что копировать: три уровня, которые часто путают
Разговор о бэкапах обычно сразу уходит в технику, хотя начинать нужно с вопроса «что именно мы восстанавливаем».
Первый уровень — данные. Базы данных, пользовательские файлы, загрузки, вложения, документы. Это то, что невозможно воссоздать: потеря означает потерю навсегда. Здесь нужны самые частые копии и самая длинная глубина хранения.
Второй уровень — конфигурация. Конфиги nginx, systemd-юниты, правила фаервола, cron, содержимое /etc, переменные окружения. Технически это восстанавливается руками, но на практике «руками» означает от четырёх часов до двух дней вспоминания, почему здесь стоял именно такой параметр. Копировать нужно, но реже.
Третий уровень — код и артефакты. Обычно уже лежит в git, поэтому отдельный бэкап не нужен. Исключение — если у вас на сервере живут файлы, которых нет в репозитории: сгенерированные сертификаты, ключи, локальные патчи. Их стоит явно перенести в первый уровень или в хранилище секретов.
Практическая ошибка номер один: копируют базу и забывают про загруженные пользователями файлы. Восстановление проходит успешно, база на месте, а вместо картинок товаров на сайте — битые ссылки. Обратная ошибка встречается реже, но тоже бывает: копируют весь диск целиком, включая кэши, временные файлы и логи, и удивляются, почему бэкап занимает четыреста гигабайт и передаётся четыре часа.
Базы данных: почему копировать файлы недостаточно
Отдельно про базы, потому что здесь ошибка стоит дороже всего.
Копировать файлы работающей базы обычным rsync или tar нельзя. Точнее, можно, но восстановить из такой копии в общем случае не получится: вы поймаете файлы в разном состоянии на разные моменты времени, и база откажется подниматься либо, что хуже, поднимется с повреждёнными данными. Для PostgreSQL это pg_dump или базовая копия с архивированием WAL, для MySQL — mysqldump, xtrabackup или аналог, для MS SQL — штатные средства.
Второй момент — консистентность между базой и файлами. Если у вас интернет-магазин, и база копируется в три часа ночи, а файлы — в четыре, то заказ, созданный в 03:30, попадёт в файлы, но не попадёт в базу. Для большинства систем это некритично, но знать об этом надо, а для финансовых данных — планировать окно, когда оба среза берутся вместе.
Третий момент — размер. Полный дамп базы в сто гигабайт каждую ночь — это сто гигабайт трафика, времени и места, каждую ночь. Здесь помогает связка: полная копия раз в неделю плюс инкрементальные или журналы транзакций между ними. Это усложняет восстановление, поэтому для небольших баз честнее делать простой полный дамп — простота восстановления важнее экономии места.
Расписание и глубина хранения
Схема, которая закрывает большинство случаев, называется дед-отец-сын и звучит скучно ровно до первого реального восстановления.
Ежедневные копии хранятся неделю или две. Они отвечают на вопрос «верните, как было вчера». Это самый частый запрос: кто-то удалил не тот документ, обновление сломало данные, интеграция затёрла цены.
Еженедельные хранятся месяц-полтора. Они отвечают на вопрос «когда это сломалось» — ситуация, когда проблему заметили не сразу.
Ежемесячные хранятся год. Они нужны реже, но именно они спасают в историях типа «налоговая запросила данные за март» или «выяснилось, что обмен полгода писал мусор в справочник».
Важнее, чем сама схема, — понимать, на какой вопрос отвечает каждая копия. Ежедневных копий за год не нужно никому, а вот отсутствие месячных обнаруживается ровно в тот момент, когда они нужны.
Про частоту: сутки — это разумный интервал по умолчанию, но он означает, что в худшем случае вы теряете день работы. Спросите у бизнеса, приемлемо ли это. Иногда ответ — «конечно, нет», и тогда разговор переходит в область репликации и журналов транзакций, а не ночных дампов.
Настраивать удаление старых копий вручную не нужно: у объектных хранилищ есть правила жизненного цикла, которые сами перекладывают старые объекты в холодный класс и удаляют по истечении срока. Это дешевле и надёжнее, чем скрипт с find -mtime, который однажды удалит не то.
Шифрование
Копия, лежащая в чужом хранилище, должна быть зашифрована до отправки. Не потому, что провайдер плохой, а потому, что доступ к бакету — это ещё одна поверхность атаки, и ключ от неё может утечь способами, которые вы не контролируете.
Шифрование на стороне клиента, до загрузки, — правильный подход. Ключ хранится отдельно от сервера и отдельно от хранилища. И вот здесь появляется главный подвох всей темы: ключ шифрования, который лежит только на сервере, который вы бэкапите, — бесполезен. При потере сервера вы получите зашифрованные копии, которые невозможно открыть. Ключ должен лежать в третьем месте, и это место должно быть известно не только одному человеку в компании.
Три ошибки, которые повторяются чаще всего
Первая: бэкап, который никто не проверял. Скрипт может годами класть в хранилище пустой архив или дамп с ошибкой — размер файла при этом будет выглядеть правдоподобно. Минимальная проверка — контроль размера копии относительно предыдущей и код возврата команды. Настоящая проверка — регулярное тестовое восстановление.
Вторая: молчаливый провал. Cron отработал, скрипт упал, вывод ушёл в никуда. Классика: сервер поменяли, ключи от хранилища не перенесли, копии не делаются четыре месяца, никто не в курсе. Отсюда правило: бэкап должен сообщать не только об ошибке, но и об отсутствии успеха. Отсутствие свежей копии за последние сутки — это инцидент, даже если ничего не падало.
Третья: копия, до которой нельзя дотянуться в аварии. Инструкция по восстановлению лежит в вики на том же сервере. Ключи от хранилища — в менеджере паролей, который поднят там же. Доступ к бакету есть только у одного человека, и он в отпуске. Всё это выясняется исключительно в день аварии.
Восстановление — это и есть бэкап
Единственная метрика, которая имеет значение: сколько времени занимает возврат сервиса из копии на чистой машине и сколько данных при этом теряется. Пока эти два числа не измерены на практике, у вас нет бэкапов — у вас есть файлы в хранилище и надежда.
Тестовое восстановление раз в квартал звучит как бюрократия, но занимает пару часов и отвечает сразу на несколько вопросов: цела ли копия, помните ли вы порядок действий, работает ли ключ шифрования, укладываетесь ли вы в обещанное бизнесу время. Первый такой тест почти всегда обнаруживает что-нибудь неприятное — и это лучший из возможных сценариев, потому что обнаруживает его не авария.
Отдельно полезно записать процедуру восстановления так, чтобы её мог выполнить не автор. Не «развернуть базу из дампа», а по шагам, с командами, с указанием, где лежат ключи и в каком порядке поднимаются сервисы. Проверяется просто: дайте инструкцию коллеге, который не участвовал в настройке, и посмотрите, где он застрянет.
Как это устроено в COSCIO
В нашей платформе бэкапы вынесены в отдельный модуль, и логика ровно та, что описана выше. Задания настраиваются на уровне сервера или базы, копии уходят в S3-совместимое хранилище по расписанию, глубина хранения задаётся раздельно для ежедневных, еженедельных и ежемесячных копий.
Практически ценная часть — не сам факт копирования, а контроль. Каждое задание отчитывается о результате, а отсутствие успешного выполнения в срок поднимает инцидент в общей ленте — то есть работает та самая защита от молчаливого провала, из-за которой чаще всего и обнаруживается через полгода, что копий нет. Учётные данные хранилища шифруются, а не лежат в открытом виде в конфиге на сервере.
Что платформа не делает за вас: не решает, что именно копировать, не проверяет за вас восстановление и не заменяет тестовый прогон. Это по-прежнему ваша ответственность, и никакой инструмент её не снимает.
Минимальная схема, с которой можно начать сегодня
Если сейчас бэкапов нет вообще, не проектируйте идеальную систему — она не будет запущена. Сделайте минимум за один вечер.
Заведите бакет в S3-совместимом хранилище и создайте отдельный ключ доступа только на запись. Настройте ежедневный дамп базы и архив каталога с пользовательскими файлами, отправляйте их в бакет со сроком хранения четырнадцать дней. Настройте уведомление о том, что задание не выполнилось, — в мессенджер или на почту, куда вы реально смотрите. Запишите на одну страницу, как из этого восстановиться.
Через неделю проверьте: скачайте копию и разверните её на тестовой машине. Засеките время. Это число и есть ваш реальный уровень готовности — всё остальное можно улучшать постепенно.