Резервное копирование: стратегии, инструменты, автоматизация и тестирование

Данные — это самое ценное, что есть у проекта. Серверы можно переустановить, код — восстановить из Git, но потерянная база данных с заказами, пользователями и транзакциями может означать конец бизнеса. По статистике, большинство компаний, потерявших критически важные данные и не имевших бэкапов, закрываются в течение года.

Резервное копирование — это не просто «скопировать файлы куда-нибудь». Это целая дисциплина, которая включает стратегию, инструменты, автоматизацию, шифрование и, самое главное, регулярную проверку восстановления.

В этой статье мы подробно разберём:

  • Зачем нужны бэкапы и какие угрозы они закрывают.
  • Правило 3-2-1 и другие стратегии.
  • Типы бэкапов: полные, инкрементные, дифференциальные.
  • Инструменты: rsync, tar, mysqldump, pg_dump.
  • Продвинутые инструменты: BorgBackup, Restic, Duplicity.
  • Бэкап баз данных MySQL и PostgreSQL.
  • Хранение в облаке: S3, Backblaze B2, Wasabi.
  • Шифрование бэкапов.
  • Автоматизацию через cron и systemd timers.
  • Верификацию и тестирование восстановления.
  • Частые ошибки и лучшие практики.

1. Зачем нужны бэкапы

Бэкапы защищают от множества угроз:

УгрозаПоследствияКак спасает бэкап
Аппаратный сбойВыход из строя диска, сервераВосстановление на новом сервере
Человеческий факторСлучайное удаление файлов, rm -rfОткат к предыдущей версии
Взлом и шифровальщикиДанные зашифрованы, требуют выкупВосстановление из чистой копии
Ошибка в кодеМассовое удаление или порча данныхОткат к состоянию до обновления
Стихийное бедствиеПожар, наводнение, отключение питанияВосстановление из удалённой копии
Ошибка обновленияНовая версия ПО ломает БДОткат к предыдущей версии

Ключевая мысль: бэкап бесполезен, если его нельзя восстановить. Поэтому главный критерий — не наличие бэкапа, а возможность восстановления.

2. Стратегии резервного копирования

2.1 Правило 3-2-1

Классическая стратегия, которую рекомендуют все специалисты по данным:

  • 3 копии данных (основная + две резервные).
  • 2 разных носителя (например, локальный диск и облако).
  • 1 копия вне офиса (удалённое хранилище, другой город).

Пример:

  • Основные данные — на сервере.
  • Локальный бэкап — на отдельном диске на том же сервере.
  • Удалённый бэкап — в облаке (S3, Backblaze B2).

2.2 Правило 3-2-1-1-0

Расширенная версия:

  • 3 копии.
  • 2 разных носителя.
  • 1 копия вне офиса.
  • 1 копия offline (не подключена к сети, защита от шифровальщиков).
  • 0 ошибок при проверке восстановления.

2.3 RPO и RTO

  • RPO (Recovery Point Objective) — сколько данных вы готовы потерять. Если RPO = 1 час, бэкапы должны делаться каждый час.
  • RTO (Recovery Time Objective) — как быстро вы должны восстановиться. Если RTO = 30 минут, нужна горячая реплика.

Эти параметры определяют частоту бэкапов и выбор инструментов.

2.4 Каскадная стратегия (дедовский метод)

  • Ежедневные бэкапы — хранятся 7 дней.
  • Еженедельные — хранятся 4 недели.
  • Ежемесячные — хранятся 12 месяцев.
  • Ежегодные — хранятся несколько лет.

Это позволяет экономить место, сохраняя долгосрочную историю.

3. Типы бэкапов

