Skip to content

Failover: автоматическое переключение сайта на резервный сервер #44

Description

@dhammagift

Зачем

25 сен 2026 сайт и приложения словаря ушли в чёрный экран: у dict.dhamma.gift сертификат перевыпустили без SAN на этот поддомен, а приложение (Capacitor/TWA) грузит фиксированный https://dict.dhamma.gift/ и при SSL-ошибке просто отменяет загрузку. Инцидент показал: отказ основного сервера сейчас лечится только руками, и узнаём мы о нём от пользователей.

Проверено в тот же день: dhamma.gift, dict.dhamma.gift, find.dhamma.gift → 163.5.29.37; old./test.dhamma.gift → локально на резервной машине (94.126.201.8); NS зоны — Cloudflare (ursula/decker.ns.cloudflare.com), www уже за Cloudflare. API-токена Cloudflare на резервной машине нет.

Что нужно

Автоматический failover основного origin на резервный + автоматический failback + уведомление (почта/Telegram), без ручного вмешательства.

Варианты

1. Cloudflare Load Balancing (managed, платно)

  • от $5/мес (plans, application services), нужен billing profile, включается в дашборде — Enable Load Balancing.
  • Даёт пулы/мониторы, авто-failover и авто-failback, алерт Load Balancing Health Alert (unhealthy/healthy по пулу и по origin'у, e-mail/вебхук) — входит в покупку, см. Manage load balancers.
  • Режимы (proxy modes): L7 (оранжевое облако) — failover за секунды, не зависит от DNS-кэша клиентов, прячет IP origin'ов, работает с кэшем/WAF, есть session affinity и failover_across_pools. DNS-only (серое) — проще, но медленно и зависит от TTL/кэша резолверов.
  • Побочные следствия: apex dhamma.gift переезжает за Cloudflare (сейчас он в DNS напрямую на VPS); для связи CF→origin нужен Cloudflare Origin CA (бесплатный, до 15 лет) на обоих origin'ах — заодно снимает класс аварии «кривой сертификат origin» полностью.
  • Из FAQ: endpoint'ы задавать IP, а не FQDN; CF кэширует выбранный IP до 5 с; число регионов мониторинга прямо влияет на объём health-запросов к origin'у.

2. Cron-скрипт на резервной машине (бесплатно)

Раз в минуту проверяет основной origin, после N фейлов подряд через Cloudflare API (Zone:DNS:Edit) меняет A-запись на резервный IP, шлёт уведомление в Telegram; после M успешных проверок возвращает назад.

  • Плюсы: $0, никаких изменений в схеме, работает и для серого DNS.
  • Минусы: сам себя не проверит — если умрёт резервная машина или у неё отвалится сеть, watchdog'а нет. Хуже: при сетевом разрыве между машинами он может решить, что основной мёртв, и переключить DNS на себя при живом основном (split-brain). Лечится только третьим независимым наблюдателем.
  • TTL 60 с + Android/WebView кэшируют DNS, поэтому в приложениях переключение всё равно с задержкой; сертификаты придётся держать живыми на обеих машинах.

3. Cloudflare Worker по cron-триггеру (бесплатно, третий наблюдатель)

Тот же алгоритм, но живёт внутри Cloudflare: раз в 1–5 мин проверяет origin'ы, состояние держит в KV, дёргает DNS через API, шлёт алерт. Бесплатные лимиты Worker/KV это покрывают.

  • Плюсы: не зависит ни от одной нашей машины (снимает проблему «watchdog сам себя не проверит»), $0.
  • Минусы: нужен API-токен; всё равно DNS-переключение (медленный путь) — если хочется быстро, нужен Worker, который проксирует каждый запрос с ретраем на резерв (тогда hostname заводится проксированным, и это уже почти L7 LB, но своими руками и на free-лимитах 100k запросов/сутки).

4. Клиентский failover (обсуждение)

  • Первый визит в обычном браузере — невозможен: пока origin не ответил, никакого нашего кода у клиента нет. Единственный слой, который можно спасти для «никогда не ходивших», — DNS/edge (Cloudflare).
  • Повторный визит: service worker может отдать кэш (у словаря PWA уже есть офлайн-оболочка — возвращающиеся пользователи переживают падение) или сходить на резервный origin с ретраем. Ограничения: SW работает только в своём scope, кросс-доменный ответ требует CORS, относительные пути/абсолютные /static/..., куки и POST ломаются, origin документа остаётся прежним.
  • Наши приложения (Capacitor-оболочки) — здесь клиентский failover реально работает и для первого запуска: нативный код держит список базовых URL, при onReceivedError/onReceivedHttpError/SSL-ошибке грузит следующий. Это дешёвое дополнение к edge-решению, но website-пользователей не спасает.
  • Две A-записи на один хост (бесплатно): клиент сам пробует второй IP, если первый не отвечает. Помогает только при «жёстком» падении (connection refused), без health-check, и половина трафика уходит на резерв всегда — это уже балансировка, а не failover.

Блокеры, которые надо закрыть до включения любого варианта

  1. Резервный origin должен реально отдавать те же хосты: сейчас на 94.126.201.8 нет vhost'а для apex dhamma.gift (есть old., test., d., node.), /var/www/html/dict пустой, словарь локально живёт в /var/www/ddg-ui/public. Иначе failover приведёт на пустую/устаревшую копию.
  2. Синхронизация контента основной → резерв (rsync/git) и её расписание.
  3. /healthz на обоих origin'ах (нужен и монитору Cloudflare).
  4. Скоуп: словарь + статика переезжают легко; поиск dg-node требует БД (на резерве есть /var/www/dg-node-test и /var/www/offline-data — надо проверить полноту копии).
  5. Доступ: API-токен Cloudflare (Zone:DNS:Edit, для Worker'а ещё Workers) — либо включение и оплата руками в дашборде.

Предложение

Начать с Worker-наблюдателя (вариант 3) + резервный origin, подготовленный по п.1–3: это бесплатно, не имеет единственной точки отказа «watchdog на резервной машине», и даёт автоматический failback и уведомления. Если захочется секундного переключения и снятия вопроса с сертификатами — добавить Cloudflare LB за $5/мес поверх той же пары origin'ов.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions