Иногда инцидент начинается не с 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
Что должно триггерить повышение приоритета? Текущая ситуация или потеря отказоустой��ивости?
Кто принимает решение об эскалации, когда графики зелёные?
Короткое резюме
Инцидент начался как потеря межстоечной отказоустойчивости. Он стал инцидентом только тогда, когда деградация стала измеримой. Разрыв между этими моментами и есть реальный риск
Об авторе
Работаю с физической и гибридной инфраструктурой на стыке стойки, сети и продакшн-нагрузки. Часто инциденты начинаются не там, где их видит дашборд
