Иногда инцидент начинается не с 5xx и не с красного графика
Он начинается с одной стойки
И с одного таймаута
09:12 - alert: db-replica-02 connection timeout
HAProxy зелёный
HTTP 5xx = 0.2%
p50 = 38–42ms

2 стойки
В каждом свой ToR
Primary и app в rack-1
Replica-01 в rack-1
Replica-02 в rack-2
Read-routing выполняется на уровне приложения (driver read-replica strategy). PgBouncer не занимается распределением между репликами
Health check HAProxy:
option httpchk GET /health
/health проверяет:
app process alive
connect() к PgBouncer socket
DB round-trip не выполняется:
SELECT 1;
Мониторинг меряет HTTP, latency, replication lag
Отказ начался на уровне стойки
09:12-09:16
Replica-02 (стойка 2) перестаёт отвечать
PostgreSQL:
could not connect to server: Connection timed out timeout after 300ms
Replication lag на replica-02 начинает быстро расти по мере накопления WAL на primary
Service discovery помечает replica-02 как unhealthy
Primary и replica-01 остаются доступными, write-path не нарушен
Приоритет инцидента не повышается
Потому что HAProxy health check проверяет только /health без DB round-trip → пул остаётся зеленым → инцидент не объявляется
HTTP 200 продолжают возвращаться
Retry-конфиг
connect_timeout = 300ms statement_timeout = 800ms retry_attempts = 3 retry_backoff = 200ms failover = next_replica
Значимая доля read-запросов (около 50% при round-robin) шла на replica-02
Сценарий для такого запроса:
connect → 300ms timeout
backoff 200ms
retry → переключение на replica-01
SELECT выполняется
клиент получает 200
Потому что retry происходит внутри app до формирования HTTP-ответа → финальный статус 200 → 5xx остаётся baseline
Мониторинг считает финальный HTTP статус
Первичная ошибка не отражается отдельной метрикой
09:14 - сеть
OOB (IPMI) replica-02 недоступен
В этом DC management VLAN IPMI также сходится в ToR-2 (общий ToR для data и mgmt в rack-2)
Data-интерфейс:
ToR port Gi1/0/24: up FDB: MAC present ARP: incomplete ICMP: no reply
IPMI и data-plane теряют связность одновременно
Потому что телеметрия на уровне стойки отсутствует и OOB не влияет на приоритет инцидента → одновременная недоступность management и data-plane трактуется как хостовая проблема → эскалация откладывается
09:20 - метрики
p50 ≈ 40ms
p95 ≈ 130ms
p99 = 620-900ms
Почему p99 ≈ 600-900ms при timeout 300ms?
Запросы, попавшие на replica-02:
300ms connect timeout
200ms backoff
~40-60ms успешный SELECT = ~550-600ms
Хвост до 800–900 ms формировался запросами, которые проходили через connect timeout (300 ms) и backoff (200 ms), а затем задерживались при получении соединения из пула. Повторные попытки увеличили время удержания соединений и привели к временному насыщению пула
Потому что reads распределяются между репликами → часть трафика регулярно упирается в timeout → retry увеличивает хвост → p99 растёт
SLA = 1.5s
Формально не нарушен
09:24 - пауза
Primary жив
Replica-01 жива
Replica-02 недоступна
Потеряна межстоечная отказоустойчивость
Приоритет инцидента оценивает текущее влияние, а не потерю отказоустойчивости → пауза становится системной
Система продолжала жить, но отказоустойчивость стала "локальной" внутри rack-1
Отказ rack-1 превратил бы ситуацию в полноценный отказ сервиса
09:30 - коммутатор
На ToR-2:
LINK-3-UPDOWN: Interface Gi1/0/18, changed state to down LINK-3-UPDOWN: Interface Gi1/0/18, changed state to up
Flapping
Uplink:
LACP renegotiation detected
Ошибки интерфейса:
show interfaces counters errors CRC: 1487 (growing during instability)
CRC росли в период нестабильности аплинка
Вторая нода в rack-2 начинает терять пакеты
ToR ведёт себя нестабильно, аплинк флапает, хосты rack-2 периодически теряют связность
09:33 - повышение приоритета инцидента
Причины:
replica-02 недоступна
flapping в rack-2
потеря межстоечного резервирования
Инцидент переведён в категорию высокого приоритета
Отправлен on-site инженер
09:41 - ToR reboot-loop
Логи NOS:
kernel panic: process netstack crashed watchdog timeout system restarting...
После перезапуска:
port-channel1: down re-negotiating LACP
Причина — reboot-loop ToR: crash → перезапуск → повторная инициализация аплинка и таблиц коммутации
В этот момент хосты временно теряют L2-связность
Это объясняет:
отсутствие связности replica-02
недоступность IPMI (mgmt через тот же ToR)
packet loss у других хостов rack-2
App-ноды в rack-1 не затронуты
Retry продолжает маскировать деградацию
09:48
ToR стабилизирован
Replica-02 вернулась в сеть. По необходимости (процессы зависли) хост был перезапущен
pg_stat_replication: state = streaming write_lag = decreasing replay_lag = decreasing
Replication догоняет WAL
09:55
p95 = 45ms
p99 < 120ms
5xx остаётся baseline
Формально простоя не было
Факты периода 09:12–09:48:
rack-2 частично изолирован
доля повторных попыток выросла в 4–5 раз
p99 вырос почти в 10 раз
межстоечная отказоустойчивость отсутствовала
write-path оставался доступным
Изменения после инцидента:
/healthдополнен DB round-tripSELECT 1добавлена метрика
retry_attempts_totalмониторинг питания стойки и состояния ToR интегрирован в систему приоритизации
объединён сигнал одновременной недоступности OOB и data-plane
правило: потеря реплики в другой стойке повышает приоритет независимо от HTTP 5xx
Что должно триггерить повышение приоритета? Текущая ситуация или потеря отказоустойчивости?
Кто принимает решение об эскалации, когда графики зелёные?
Короткое резюме
Инцидент начался как потеря межстоечной отказоустойчивости. Он стал инцидентом только тогда, когда деградация стала измеримой. Разрыв между этими моментами и есть реальный риск
Об авторе
Работаю с физической и гибридной инфраструктурой на стыке стойки, сети и продакшн-нагрузки. Часто инциденты начинаются не там, где их видит дашборд
