Резервное копирование в продакшене: или как не стать героем после инцидента
Почему бэкапы — это не просто кнопка "Создать"
Вы когда-нибудь теряли данные? Не в тестовом окружении, а в продакшене, когда клиент звонит в 3 утра и спрашивает, где его заказы. Или когда DBA уходит в отпуск, а вы обнаруживаете, что никто не знает, как восстановить базу из бэкапа.
Резервное копирование — это не просто архивирование данных. Это система, которая должна:
- Работать автоматически, чтобы не зависеть от ручных действий.
- Восстанавливаться быстро, чтобы минимизировать время простоя.
- Быть проверенной, чтобы не оказаться "фиктивной" защитой.
- Масштабироваться, чтобы не ломаться при росте данных.
Если у вас нет четкой стратегии, то через полгода вы получите:
- Бэкапы, которые никто не проверяет.
- Архивы, которые занимают гигабайты, но никому не нужны.
- Восстановление, которое занимает часы или вообще невозможно.
Проблемы, которые решает правильная стратегия
Человеческий фактор Команды часто пренебрегают бэкапами, потому что "все работает". Пока не работает. Например, в 2021 году GitLab потерял данные из-за ошибки в скрипте резервного копирования. Причина? Никто не проверял, что бэкапы действительно восстанавливаются.
Ограниченные ресурсы В продакшене нельзя позволить себе бесконечное потребление дискового пространства или CPU. Нужно балансировать между частотой бэкапов и их размером.
Разные типы данных Не все данные одинаковы. Транзакционные базы (PostgreSQL, MySQL) требуют одного подхода, а NoSQL (MongoDB, Cassandra) — другого. А что делать с логами, конфигами и метаданными?
Сложные окружения Микросервисы, репликация, шардинг — все это усложняет резервное копирование. Если вы не учитываете эти нюансы, бэкапы могут быть неполными или несовместимыми.
Практические шаги: как построить стратегию
1. Определите RPO и RTO
Два ключевых показателя:
- RPO (Recovery Point Objective) — максимально допустимая потеря данных. Например, 15 минут означает, что вы можете позволить себе потерять изменения, сделанные за последние 15 минут.
- RTO (Recovery Time Objective) — максимальное время восстановления. Например, 1 час означает, что система должна быть восстановлена за час или меньше.
Пример: Если у вас интернет-магазин, где пользователи добавляют товары в корзину, RPO = 5 минут, а RTO = 30 минут. Это значит, что вы должны иметь бэкапы каждые 5 минут и восстанавливаться за полчаса.
2. Выберите уровень бэкапов
Не все бэкапы одинаковы. Вот три основных типа:
| Тип | Описание | Когда использовать | Пример команды (PostgreSQL) |
|---|---|---|---|
| Full | Полная копия всех данных. | Еженедельно или ежемесячно. | pg_basebackup -D /path/to/backup -Ft -z -P |
| Incremental | Копия только измененных данных с момента последнего бэкапа. | Ежедневно или почасов. | pg_dump -Fc --incremental --file=backup.dump |
| Log-based (WAL) | Копия транзакционных логов для точечного восстановления. | Каждые 5-15 минут. | Настройка pg_wal + wal-g или barman |
Практический пример для MySQL:
# Полный бэкап (еженедельно)
mysqldump -u root -p --single-transaction --routines --triggers --events --all-databases | gzip > /backups/full_$(date +\%Y-\%m-\%d).sql.gz
# Инкрементальный бэкап (ежедневно)
mysqldump -u root -p --single-transaction --where="updated_at > '2023-01-01'" database_name | gzip > /backups/incremental_$(date +\%Y-\%m-\%d).sql.gz
3. Автоматизация и проверка
Ручные бэкапы — это лотерея. Нужно автоматизировать и проверять:
Пример cron-задачи для PostgreSQL с использованием barman:
# /etc/cron.d/barman
0 2 * * * barman backup server1 --wal --create-slot --if-not-exists --archive
30 2 * * * barman backup server1 --wal --create-slot --if-not-exists --archive
0 3 * * * barman backup server1 --wal --create-slot --if-not-exists --archive
Скрипт проверки восстановления (bash):
#!/bin/bash
BACKUP_DIR="/backups/postgres"
RESTORE_DIR="/tmp/restore_test"
# Восстанавливаем из последнего бэкапа
pg_restore -d postgres -U postgres --clean --if-exists --no-owner --no-privileges $BACKUP_DIR/latest.dump
# Проверяем, что данные восстановлены (пример для таблицы users)
if pg_table_size('users') > 0; then
echo "Восстановление прошло успешно"
else
echo "Ошибка: таблица users пустая!" | mail -s "АЛЕРТ: Бэкап не восстанавливается" admin@example.com
fi
4. Хранение бэкапов
Где хранить бэкапы? Варианты:
| Способ | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Локальное хранилище (NFS, SSD) | Быстрое восстановление, простота. | Риск потери при пожарах/кражах. | Тестовые окружения. |
| Облачные бэкапы (S3, GCS) | Безопасность, масштабируемость. | Задержки при восстановлении. | Производственные системы. |
| Дисковые массивы (RAID, Ceph) | Высокая надежность. | Дорого, сложно настраивать. | Критические системы. |
Пример настройки бэкапов в S3 с помощью wal-g (PostgreSQL):
# Конфиг wal-g
[wal-g]
wal_dir = /var/lib/postgresql/wal
s3_prefix = my-db-backups
s3_bucket = my-backup-bucket
s3_region = us-east-1
Команда для отправки бэкапов в S3:
wal-g backup-push /var/lib/postgresql/data
5. Мониторинг и логирование
Нужно знать, что бэкапы создаются и проходят проверку. Пример настройки мониторинга с Prometheus и Alertmanager:
Конфиг Prometheus для мониторинга бэкапов (PostgreSQL):
- job_name: 'barman'
static_configs:
- targets: ['localhost:9100']
metrics_path: '/metrics'
Пример алерта для оповещения о неудачных бэкапах:
groups:
- name: backup-alerts
rules:
- alert: BackupFailed
expr: barman_backup_status{status="failed"} == 1
for: 5m
labels:
severity: critical
annotations:
summary: "Бэкап {{ $labels.server }} не удался"
description: "Последние {{ $labels.backup_id }} бэкап завершился с ошибкой"
Типичные ошибки и как их избежать
Отсутствие проверки бэкапов
- Проблема: Скрипты создают бэкапы, но никто не проверяет, восстанавливаются ли они.
- Решение: Автоматизируйте тесты восстановления (как в примере выше).
Игнорирование WAL-логов
- Проблема: Полные бэкапы создаются раз в неделю, а данные меняются каждую минуту. При сбое теряются дни данных.
- Решение: Используйте log-based бэкапы (WAL) для точечного восстановления.
Хранение всех бэкапов вечно
- Проблема: Диск заполняется за месяц, потому что никто не удаляет старые бэкапы.
- Решение: Настройте политику хранения (например, 7 дней инкрементальных + 4 недели полных).
Ручные настройки без документации
- Проблема: DBA уходит, а новый не знает, как настроить бэкапы.
- Решение: Документируйте все настройки (примеры конфигов, команды, схемы хранения).
Забывчивость с правами доступа
- Проблема: Бэкапы создаются под пользователем без прав на восстановление.
- Решение: Используйте сервисные аккаунты с минимальными правами (например,
backup_userс рольюpg_backup).
Практический вывод: как начать сегодня
Начните с аудита
- Проверьте, какие бэкапы у вас уже есть.
- Узнайте, когда они создавались в последний раз.
- Попробуйте восстановить тестовые данные.
Настройте базовые бэкапы
- Для PostgreSQL:
pg_basebackup+barman/wal-g. - Для MySQL:
mysqldump+ cron + проверка скриптом. - Для MongoDB:
mongodump+mongorestore+ тесты.
- Для PostgreSQL:
Автоматизируйте проверку
- Добавьте скрипт, который раз в неделю пытается восстановить данные в тестовую базу.
Документируйте процесс
- Опишите, как восстановить базу в случае аварии.
- Укажите контакты ответственных за бэкапы.
Настройте мониторинг
- Отслеживайте статус бэкапов (успех/неудача).
- Настраивайте алерты на неудачные попытки.
Заключение: бэкапы — это не опция, а обязанность
Резервное копирование — это не то, чем можно заняться "позже". Это часть инфраструктуры, которая должна работать сегодня, чтобы не платить завтра.
Проверьте себя:
- Может ли ваша команда восстановить базу данных сейчас?
- Знает ли кто-то, как это сделать, если основной администратор заболеет?
- Сколько данных вы можете позволить себе потерять?
Если на эти вопросы нет уверенных ответов — приступайте к настройке стратегии сейчас. Потому что вопрос не "зачем бэкапы?", а "как быстро вы хотите восстановиться после инцидента?".