Отказоустойчивость и аварийное восстановление Global ERP

Отказоустойчивость и аварийное восстановление Global ERP#

Важно

Документ не заменяет детальные пошаговые инструкции уровня runbook для конкретных инцидентов. Такие инструкции должны вестись отдельно и поддерживаться в актуальном состоянии администраторами подсистем. Настоящее руководство описывает общий подход к обеспечению высокой доступности (HA) и аварийному восстановлению (DR) системы Global ERP, задаёт рамочную модель, архитектурные требования и единый порядок принятия решений.

Термины и принципы#

Высокая доступность (HA, High Availability) - это способность системы продолжать работу при отказе отдельных компонентов без полной остановки сервиса. Обычно речь идёт об отказе ноды, диска, процесса, сетевого сегмента или экземпляра приложения. Цель HA - минимизировать простой сервиса и не допустить эскалации локального сбоя в полноценную аварию.

Аварийное восстановление (DR, Disaster Recovery) - это способность восстановить работоспособность системы после серьёзной аварии, включая полный отказ кластера, потерю хранилища, разрушение базы данных или недоступность целого ЦОДа. Цель DR - восстановить сервис в предсказуемые сроки и с контролируемой потерей данных.

Для оценки готовности системы используются два ключевых показателя.

RTO (Recovery Time Objective) - максимально допустимое время восстановления после аварии.

RPO (Recovery Point Objective) - максимально допустимый объём потери данных, выраженный во времени между последним согласованным состоянием и моментом отказа.

При проектировании Global ERP необходимо исходить из следующих базовых принципов:

  1. Отказоустойчивость не должна строиться только на резервных копиях; резервные копии являются последней линией восстановления, а не заменой репликации и резервирования;

  2. Площадки должны быть действительно независимыми: две подсети в одном ЦОД с общей инженерной инфраструктурой нельзя считать двумя зонами доступности;

  3. Используйте зоны доступности (Availability Zones) для обеспечения непрерывной работы. Зона доступности — это центр обработки данных с отдельным источником питания, системой резервного копирования и подключением к Интернету. Две подсети в одном ЦОД с общим источником питания нельзя считать двумя зонами доступности. Примером двух AZ могут служить два отдельных центра обработки данных в относительной близости друг к другу, которые имеют сетевое соединение с низкой сетевой задержкой и высокой пропускной способностью.

  4. ЦОДов должны быть не менее двух, один из которых будет в другом регионе. Каждый дополнительный ЦОД - это усложнение и удорожание конструкции, однако при необходимости такая возможность существует.

  5. Ключевые инфраструктурные компоненты - PostgreSQL, Kubernetes, NFS, балансировка, репозиторий артефактов и CI/CD - должны оцениваться как части единой цепочки восстановления;

  6. Каждое проектное решение по HA/DR должно сопровождаться тестируемым сценарием переключения или восстановления;

  7. Любая схема резервирования должна учитывать не только запуск инфраструктуры, но и возможность вернуть бизнес-функции, включая интеграции, фоновые задания, доступность файлов и согласованность данных.

Классификация аварийных ситуаций#

Рекомендуется ввести единую шкалу аварийных состояний:

Зелёная тревога - простой отказ, не приводящий к недоступности сервиса или вызывающий перебой не более 10 минут. Возможна частичная потеря функциональности. Обрабатывается автоматически.

Жёлтая тревога - отказ средней значимости. Перерыв в предоставлении сервиса до 4 часов. Требует ручного вмешательства администраторов.

Красная тревога - катастрофический отказ. Перерыв свыше 4 часов. Требует информирования и согласования с дирекцией по ИТ. При таких инцидентах остаётся риск превышения проектных значений RTO.

Роли и зоны ответственности#

Рекомендуемая модель ответственности:

Администратор Global ERP отвечает за эксплуатационную целостность платформы, контроль репликации прикладных экземпляров, координацию работ по DRP и общее ведение сценариев восстановления.

Системный администратор отвечает за работоспособность инфраструктурной основы: виртуализации, серверов, Kubernetes, NFS, резервного копирования, репликации и состояния репозиториев артефактов.