ТипОписаниеПлюсыМинусы
Полный (Full)Копия всех данныхПростое восстановлениеМного места, долго
Инкрементный (Incremental)Только изменения с последнего бэкапа (любого типа)Быстро, мало местаВосстановление требует всей цепочки
Дифференциальный (Differential)Изменения с последнего полного бэкапаБыстрее восстановление, чем инкрементБольше места, чем инкремент
Синхронизация (Mirror)Точная копия, изменения применяются сразуАктуальностьЕсли удалили файл — он удалится и в бэкапе

Рекомендация: комбинируйте полные и инкрементные бэкапы. Например, полный раз в неделю, инкрементный — каждый день.

4. Базовые инструменты

4.1 tar — архивация файлов

Bash
# Создание архива
tar -czf backup_$(date +%Y%m%d).tar.gz /var/www/html

# Распаковка
tar -xzf backup_20240310.tar.gz -C /restore/

# Исключение директорий
tar -czf backup.tar.gz --exclude='/var/www/html/cache' --exclude='*.log' /var/www/html

Плюсы: простота, встроен в Linux.
Минусы: нет инкрементности, каждый раз полный архив.

4.2 rsync — синхронизация файлов

Bash
# Локальная синхронизация
rsync -av --delete /var/www/html/ /backup/html/

# Синхронизация с удалённым сервером
rsync -avz -e ssh /var/www/html/ user@backup-server:/backup/html/

# Инкрементная синхронизация с использованием hard links (экономия места)
rsync -av --link-dest=/backup/html/last /var/www/html/ /backup/html/$(date +%Y%m%d)/

Ключи:

  • -a — архивный режим (сохраняет права, владельцев, время).
  • -v — подробный вывод.
  • -z — сжатие при передаче.
  • --delete — удалять файлы в приёмнике, которых нет в источнике.
  • --link-dest — создавать жёсткие ссылки на неизменённые файлы (экономия места).

Плюсы: эффективная синхронизация, работа по SSH.
Минусы: не хранит историю версий (если без --link-dest).

4.3 mysqldump — бэкап MySQL

Bash
# Дамп одной базы
mysqldump -u root -p mydb > mydb_$(date +%Y%m%d).sql

# Дамп всех баз
mysqldump -u root -p --all-databases > all_dbs_$(date +%Y%m%d).sql

# Сжатие на лету
mysqldump -u root -p mydb | gzip > mydb_$(date +%Y%m%d).sql.gz

# Согласованный дамп без блокировки таблиц (InnoDB)
mysqldump -u root -p --single-transaction mydb > mydb.sql

Восстановление:

Bash
mysql -u root -p mydb < mydb_20240310.sql
# или
gunzip < mydb_20240310.sql.gz | mysql -u root -p mydb

4.4 pg_dump — бэкап PostgreSQL

Bash
# Дамп одной базы
pg_dump -U postgres mydb > mydb_$(date +%Y%m%d).sql

# Дамп в кастомном формате (сжатие, параллельное восстановление)
pg_dump -U postgres -Fc mydb > mydb_$(date +%Y%m%d).dump

# Дамп всех баз
pg_dumpall -U postgres > all_dbs_$(date +%Y%m%d).sql

Восстановление:

Bash
psql -U postgres mydb < mydb_20240310.sql
# или для кастомного формата
pg_restore -U postgres -d mydb mydb_20240310.dump

5. Продвинутые инструменты

5.1 BorgBackup

Borg — мощный инструмент с дедупликацией, сжатием и шифрованием.

Установка:

Bash
sudo apt install borgbackup

Инициализация репозитория:

Bash
borg init --encryption=repokey /backup/borg

Создание бэкапа:

Bash
borg create /backup/borg::'{now:%Y-%m-%d_%H:%M}' /var/www/html /etc/nginx

Просмотр архивов:

Bash
borg list /backup/borg

Восстановление:

Bash
borg extract /backup/borg::2024-03-10_12:00

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

5.2 Restic

Restic — современный инструмент с поддержкой облаков (S3, Backblaze B2, Wasabi).

Установка:

Bash
sudo apt install restic

Инициализация:

