Классическая ловушка при проектировании отказоустойчивости — разрыв между ожиданиями бизнеса и возможностями инфраструктуры. На бумаге в SLA может быть зафиксировано RTO в 4 часа, но если терабайтный бэкап PostgreSQL физически разворачивается 8 часов из-за лимитов дисковой подсистемы, такой SLA не выдержит первого серьезного инцидента.
На практике планы Disaster Recovery (DR) часто пишутся «для галочки» и в полном отрыве от реальной архитектуры. Под катом — техническая изнанка проектирования отказоустойчивости: как приземлить RTO и RPO на реальную инфраструктуру, связать их со стоимостью простоя и взять эти метрики под контроль с помощью правильных инженерных подходов.
Также в статью включены практические инструменты: чек-лист для безопасного проведения DR-учений и перечень ключевых параметров, которые необходимо непрерывно мониторить для контроля рисков.
Что на самом деле измеряют RPO и RTO
Если отбросить сухую теорию, суть этих метрик сводится к двум вопросам:
-
сколько времени мы можем восстанавливаться;
-
сколько данных допустимо потерять.
RPO, Recovery Point Objective — это максимально допустимый объем потери данных, выраженный во времени. Если база бэкапится раз в сутки в 00:00, а сервер падает в 23:59, реальный RPO для такого сценария может составить почти 24 часа. Все изменения за день окажутся под угрозой.
RTO, Recovery Time Objective — это целевое время восстановления сервиса до состояния, когда он снова доступен пользователям или смежным системам.
Важно: RTO — это не только время восстановления из бэкапа. В честный RTO входят обнаружение аварии, реакция команды, подготовка инфраструктуры, восстановление данных, конфигурация сервисов, проверка целостности, переключение трафика и прогрев системы.
Упрощенно эту зависимость можно представить так:
Реальное RTO = Время обнаружения аварии + Время принятия решения о восстановлении + Время подготовки инфраструктуры + Время восстановления данных и сервисов + Время настройки конфигураций + Время проверки работоспособности + Время переключения трафика + Время прогрева системы
Если дамп PostgreSQL разворачивается за 2 часа, это еще не значит, что RTO компании равно двум часам. В условиях реального инцидента к этому таймингу неизбежно добавляются:
-
20 минут — на первичную диагностику и локализацию;
-
40 минут — на подготовку целевого окружения;
-
30 минут — на раскатку секретов и конфигураций;
-
40 минут — на валидацию данных и проверку консистентности;
-
10–20 минут — на переключение сетевого трафика.
Почему «у нас всё хорошо» — опасное заблуждение
Большинство проблем с DR возникают не из-за отсутствия бэкапов, а из-за неверных ожиданий.
-
Путают RTO и время восстановления из бэкапа. Это главная ловушка. Если ваш дамп PostgreSQL весит 500 ГБ и разворачивается на тестовом контуре за 2 часа, это НЕ значит, что ваше RTO = 2 часа. Сюда нужно заложить время на обнаружение аварии, развертывание чистой ОС/железа, накатывание конфигов, переключение DNS, валидацию данных и прогрев кэшей. В реальности 2 часа легко превращаются в 8.
-
Устанавливают одинаковые требования для всех систем. Требовать RTO < 15 минут для платежного шлюза и внутренней wiki — дорого и бессмысленно. Минимальный RTO требует другой архитектуры: репликации, standby-контуров, автоматизации failover, мониторинга и регулярных учений. Это стоит денег.
-
Не тестируют восстановление. DR-план, который ни разу не проверялся, — это не план, а гипотеза. Его реальная эффективность станет понятна только во время аварии, то есть в худший возможный момент.
-
Не учитывают зависимости. Сервис может быть восстановлен формально, но не работать из-за мертвой CRM, очереди, LDAP, DNS, Vault, object storage или внутреннего API. Поэтому DR нужно проектировать не для отдельных серверов, а для цепочек зависимостей.
Как мы получили 11 часов простоя вместо четырех
Несколько лет назад я участвовал в разборе крупного сбоя в корпоративной инфраструктуре. На бумаге всё выглядело хорошо: RTO — 4 часа, DR-план утвержден, бэкапы регулярно складываются в архив.
Но когда боевой кластер СУБД вышел из строя, штатный сценарий восстановления оказался нежизнеспособным. Вместо четырех часов система оставалась недоступной одиннадцать.
Проблем оказалось две.
Bus-фактор и монополия на доступы
Процедура инициализации резервного хранилища секретов требовала ручного ввода мастер-пароля. Пароль знал один ведущий инженер. На момент инцидента он был недоступен, а регламента экстренного восстановления доступа не существовало.
Инфраструктура была технически готова к восстановлению, но организационно процесс остановился.
Неучтенные каскадные зависимости
Основную систему удалось поднять примерно за 3 часа. Формально мы укладывались в целевой RTO.
Но приложение при запуске обращалось во внутреннюю legacy-CRM для валидации профилей. При проектировании DR эту CRM посчитали второстепенной и не включили в приоритетный контур восстановления.
В результате core-сервис начал тонуть в таймаутах, ожидая ответа от смежного компонента. Пришлось на ходу восстанавливать legacy-окружение, менять конфигурацию и перепроверять цепочку вызовов. Именно эти зависимости и съели большую часть времени.
Вывод простой: если система не может работать без зависимости, эта зависимость тоже часть вашего DR-плана.
Как рассчитать RTO и RPO
Процесс не должен начинаться с фразы «бизнес хочет 15 минут». Сначала нужно понять, какие системы действительно критичны и сколько стоит их простой.
Рабочий алгоритм выглядит так:
-
Инвентаризировать сервисы, базы данных, очереди, внешние API и инфраструктурные зависимости.
-
Провести BIA, Business Impact Analysis: оценить потери от простоя каждого сервиса.
-
Разделить системы по критичности.
-
Назначить RTO/RPO с учетом стоимости простоя и стоимости реализации DR.
-
Подобрать технологический подход: backup, PITR, репликация, standby, DRaaS.
-
Проверить цифры через тестовое восстановление.
-
Регулярно обновлять DR-план после изменений в архитектуре.
Пример матрицы:
Эта таблица не универсальна. Для одной компании CRM может быть вспомогательной системой, а для интернет-магазина — критическим элементом продаж. Поэтому матрица должна строиться от бизнес-процессов, а не от названий систем.
PostgreSQL: почему одного ночного бэкапа недостаточно
Если целевой RPO меньше 15 минут, а RTO меньше 1 часа, обычного pg_dump раз в сутки недостаточно.
Для PostgreSQL production-сценарий обычно строится вокруг нескольких уровней защиты:
-
потоковая репликация для быстрого failover;
-
base backup как стартовая точка восстановления;
-
WAL-архив для Point-in-Time Recovery;
-
регулярные restore-тесты;
-
мониторинг replication lag и состояния WAL-архивации.
Важно помнить: репликация не заменяет бэкап.
Репликация помогает при отказе узла. Но если приложение выполнит ошибочный DELETE, реплика быстро и честно повторит эту операцию. Для восстановления после логической ошибки нужен PITR: base backup плюс WAL-архив, позволяющий откатиться к моменту до инцидента.
Упрощенная схема:
[ Clients / API ] │ ▼[ HAProxy / PgBouncer / Router ] │ ▼[ PostgreSQL Primary ] ── WAL streaming ──► [ PostgreSQL Standby ] │ │ ▼ ▼[ WAL archive / Backup storage ] [ Monitoring ] │ ▼[ PITR restore target ]
PgBouncer или балансировщик сам по себе не решает задачу failover. Он только направляет трафик. Выбор нового primary, защита от split-brain и управление переключением должны быть реализованы отдельным механизмом: Patroni, repmgr, Pacemaker/Corosync, managed-сервисом облака или DR-платформой.
Как мониторить риск нарушения RPO в PostgreSQL
Для асинхронной репликации replication lag — один из ключевых индикаторов риска нарушения RPO. Но важно понимать, какой именно тип задержки мы измеряем в конкретный момент.
На мастер-ноде (primary) для этого полезно анализировать системное представление pg_stat_replication:
SELECT application_name, client_addr, state, sync_state, pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) AS send_lag_bytes, pg_wal_lsn_diff(pg_current_wal_lsn(), write_lsn) AS write_lag_bytes, pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn) AS flush_lag_bytes, pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS replay_lag_bytes, write_lag, flush_lag, replay_lagFROM pg_stat_replication;
Эти значения помогают понять, где именно возникло отставание:
-
WAL еще не отправлен на standby;
-
WAL получен, но не записан;
-
WAL записан, но не сброшен на диск;
-
WAL сброшен, но еще не применен.
Для оценки готовности standby к переключению (promotion) особенно важен replay lag: если WAL-сегменты уже получены репликой, но еще не применены, резервный узел не сможет мгновенно взять на себя роль нового primary.
На самой реплике (standby) можно дополнительно оценивать разницу между полученным и примененным объемом WAL:
SELECT pg_wal_lsn_diff( pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn());
Важно: этот запрос показывает только внутреннее отставание реплики между процессами получения (
receive) и применения (replay). Для полноценного контроля отставания от мастера его одного недостаточно.
Пример простого Bash-скрипта для дежурной проверки replay lag со стороны мастера (primary):
#!/usr/bin/env bashDB_USER="postgres"DB_NAME="core_prod"MAX_ALLOWED_REPLAY_LAG_BYTES=16777216 # 16 МБ (1 WAL-сегмент)LAG_BYTES=$(psql -U "$DB_USER" -d "$DB_NAME" -t -A -c "SELECT COALESCE( MAX(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)), 0)FROM pg_stat_replication;")if [[ ! "$LAG_BYTES" =~ ^[0-9]+$ ]]; then echo "CRITICAL: failed to get PostgreSQL replication lag" exit 2fiecho "Current max replay lag: $LAG_BYTES bytes"if [ "$LAG_BYTES" -gt "$MAX_ALLOWED_REPLAY_LAG_BYTES" ]; then echo "WARNING: replication lag exceeds RPO threshold" exit 1fiecho "OK: replication lag is within threshold"exit 0
Конечно, в полноценном production-окружении подобные скрипты лучше заменить нативной интеграцией с Prometheus, Zabbix или другой системой мониторинга. Но сам принцип остается неизменным: RPO должно быть непрерывно наблюдаемой метрикой, а не просто декларативной строкой в документе.
Чем закрывать целевые RTO и RPO
Выбор технологии зависит от критичности системы, бюджета и допустимой потери данных.
-
Резервное копирование (Backup). Самый базовый уровень защиты. Подходит для стандартных и некритичных систем. RPO зависит от частоты копирования, RTO — от размера данных и скорости восстановления. Но backup без регулярного restore-теста не гарантирует восстановление. Это просто файл неизвестного качества.
-
Восстановление на момент времени (PITR). Для баз данных, особенно PostgreSQL, Point-in-Time Recovery часто является обязательным элементом. Он помогает восстановиться не только после падения сервера, но и после логической ошибки: неудачной миграции, ошибочного удаления данных, повреждения таблиц.
-
Репликация. Подходит для критичных систем, где нужно быстро переключиться на резервный узел. Синхронная репликация может приблизить RPO к нулю для подтвержденных транзакций, но не отменяет риски логических ошибок, неправильного failover, split-brain и каскадной порчи данных. Асинхронная репликация быстрее и проще, но допускает lag. Поэтому ее нужно мониторить и явно связывать с допустимым RPO.
-
Облачное аварийное восстановление (DRaaS). Когда систем много, зависимости сложные, а бизнес требует предсказуемого восстановления, ручные скрипты становятся рискованными. В таких случаях применяют DRaaS-подход: резервный контур, репликация машин или данных, заранее описанный порядок запуска и автоматизированный failover.
Например, в Хайстекс Акура используется подход с блочной репликацией машин. Вместо того чтобы адаптировать каждое приложение отдельно, в резервный контур непрерывно реплицируются диски, а сценарий восстановления описывается заранее: какие машины поднять, в каком порядке, с какими сетевыми настройками и проверками.
Такой подход особенно полезен там, где нужно восстанавливать не одну базу, а связанный набор сервисов.
Как проверить, что RTO/RPO достижимы
Единственный надежный способ — регулярные DR-тесты. Необязательно сразу отключать боевую площадку (production). Тестировать восстановление можно в изолированном контуре: поднять standby, восстановить базу из бэкапа и WAL-архива, проверить порядок запуска сервисов и замерить время переключения.
Я подготовил два базовых инструмента: пошаговый чек-лист для проведения самих учений и перечень критических параметров инфраструктуры, которые необходимо непрерывно контролировать в процессе восстановления.
Минимальный чек-лист для проведения DR-учений
Что обязательно мониторить
Правильно настроенный Disaster Recovery нужен не для красивого SLA, а для того, чтобы перевести ликвидацию аварии из режима хаоса в управляемый процесс. Не стоит пытаться защищать все системы одинаково. Нужно честно определить, какие сервисы критичны для бизнеса, просчитать стоимость их простоя, установить для них реалистичные RTO/RPO и проверить эти цифры на практике.
Бэкапы нужно не только создавать, но и восстанавливать. Репликацию — не только включать, но и мониторить. DR-планы — не только писать, но и регулярно прогонять в тестовом контуре.
И главное: если восстановление ни разу не проверялось, оно еще не существует.
ссылка на оригинал статьи https://habr.com/ru/articles/1054008/