Администратор СУБД отвечает за PostgreSQL, репликацию, резервные копии базы, процедуры промоутинга реплик и восстановления данных.

Инженер DevOps отвечает за CI/CD, воспроизводимость развёртывания, доступность образов и поддержку эксплуатационных сценариев, связанных с Kubernetes и автоматизацией.

Сетевой администратор отвечает за маршрутизацию, DNS, сетевую связность между площадками и переключение пользовательского трафика.

Функциональные эксперты проверяют работоспособность бизнес-функций и интеграций после восстановления.

Архитектура#

Архитектура HA/DR для Global ERP должна опираться не на один механизм, а на комбинацию решений: резервирование узлов, репликацию данных, регулярные резервные копии, территориальное разнесение, автоматический мониторинг, а также повторяемые процедуры развертывания из репозитория артефактов. Именно сочетание этих механизмов и формирует реальную устойчивость системы.

Базовый вариант#

  • Kubernetes: 1 control-plane + N worker.

  • PostgreSQL: одиночный инстанс (без реплик).

  • Бекапы: экспорт манифестов K8s (namespaces + cluster-scoped), логические дампы PostgreSQL (актуально при размере БД <= 1.5 ТБ).

Базовый вариант подходит для систем, где требуется технологическая отказоустойчивость внутри одной площадки, но ещё не требуется полноценный межплощадочный DR-контур. В этом случае Kubernetes разворачивается как один control-plane и несколько worker-узлов, PostgreSQL работает как одиночный инстанс или в упрощённой схеме без удалённой реплики, а защита данных строится преимущественно на резервных копиях: логических или бинарных дампах БД, экспортируемых манифестах Kubernetes и копиях конфигурации приложения.

Такой вариант в большей степени допустим для пилотных сред, TEST/DEV-контуров. Для полноценного PROD его недостаточно, поскольку отказ СУБД, NFS или площадки приведёт к длительному восстановлению из бэкапов.

Архитектура варианта

Вариант DR Active–Passive#

  • Модель: один ЦОД активен, второй «на паузе» с заранее выделенными ~50% ресурсов. При наступлении катастрофы необходимо время на развертывание ЦОДа на полную мощность.

  • Реестр образов: обязательные бекапы/репликации.

  • СУБД: асинхронная реплика на резерв(ы). Допускается задержка (минуты/часы). Реплик может быть несколько.

  • Переключение: автоматическое через HAProxy, полуавтоматическое (кнопка/скрипт), или ручное через DNS (пониженный TTL).

В модели Active–Passive основная площадка обслуживает нагрузку, а вторая площадка остаётся резервной. На резервной стороне поддерживаются реплики критичных данных и, при необходимости, заготовленная инфраструктура с неполной загрузкой ресурсов. При катастрофе основного ЦОДа резервная площадка активируется, после чего нагрузка перенаправляется на неё.

Этот вариант относительно прост в эксплуатации и обычно даёт лучший баланс между стоимостью и устойчивостью. Он хорошо подходит для систем, где допустимо ручное или полуавтоматическое переключение, а небольшой RPO, связанный с асинхронной репликацией, считается приемлемым.

Архитектура варианта

Вариант DR Active–Active#

  • Два кластера Kubernetes. Внутри каждого кластера используется gsroute - JGroups Gossip Router - который обеспечивает маршрутизацию кластерных групп.

    • Публикация на IP: сервис gsroute должен быть опубликован на выделенный IP; допускается публикация на том же узле и IP, где сам роутер, при соблюдении сетевых правил (firewall, ACL).

  • «Резиновый» кластер. Имеем несколько control-host и worker-нод, разнесённых по разным ЦОДам. Кластер подстраивается под текущую нагрузку: при падении части площадки горизонтально растёт за счёт других узлов.

  • Балансировка: трафик между ЦОДами распределяется HAProxy.

    • Если один ЦОД падает, пользователи, чьи сессии были закреплены за ним, получают разрыв соединения, после чего им необходимо заново авторизоваться в системе.

    • Пользователи, чьи сессии обслуживает живой ЦОД, ничего не делают и продолжают работу.

    • Нагрузка на оставшийся ЦОД возрастает, поэтому необходим резерв ресурсов.

