Резервное копирование в продакшене: или как не стать героем после инцидента

Почему бэкапы — это не просто кнопка "Создать"

Вы когда-нибудь теряли данные? Не в тестовом окружении, а в продакшене, когда клиент звонит в 3 утра и спрашивает, где его заказы. Или когда DBA уходит в отпуск, а вы обнаруживаете, что никто не знает, как восстановить базу из бэкапа.

Резервное копирование — это не просто архивирование данных. Это система, которая должна:

  1. Работать автоматически, чтобы не зависеть от ручных действий.
  2. Восстанавливаться быстро, чтобы минимизировать время простоя.
  3. Быть проверенной, чтобы не оказаться "фиктивной" защитой.
  4. Масштабироваться, чтобы не ломаться при росте данных.

Если у вас нет четкой стратегии, то через полгода вы получите:

  • Бэкапы, которые никто не проверяет.
  • Архивы, которые занимают гигабайты, но никому не нужны.
  • Восстановление, которое занимает часы или вообще невозможно.

Проблемы, которые решает правильная стратегия

  1. Человеческий фактор Команды часто пренебрегают бэкапами, потому что "все работает". Пока не работает. Например, в 2021 году GitLab потерял данные из-за ошибки в скрипте резервного копирования. Причина? Никто не проверял, что бэкапы действительно восстанавливаются.

  2. Ограниченные ресурсы В продакшене нельзя позволить себе бесконечное потребление дискового пространства или CPU. Нужно балансировать между частотой бэкапов и их размером.

  3. Разные типы данных Не все данные одинаковы. Транзакционные базы (PostgreSQL, MySQL) требуют одного подхода, а NoSQL (MongoDB, Cassandra) — другого. А что делать с логами, конфигами и метаданными?

  4. Сложные окружения Микросервисы, репликация, шардинг — все это усложняет резервное копирование. Если вы не учитываете эти нюансы, бэкапы могут быть неполными или несовместимыми.


Практические шаги: как построить стратегию

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 }} бэкап завершился с ошибкой"

Типичные ошибки и как их избежать

  1. Отсутствие проверки бэкапов

    • Проблема: Скрипты создают бэкапы, но никто не проверяет, восстанавливаются ли они.
    • Решение: Автоматизируйте тесты восстановления (как в примере выше).
  2. Игнорирование WAL-логов

    • Проблема: Полные бэкапы создаются раз в неделю, а данные меняются каждую минуту. При сбое теряются дни данных.
    • Решение: Используйте log-based бэкапы (WAL) для точечного восстановления.
  3. Хранение всех бэкапов вечно

    • Проблема: Диск заполняется за месяц, потому что никто не удаляет старые бэкапы.
    • Решение: Настройте политику хранения (например, 7 дней инкрементальных + 4 недели полных).
  4. Ручные настройки без документации

    • Проблема: DBA уходит, а новый не знает, как настроить бэкапы.
    • Решение: Документируйте все настройки (примеры конфигов, команды, схемы хранения).
  5. Забывчивость с правами доступа

    • Проблема: Бэкапы создаются под пользователем без прав на восстановление.
    • Решение: Используйте сервисные аккаунты с минимальными правами (например, backup_user с ролью pg_backup).

Практический вывод: как начать сегодня

  1. Начните с аудита

    • Проверьте, какие бэкапы у вас уже есть.
    • Узнайте, когда они создавались в последний раз.
    • Попробуйте восстановить тестовые данные.
  2. Настройте базовые бэкапы

    • Для PostgreSQL: pg_basebackup + barman/wal-g.
    • Для MySQL: mysqldump + cron + проверка скриптом.
    • Для MongoDB: mongodump + mongorestore + тесты.
  3. Автоматизируйте проверку

    • Добавьте скрипт, который раз в неделю пытается восстановить данные в тестовую базу.
  4. Документируйте процесс

    • Опишите, как восстановить базу в случае аварии.
    • Укажите контакты ответственных за бэкапы.
  5. Настройте мониторинг

    • Отслеживайте статус бэкапов (успех/неудача).
    • Настраивайте алерты на неудачные попытки.

Заключение: бэкапы — это не опция, а обязанность

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

Проверьте себя:

  • Может ли ваша команда восстановить базу данных сейчас?
  • Знает ли кто-то, как это сделать, если основной администратор заболеет?
  • Сколько данных вы можете позволить себе потерять?

Если на эти вопросы нет уверенных ответов — приступайте к настройке стратегии сейчас. Потому что вопрос не "зачем бэкапы?", а "как быстро вы хотите восстановиться после инцидента?".