На прошлой неделе у клиента production-база упала в 3:15 AM. Дежурный проснулся, но Wi-Fi глючил. Через 20 минут после логина скрипт восстановления не сработал из-за ошибки в конфигурации. Downtime составил 45 минут — час простоя обошелся компании в среднем $10,000, так что потеряли $7,500 только на этом инциденте. Автоматический failover мог бы сократить это до 30 секунд — в 30-60 раз быстрее ручного переключения. Но только если он настроен правильно. Мы сталкивались с кейсами, когда автоматика делала только хуже: split-brain, расхождение данных, ручное восстановление на 4 часа. Поэтому к настройке failover нужно подходить с пониманием подводных камней.
Мы разрабатываем и внедряем автоматический failover — систему, которая обнаруживает отказ основного сайта и переключает трафик на резервный без участия человека. Задача нетривиальная: нужна защита от split-brain, ложных срабатываний, корректный порядок остановки и запуска сервисов. Ошибка здесь опаснее ручного переключения.
Как работает защита от split-brain?
Split-brain возникает, когда оба сайта считают себя активными и одновременно принимают записи. Результат — расхождение данных, которое потом сложно reconcile. Классический случай: сеть между регионами оборвалась на 30 секунд. DR-сайт promote-нул реплику, а primary остался жив и продолжал принимать транзакции. После восстановления получили двух мастеров с разными данными.
Защита — кворум через внешний арбитр. Для PostgreSQL используем Patroni с etcd, Consul или ZooKeeper. Для кластеров — witness node или STONITH (Shoot The Other Node In The Head) — гарантированное выключение ноды перед promote.
# patroni.yml — конфигурация автоматического failover
scope: pg-production
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
# Максимальный лаг реплики, при котором она может стать мастером
maximum_lag_on_failover: 1048576 # 1 MB
# Синхронный режим: хотя бы одна реплика должна подтвердить запись
synchronous_mode: true
synchronous_mode_strict: false # false = не блокировать запись если нет реплик
postgresql:
use_pg_rewind: true # позволяет вернуть старый мастер как реплику
# Скрипт вызывается при смене роли
post_failover:
- name: notify_ops
command: /usr/local/bin/notify-failover.sh
Почему DNS failover не всегда спасает?
DNS failover через Route53 Health Check или Cloudflare Load Balancing — популярное решение, но с серьёзным недостатком: TTL кэширование. Даже при TTL=60 клиенты могут держать старый IP несколько минут. Для критичных приложений используем Anycast (Cloudflare Argo, AWS Global Accelerator) — переключение на сетевом уровне, минуя DNS-кэш. Anycast даёт время переключения менее 10 секунд против 60-300 секунд у DNS.
# terraform/route53-failover.tf
resource "aws_route53_health_check" "primary" {
fqdn = "app-primary.company.internal"
port = 443
type = "HTTPS"
resource_path = "/health"
failure_threshold = 3
request_interval = 10
tags = {
Name = "primary-health-check"
}
}
resource "aws_route53_record" "app_primary" {
zone_id = aws_route53_zone.main.zone_id
name = "app.company.com"
type = "A"
failover_routing_policy {
type = "PRIMARY"
}
health_check_id = aws_route53_health_check.primary.id
set_identifier = "primary"
ttl = 60
records = [var.primary_ip]
}
resource "aws_route53_record" "app_dr" {
zone_id = aws_route53_zone.main.zone_id
name = "app.company.com"
type = "A"
failover_routing_policy {
type = "SECONDARY"
}
set_identifier = "dr"
ttl = 60
records = [var.dr_ip]
}
Как автоматизировать failover с помощью AWS Lambda?
Для сложных сценариев оркестрируем failover через Lambda, вызываемую EventBridge по CloudWatch алерту. Скрипт promote-ит Read Replica, обновляет конфиг в SSM, перезапускает ECS сервисы и переключает Route53. Время выполнения — около 2 минут. Подробнее в документации AWS Lambda.
# lambda/failover-orchestrator.py
import boto3
import json
def lambda_handler(event, context):
""" Вызывается EventBridge при алерте CloudWatch: DatabaseDown severity=critical duration=5m """
rds = boto3.client('rds', region_name='eu-central-1')
r53 = boto3.client('route53')
# Шаг 1: Promote RDS Read Replica в DR-регионе
response = rds.promote_read_replica(
DBInstanceIdentifier='prod-dr-replica',
BackupRetentionPeriod=7,
PreferredBackupWindow='03:00-04:00'
)
# Ждём, пока реплика станет standalone
waiter = rds.get_waiter('db_instance_available')
waiter.wait(DBInstanceIdentifier='prod-dr-replica')
# Шаг 2: Обновить application config через SSM Parameter Store
ssm = boto3.client('ssm', region_name='eu-west-1')
dr_endpoint = rds.describe_db_instances(
DBInstanceIdentifier='prod-dr-replica'
)['DBInstances'][0]['Endpoint']['Address']
ssm.put_parameter(
Name='/app/database/host',
Value=dr_endpoint,
Type='String',
Overwrite=True
)
# Шаг 3: Перезапустить ECS сервисы в DR-регионе с новым конфигом
ecs = boto3.client('ecs', region_name='eu-west-1')
ecs.update_service(
cluster='prod-dr',
service='app',
forceNewDeployment=True
)
# Шаг 4: Переключить Route53
# (вызов update_health_check или change_resource_record_sets)
return {'status': 'failover_initiated', 'dr_db': dr_endpoint}
Как протестировать failover без риска?
Периодически проверяем, что автоматика работает. Процесс тестирования состоит из шагов:
- Отключаем health check endpoint для primary-ресурса.
- Убеждаемся, что трафик переключился на DR-сайт (проверяем логи и метрики).
- Включаем health check обратно.
- Возвращаем primary в строй и выполняем switchback через
patronictl switchover.
Для Patroni используем patronictl failover --master current-master --candidate replica-dr --force. После каждого тестового failover обязательно проверяем возврат в primary mode. Рекомендуем проводить тесты не реже раза в квартал, а для критичных систем — ежемесячно. Экономия от внедрения failover может превышать $100,000 в год за счёт предотвращения простоев.
Сравнение методов failover
| Метод | Время переключения | Сложность | Риск split-brain |
|---|---|---|---|
| DNS failover (TTL=60) | 60-300 сек | Низкая | Нет |
| Anycast (Global Accelerator) | <10 сек | Средняя | Нет |
| BGP anycast | <1 сек | Высокая | Да (требует настройки) |
| Patroni + etcd | <30 сек | Средняя | Нет (кворум) |
Что входит в нашу работу
- Аудит текущей инфраструктуры и выявление single points of failure
- Проектирование архитектуры failover (DNS/Anycast, БД, приложения)
- Настройка Patroni, Route53, Lambda, Ansible
- Разработка runbook и процедуры отката
- Тестирование сценариев: отказ primary, отказ реплики, отказ сети
- Документация и передача знаний вашей команде
Ориентировочные сроки
| Сложность | Компоненты | Срок |
|---|---|---|
| Базовый | DNS failover (Route53/Cloudflare) + 1 БД | 3–5 дней |
| Средний | Patroni + DNS + app layer, 2–3 сервиса | 1–2 недели |
| Сложный | Полная оркестрация (Lambda/Ansible), 10+ сервисов, тестирование | 4–8 недель |
Стоимость проекта обсуждается после аудита. Получите консультацию по настройке failover — свяжитесь с нами для оценки вашего проекта. Опыт наших инженеров — более 10 лет в продакшен-инфраструктуре. Закажите аудит вашей инфраструктуры уже сегодня.