Модель Active–Active используется в тех случаях, когда нагрузка заранее распределяется между двумя площадками, а каждая площадка способна принять на себя дополнительную долю трафика в случае отказа другой. Преимущество подхода состоит в том, что отказ одной площадки не требует полноценного холодного старта резервного ЦОДа: трафик просто перераспределяется.

Архитектура варианта

Гибридный вариант (два основных + третий резервный)#

  • В обоих основных (активная эксплуатация) ЦОДах проходят реплики.

  • В третьем резервном ЦОДе - хранятся бэкапы/реплики:

    • логический дамп,

    • бинарный дамп,

    • Конфигурационные файлы (K8S, приложения, LB, секреты в зашифрованном виде).

  • Регламент: резервный ЦОД должен быть поднят за несколько часов (RTO).

Гибридная модель сочетает активную работу двух основных площадок или основной и резервной площадки с третьей выделенной площадкой хранения резервных копий и реплик. Третий ЦОД не обязательно обслуживает пользователей в штатном режиме, но должен быть способен принять восстановление в заранее определённое время.

Архитектура варианта

Требования к ключевым компонентам#

Kubernetes#

  • Kubernetes является базой вычислительного слоя Global ERP, поэтому отказоустойчивость платформы напрямую зависит от его конфигурации. Для HA-сценариев рекомендуется использовать не менее трёх control-plane узлов с кворумом etcd. Узлы control-plane следует разносить по разным стойкам, сегментам и, если это допускается сетевой задержкой, по разным площадкам. Worker-узлы должны иметь резерв по ресурсам, чтобы выдерживать потерю одной или нескольких нод без остановки бизнес-критичных подов.

  • Серверы etcd. Необходим в том случае, если вы используете для своих кластеров Kubernetes отдельные кластеры etcd. Приоритет в этих серверах должен отдаваться скорости чтения/записи, поэтому необходимо использовать твердотельные накопители.

  • Дополнительно необходимо обеспечить экспорт и резервное хранение cluster-scoped и namespace-scoped манифестов, секретов в зашифрованном виде, Helm-values и иных параметров, без которых восстановление кластера будет возможно только частично.

Load Balancer#

Балансировщик нагрузки должен обеспечивать не только распределение трафика, но и участвовать в сценариях отказоустойчивости. Для этого нужны активные health-checks, корректные тайм-ауты, механизм временного вывода узлов из пула при релизе или аварии и согласованная стратегия маршрутизации сессий.

  • Горячее обновление по модулям: LB отключает отдельные модули, блокирует их на время релиза, затем возвращает в пул.

  • Стратегии балансировки:

    • roundrobin (по очереди),

    • leastconn (наименьшее число активных сессий - приоритет отдачи сессий: «где меньше, туда новые»),

    • source/ip-hash (по IP).

  • Health-checks: активные проверки с тайм-аутами и интервалами.

  • Интеграция с CI/CD: скрипты для проверки статуса перед/после релиза.

Сеть (CNI + внешняя надёжность)#

  • Сетевая политика похожа на правила брандмауэра или группы безопасности, которые позволяют определить допустимый входящий и исходящий трафик. В состав основных сетевых API-интерфейсов Kubernetes входит NetworkPolicy API.

  • Внешняя надёжность сети: пограничный роутер с firewall, чёткие ACL.

Хранилище и управление дампами#

  • Эфемерные хранилища - это непостоянные тома, живущие в рамках жизненного цикла пода. Они исчезают при пересоздании пода и не подходят для хранения постоянных данных. Состояние не хранится на таких томах. Любая инфраструктура разворачивается по системным требованиям заново, компоненты идемпотентно доставляются и конфигурируются.

  • Дампы памяти JVM: предусмотрена возможность снимать heap дампы с приложений:

    • В под добавляется дополнительный «транспортный» контейнер для безопасной передачи дампов.

    • Размер ноды: не рекомендуем >32 ГБ RAM на ноду, для того чтобы дампы были переносимыми по сети/дискам.

    • Хранилище для дампов: резервируем отдельное место (quota). Также необходимо настроить политики ротации.