Bash
restic init --repo s3:s3.amazonaws.com/my-bucket

Создание бэкапа:

Bash
restic -r s3:s3.amazonaws.com/my-bucket backup /var/www/html

Восстановление:

Bash
restic -r s3:s3.amazonaws.com/my-bucket restore latest --target /restore

Плюсы: поддержка облаков, шифрование, дедупликация, простота.
Минусы: требует настройки доступа к облаку.

5.3 Duplicity

Duplicity — инструмент с шифрованием и поддержкой облаков.

Установка:

Bash
sudo apt install duplicity

Создание бэкапа:

Bash
duplicity /var/www/html s3://s3.amazonaws.com/my-bucket

Восстановление:

Bash
duplicity restore s3://s3.amazonaws.com/my-bucket /restore

Плюсы: шифрование, инкрементность, облака.
Минусы: сложнее в настройке, чем Restic.

5.4 Сравнение инструментов

ИнструментДедупликацияШифрованиеОблакаСложность
tarНетНетНетНизкая
rsyncЧастичная экономия места через жёсткие ссылки (hard links) — не дедупликация в полном смыслеНетЧерез SSHНизкая
BorgДаДаНет (только SSH)Средняя
ResticДаДаДаСредняя
DuplicityНетДаДаСредняя

6. Бэкап баз данных

6.1 MySQL / MariaDB

Логический бэкап (mysqldump):

Bash
mysqldump -u root -p --single-transaction --routines --triggers --events mydb | gzip > mydb_$(date +%Y%m%d).sql.gz

Физический бэкап (Percona XtraBackup):

Bash
xtrabackup --backup --target-dir=/backup/mysql/
xtrabackup --prepare --target-dir=/backup/mysql/

Плюсы физического: быстрее, не блокирует БД.
Минусы: требует установки, сложнее.

6.2 PostgreSQL

Логический бэкап (pg_dump):

Bash
pg_dump -U postgres -Fc mydb > mydb_$(date +%Y%m%d).dump

Физический бэкап (pg_basebackup):

Bash
pg_basebackup -U replicator -D /backup/postgresql/ -P -v

Непрерывное архивирование (WAL):

Настройте archive_mode = on и archive_command для копирования WAL-логов. Это позволяет восстановиться на любой момент времени (Point-in-Time Recovery).

6.3 Репликация как часть стратегии

Репликация — это не бэкап, но она дополняет его:

  • Master-slave — если мастер падает, слейв можно повысить.
  • Задержка репликации — можно настроить слейв с задержкой на час, чтобы защититься от случайного удаления данных.

Важно: репликация не защищает от DROP TABLE — команда мгновенно применится на слейве. Репликация не спасает от логических ошибок (DROP DATABASE, UPDATE без WHERE). Для этого нужны point-in-time recovery (WAL-архивы, binlog) или снапшоты.

7. Хранение в облаке

Облако — это «1» из правила 3-2-1 (копия вне офиса).

7.1 AWS S3

Bash
# Загрузка файла
aws s3 cp backup.tar.gz s3://my-bucket/backups/

# Синхронизация директории
aws s3 sync /backup/ s3://my-bucket/backups/

Настройка lifecycle: автоматическое удаление старых бэкапов через N дней.

7.2 Backblaze B2

Дешевле S3, совместим с S3 API.

Bash
b2 upload-file my-bucket backup.tar.gz backups/backup.tar.gz

7.3 Wasabi

Ещё один дешёвый провайдер, совместимый с S3.

Bash
aws s3 cp backup.tar.gz s3://my-bucket/ --endpoint-url=https://s3.wasabisys.com

7.4 Сравнение облаков

ПровайдерЦена за ГБОсобенности
AWS S3~$0.023Много сервисов, сложный биллинг
Backblaze B2~$0.005Дешёвый, простой
Wasabi~$0.0059Нет платы за трафик

8. Шифрование бэкапов