Файловое хранилище (NFS) должно рассматриваться как самостоятельный отказоустойчивый компонент, а не как вспомогательный сервис. Потеря доступа к NFS может приводить к полной остановке приложения, если на нём размещены конфигурации, пользовательские файлы, временные каталоги или логически значимые данные.

Для PROD необходимо предусматривать резервный NFS-сервер либо иной эквивалентный механизм хранения с возможностью переключения. Между основной и резервной сторонами должна поддерживаться синхронизация, а сама процедура смены активного файлового узла должна быть описана в runbook и регулярно проверяться в тестовом контуре.

Мониторинг - метрики#

  • Kubernetes/узлы: CPU/Memory/Load/IOPS, диск/inode, network tx/rx, taints, частота рестартов.

  • Поды/приложения: ошибки 5xx/4xx, очереди, размер пулов соединений, количество открытых файлов, JVM memory.

  • LB HAProxy: статус бэкендов, активные/ожидающие сессии, ошибки health-check.

  • PostgreSQL: логи, количество подключений.

  • Бэкапы: наличие свежих архивов, размер, checksum, длительность, статусы.

  • Сеть: packet loss между ЦОДами, ошибки интерфейсов, пропускная способность каналов.

  • Хранилище/CSI: состояние пулов.

PostgreSQL - репликации и кластерные решения#

СУБД является наиболее критичным компонентом с точки зрения целостности данных, поэтому для PROD-среды необходимо использовать primary–standby схему с репликацией. Для межплощадочного DR-контурa предпочтительна асинхронная репликация: она снижает влияние сетевой задержки на транзакции, но требует осознанного принятия небольшого RPO. Синхронная репликация допустима только в пределах стабильной и низколатентной сети.

Для оркестрации отказа используются open-source решения (Pacemaker, Patroni) или коммерческие (Postgres Pro Cluster, BIHA, Tantor XData) - последние оправданы, если необходима вендорская поддержка.

Логические и бинарные дампы эффективны при размере базы до 1.5 ТБ; для баз большего объёма применяется только потоковая репликация и физические бекапы (pg_probackup с WAL-архивированием).

Для снижения нагрузки при восстановлении реплик применяется цикличная схема ротации: три (или пять) реплики включаются поочерёдно, каждая работает один день, затем выключается и уступает место следующей. Когда реплика включается повторно на четвёртый день, ей нужно синхронизировать лишь три дня изменений, а не всю базу целиком.

Репозиторий артефактов и CI/CD#

Недоступность CI/CD или Nexus-подобного репозитория не всегда означает немедленную аварию сервиса, но существенно осложняет восстановление и выпуск исправлений. Поэтому эти системы должны резервироваться, регулярно обновлять резервные копии и контролироваться с точки зрения доступности.

Минимальное требование - наличие резервной копии репозитория образов, исходного кода, пайплайнов и конфигураций развертывания. Для зрелого DR-контура желательно обеспечить удалённую реплику и на стороне CI/CD.

Стратегии деплоя#

Выбор стратегии обновления приложения - это баланс между скоростью вывода изменений, надёжностью и стоимостью инфраструктуры. Конкретный выбор зависит от допустимого простоя, критичности сервиса, бюджета и зрелости процессов отката.

Recreate полностью останавливает старую версию перед запуском новой. Это самый простой и дешёвый вариант, но он гарантирует простой в момент деплоя. Оправдан на ранних этапах проекта и во внутренних системах с плановыми окнами обслуживания.

Rolling Update обновляет инстансы по одному: каждый выводится из-под нагрузки, обновляется, проверяется и возвращается в работу. Простоя нет - в пуле всегда остаются работающие инстансы. Некоторое время параллельно работают две версии приложения, что усложняет анализ поведения. Хорошо ложится на Kubernetes и подходит для большинства сервисов с требованием высокой доступности.

Blue/Green держит два полноценных окружения: «синее» (текущий прод) и «зелёное» (новая версия). После тестирования «зелёного» трафик переключается мгновенно; откат - переключить обратно. Простоя нет, откат молниеносный, но требует двойных ресурсов. Оправдан для критичных сервисов с жёстким SLA при наличии соответствующего бюджета.

Canary выкатывает новую версию постепенно: сначала на 2% пользователей, затем на 10%, 25%, 75% и наконец 100%. Риск инцидента ограничен малой группой; при проблемах выполняется откат. Требует развитой системы метрик и грамотной маршрутизации трафика. Идеален для крупных пользовательских систем и релизов с труднопредсказуемыми последствиями.

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

Резервное копирование и верификация#

Jump Host и доступ#

Все подключения к продуктивной инфраструктуре осуществляются через Jump Host по SSH с ProxyJump - прямых входов в прод нет. Используются сертификаты. Все сессии логируются: команды и tty-вывод. Доступ разграничен по окружениям и ролям.

Верификация бекапов#

Наличие свежих архивов, их размер и контрольные суммы проверяются автоматически при каждом создании. Периодически выполняется test restore в изолированную песочницу. Мониторинг отслеживает время последней успешной верификации и сигнализирует при её отсутствии.

Автотест в CI#

После любого restore автоматически запускается CI-job: поднимается тестовый стенд, выполняются миграции, прогоняются SQL и HTTP smoke-тесты, собирается отчёт (JUnit/Allure) и публикуется результат. Инструмент - JEXL-скрипт проверок.

Test Restore#

  • Пре‑чек ресурсов: вычислить потребности CPU/RAM/дисков под восстановление; проверить, что конфиг СУБД корректен.

  • Процедура: развернуть дамп / включить реплику как master. Поднять сервисы.

  • Проверки: скрипты для smoke‑тестов.

  • Артефакты: сохранить логи, графики, скорость восстановления.

Откат изменений#

Откат изменений не является аварийным восстановлением в строгом смысле, но напрямую влияет на устойчивость эксплуатации. Если новая версия приложения вызывает критический дефект, откат Helm-релиза должен выполняться как штатная и многократно проверенная операция. При этом важно заранее понимать совместимость схемы БД с предыдущей версией приложения.

Ошибочные изменения базы данных требуют отдельного подхода. Если существует резервная копия до момента изменений, применяется Point-in-Time Recovery. Если изменение обратимо, предпочтителен заранее подготовленный downgrade-скрипт. Откатывать схему БД без проверенного сценария нельзя, поскольку такой откат сам по себе может стать причиной полноценного инцидента.

Конфигурационные ошибки - неверный Secret, ConfigMap или переменная среды - должны устраняться через возврат предыдущей версии из Git или из истории изменений Kubernetes. Важно, чтобы история таких изменений хранилась централизованно и позволяла восстановить точное рабочее состояние.

Сценарии восстановления#

Простые отказы (зелёная тревога)#

Простые отказы в большинстве случаев обрабатываются автоматически: отказоустойчивые механизмы платформы самостоятельно перераспределяют нагрузку, уведомления поступают администраторам по системе мониторинга.

Отказ одного или нескольких worker-узлов Kubernetes. Kubernetes автоматически перераспределяет поды на работающие узлы. Кластер Global ERP продолжает обслуживать запросы. Администратор проверяет статус и анализирует причину сбоя.

Целевое RTO - менее 10 минут.

Отказ мастер-реплики PostgreSQL. Дежурный администратор запускает процедуру смены ролей. Порядок действий:

  • остановить поды Global ERP (или масштабировать Deployment до 0 реплик);

  • выполнить промоутинг реплики;

  • проверить доступность и целостность данных;

  • обновить параметры подключения;

  • запустить поды и проверить логи. При сбое репликации выполняется восстановление из последней полной резервной копии с ручным восстановлением кластера.

Целевое RTO - 45 минут.

Отказы средней значимости (жёлтая тревога)#

Отказ NFS-сервера. При потере доступа к файловому хранилищу кластер Global ERP прекращает отвечать на запросы. Администратор активирует резервный NFS-сервер, убеждается в синхронизации данных и обновляет параметры, после чего перезапускает поды. Целевое RTO - 35 минут.

Полный отказ кластера приложений Global ERP. При наличии синхронизированного резервного кластера администратор выполняет переключение на него. Если такой кластер не готов - выполняется стандартная процедура установки релиза или разворачивания кластера серверов приложений с нуля. Целевое RTO - 4 часа.