Если бэкап содержит конфиденциальные данные, его нужно шифровать.

8.1 GPG

Bash
# Шифрование
gpg --symmetric --cipher-algo AES256 backup.tar.gz

# Расшифровка
gpg --decrypt backup.tar.gz.gpg > backup.tar.gz

8.2 openssl

Bash
# Шифрование
openssl enc -aes-256-cbc -salt -in backup.tar.gz -out backup.tar.gz.enc

# Расшифровка
openssl enc -d -aes-256-cbc -in backup.tar.gz.enc -out backup.tar.gz

8.3 Встроенное шифрование Borg/Restic

Borg и Restic шифруют данные автоматически при создании репозитория. Это самый удобный способ.

9. Автоматизация бэкапов

9.1 Скрипт бэкапа с ротацией

Bash
#!/bin/bash
# backup.sh
set -euo pipefail

BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)
WEB_ROOT="/var/www/html"
DB_NAME="mydb"
DB_USER="${DB_USER:-root}"
DB_PASS="${DB_PASS:-$(cat /etc/backup/db_pass 2>/dev/null)}"
RETENTION_DAYS=7

if [ -z "$DB_PASS" ]; then
    echo "ОШИБКА: Пароль БД не найден. Укажите DB_PASS или создайте /etc/backup/db_pass" >&2
    exit 1
fi

# Создание директории
mkdir -p "$BACKUP_DIR"

# Бэкап файлов
tar -czf "$BACKUP_DIR/files_$DATE.tar.gz" "$WEB_ROOT"

# Бэкап базы данных
mysqldump -u "$DB_USER" -p"$DB_PASS" --single-transaction "$DB_NAME" | gzip > "$BACKUP_DIR/db_$DATE.sql.gz"

# Шифрование
gpg --symmetric --cipher-algo AES256 --batch --passphrase-file /etc/backup.key "$BACKUP_DIR/files_$DATE.tar.gz"
gpg --symmetric --cipher-algo AES256 --batch --passphrase-file /etc/backup.key "$BACKUP_DIR/db_$DATE.sql.gz"

# Удаление незашифрованных файлов
rm "$BACKUP_DIR/files_$DATE.tar.gz" "$BACKUP_DIR/db_$DATE.sql.gz"

# Загрузка в облако
aws s3 cp "$BACKUP_DIR/files_$DATE.tar.gz.gpg" s3://my-bucket/backups/
aws s3 cp "$BACKUP_DIR/db_$DATE.sql.gz.gpg" s3://my-bucket/backups/

# Удаление старых бэкапов
find "$BACKUP_DIR" -name "*.gpg" -mtime +"$RETENTION_DAYS" -delete

echo "Бэкап завершён: $DATE"

ВАЖНО! Никогда не храните пароли в скриптах. Файл с паролем должен храниться отдельно от бэкапов, иметь права 600 и быть недоступным для обычных пользователей. Ещё лучше — использовать аппаратные модули или секретные хранилища

9.2 Cron

Bash
# Редактирование crontab
crontab -e

# Запуск каждый день в 2:00
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

# Запуск каждый час (для критичных данных)
0 * * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

9.3 Systemd timers

Альтернатива cron с более гибкими настройками.

/etc/systemd/system/backup.service:

/etc/systemd/system/backup.timer:

Включение:

Bash
sudo systemctl enable backup.timer
sudo systemctl start backup.timer

9.4 Мониторинг бэкапов

Настройте уведомления об успехе/неудаче.

Bash
# В конце скрипта
if [ $? -eq 0 ]; then
    echo "Backup successful" | mail -s "Backup OK" admin@example.com
else
    echo "Backup FAILED" | mail -s "Backup FAILED" admin@example.com
fi

Или отправляйте в Telegram через бота. Современные способы уведомлений:

Bash
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
  -d chat_id="${TELEGRAM_CHAT_ID}" \
  -d text="Backup ${STATUS}: $(date)"

10. Верификация и тестирование восстановления

Это самый важный раздел. Бэкап, который не проверен, — это не бэкап.

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

Для tar:

Bash
tar -tzf backup.tar.gz > /dev/null && echo "OK"

Для Borg:

Bash
borg check /backup/borg

Для Restic:

Bash
restic -r s3:s3.amazonaws.com/my-bucket check

10.2 Тестовое восстановление

Регулярно (раз в месяц) восстанавливайте бэкап на тестовом сервере и проверяйте, что данные на месте.

Пример для MySQL:

Bash
# Восстановление на тестовом сервере
gunzip < db_20240310.sql.gz | mysql -u root -p test_mydb

# Проверка количества записей
mysql -u root -p -e "SELECT COUNT(*) FROM test_mydb.users;"

Ещё один уровень проверки: проверка схемы и индексов. Например, после восстановления можно сделать:

Bash
mysql -u root -p -e "SHOW CREATE TABLE test_mydb.users;"

10.3 Автоматическая проверка

Добавьте в скрипт бэкапа проверку:

Bash
# Проверка, что бэкап не пустой
if [ ! -s "$BACKUP_DIR/db_$DATE.sql.gz" ]; then
    echo "Backup file is empty!" | mail -s "Backup FAILED" admin@example.com
    exit 1
fi

# Проверка, что архив открывается для небольших архивов.
tar -tzf "$BACKUP_DIR/files_$DATE.tar.gz" > /dev/null
# Если архив большой, лучше проверять только наличие заголовка или первые N файлов
tar -tf "$BACKUP_DIR/files_$DATE.tar.gz" | head -n 5 > /dev/null 2>&1
if [ $? -ne 0 ]; then
    echo "Backup archive is corrupted!" | mail -s "Backup FAILED" admin@example.com
    exit 1
fi

11. Частые ошибки и лучшие практики

ОшибкаПоследствияРешение
Бэкапы не делаютсяПотеря данныхАвтоматизируйте через cron.
Бэкапы делаются, но не проверяютсяПри восстановлении выясняется, что архив битыйРегулярно тестируйте восстановление.
Бэкапы хранятся только на том же сервереПри отказе сервера теряются и данные, и бэкапыИспользуйте удалённое хранилище (правило 3-2-1).
Бэкапы не шифруютсяУтечка конфиденциальных данныхШифруйте (GPG, Borg, Restic).
Бэкап делается без --single-transactionБлокировка таблиц, неконсистентные данныеИспользуйте --single-transaction для InnoDB.
Нет ротацииДиск переполняетсяНастройте удаление старых бэкапов.
Бэкапы хранятся вечноРастущие расходы на облакоНастройте lifecycle policy.
Нет мониторингаБэкап упал, никто не заметилНастройте уведомления.
Восстановление не документированоПаника при сбоеНапишите инструкцию по восстановлению.
Бэкап только раз в деньПотеря данных за деньУвеличьте частоту для критичных данных.

ВАЖНО! —single-transaction гарантирует консистентность только для транзакционных движков (InnoDB, NDB). Для MyISAM используйте другие методы или мигрируйте на InnoDB

Лучшие практики:

  • Автоматизируйте. Ручные бэкапы забываются.
  • Проверяйте. Регулярно восстанавливайте на тестовом сервере.
  • Шифруйте. Особенно если храните в облаке.
  • Ротируйте. Храните ежедневные, еженедельные, ежемесячные копии.
  • Документируйте. Напишите инструкцию, как восстановить данные.
  • Мониторьте. Узнавайте о проблемах до того, как они станут критичными.
  • Тестируйте сценарии. Что если диск умер? Что если сервер украли? Что если база повреждена?

Помните: бэкап — это не тот, который делается, а тот, который восстанавливается. Регулярно проверяйте свои бэкапы, и вы сможете спать спокойно, зная, что данные в безопасности.