Полный отказ кластера PostgreSQL. На одном из узлов восстанавливается последняя полная резервная копия, применяются WAL-журналы для Point-in-Time Recovery до максимально актуальной точки. После проверки данных, индексов и логической целостности обновляются конфигурации подключения приложений и перезапускаются интеграционные сервисы. Целевое RTO - 6 часов.

Полный отказ кластера Kubernetes. Системный администратор совместно с инженером DevOps принимают решение о переустановке. После переустановки кластера выполняется переключение на резервный кластер или стандартная процедура развёртывания. Целевое RTO - 5 часов.

Катастрофические отказы (красная тревога)#

Полный отказ ЦОД. После получения от администратора прогноза длительной недоступности и согласования выполняется активация инфраструктуры в резервном ЦОД. Последовательность:

  • остановить экземпляр Global ERP в основном ЦОД;

  • остановить потоковую репликацию WAL-логов;

  • промоутировать удалённую реплику на сервере резервного ЦОД;

  • обновить DNS-запись A на адрес шлюза в резервном ЦОД;

  • активировать резервный кластер Kubernetes, настроенный на новый мастер БД и локальный NFS;

  • проверить доступность системы по новому адресу; восстановить интеграции.

Целевое RTO - 60 минут для самого переключения.

Аварийное восстановление без Kubernetes. Применяется при полной недоступности инфраструктуры Kubernetes. Порядок:

  • авторизоваться под сервисной учётной запись;

  • восстановить БД из последней полной резервной копии PostgreSQL с применением WAL-журналов;

  • распаковать актуальные версии ПО сервера и пользовательских библиотек;

  • запустить сервер Global ERP;

  • запросить и применить лицензию на экземпляре;

  • выполнить нагон релиза для синхронизации схемы БД с версией приложения.

Тестирование процедур аварийного восстановления#

Наличие DR-документа без регулярного тестирования не даёт реальной гарантии готовности. Поэтому тестирование должно быть обязательной частью эксплуатации. Практически это означает следующее.

  • Не реже одного раза в год следует проводить тест потери worker-узла Kubernetes. Цель - убедиться, что поды действительно перераспределяются, а приложение остаётся доступным в пределах целевого RTO.

  • Не реже одного раза в квартал следует отрабатывать переключение PostgreSQL на реплику.

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

  • Не реже одного раза в год следует проводить полное восстановление тестового экземпляра из резервной копии.

  • Не реже одного раза в год следует проводить учение по переключению в удалённый ЦОД. Такой тест должен включать не только запуск инфраструктуры, но и проверку конечной доступности системы, а также пост-анализ фактических значений RTO и RPO.

По результатам каждого теста необходимо фиксировать:

  • фактическое время восстановления;

  • фактический объём потери данных;

  • узкие места в процедурах;

  • проблемы в документации;

  • необходимые изменения в инфраструктуре, автоматизации или регламентах.

Рекомендации по оформлению runbook и DRP#

Для практической эксплуатации рекомендуется создать набор отдельных runbook-документов. В каждый runbook разумно включать:

  • условие запуска сценария;

  • признаки, по которым сценарий подтверждается;

  • список ответственных ролей;

  • точную последовательность действий;

  • критерии успешного завершения;

  • порядок возврата в штатный режим;

  • ссылки на команды, скрипты и шаблоны конфигурации.

Такой подход позволяет оставить основной документ архитектурным и управленческим, а низкоуровневые команды - вынести в отдельные эксплуатационные инструкции.

Примерный список необходимых runbook-документов:

  1. переключение PostgreSQL на локальную реплику;

  2. переключение PostgreSQL на удалённую реплику в резервном ЦОДе;

  3. восстановление PostgreSQL из резервной копии;

  4. активация резервного NFS и возврат на основной сервер;

  5. переустановка Kubernetes-кластера и восстановление конфигурации;

  6. переключение пользовательского трафика и изменение DNS;

  7. полное переключение в резервный ЦОД;

  8. аварийный запуск Global ERP без Kubernetes.