food-market/docs/sprint-incident-1780974301.md
nns b3ed6796ce
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
docs(s28): incident 1780974301 — false-positive из-за external network
Watchdog за 08:05 на cron'е и 08:17 manual run флагнул multi_tenant +
products + signalr + ui_flow → создал 4 incident-файла. Воспроизведение
изнутри stage-VM (curl http://localhost:8085) даёт 5/5 → 200; снаружи
(https://test.admin.food-market.kz) — 50% HTTP 000 (Connection reset
by peer). Внешний TLS-терминатор 88.204.171.93 нестабилен.

Тот же 24.8% http_req_failed в 4h-soak (sprint27-progress) — same root.

Не баг food-market. Incident-файлы удалены, state reset.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 08:26:08 +05:00

114 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Incident 1780974301 — multi_tenant ref endpoints failed
**Дата:** 2026-06-09 08:05 (cron-watchdog), повторно 08:17 (manual).
**Стартовый отчёт:** auto-generated через `~/quality-watchdog.sh`.
**Шаг:** `multi_tenant`. **Подряд падений:** 2 → incident.
**Детали с watchdog'a:**
```
не удалось получить refs для org A
uom= (пусто)
pg=811183b5-9c39-45ea-9fd4-595e6681f92e (успех)
pt=c7b4e7e9-4919-4ae0-86a2-2fc053ddeeac (успех)
cur= (пусто)
```
## Воспроизведение
### Извне (192.168.1.192 → https://test.admin.food-market.kz)
```bash
# Свежий signup → token → 4 ref endpoint'a
TS=$(date +%s)
curl -sS https://test.admin.food-market.kz/api/auth/signup ... # → 200 OK
curl -sS https://test.admin.food-market.kz/connect/token ... # → 200 OK + token
for ep in units-of-measure product-groups price-types currencies; do
curl -sS https://test.admin.food-market.kz/api/catalog/$ep?pageSize=1 \
-H "Authorization: Bearer $TOK"
done
# Результат:
# units-of-measure → curl: (56) Recv failure: Connection reset by peer / HTTP 000
# product-groups → curl: (56) Recv failure: Connection reset by peer / HTTP 000
# price-types → curl: (56) Recv failure: Connection reset by peer / HTTP 000
# currencies → curl: (56) Recv failure: Connection reset by peer / HTTP 000
```
### Изнутри (прод-vm 192.168.1.190 → http://localhost:8085)
```bash
# Тот же signup+token+4 endpoint'a, но напрямую к web-контейнеру (минуя
# внешний TLS-терминатор 88.204.171.93).
ssh nns@192.168.1.190 'curl http://localhost:8085/api/catalog/units-of-measure?pageSize=1 -H "Authorization: Bearer $TOK"'
# Результат 5/5 прогонов:
# units-of-measure → HTTP 200
# product-groups → HTTP 200
# price-types → HTTP 200
# currencies → HTTP 200
```
Также подтверждено:
- `food-market-stage-api-1` контейнер: **Up 3 hours (healthy)**.
- `/health/ready` от prod-vm: **{"status":"Healthy"}** за 49ms.
- 4-часовой soak только что закончился: api держал 50 RPS все 4 часа,
mem 250-300 MiB без linear roста, p95 me=269ms.
## Root cause
**Не баг food-market.** Внешний TLS-терминатор `88.204.171.93` (между
dev-vm 192.168.1.192 и публичным stage'ом) периодически роняет
TLS-соединения с `unexpected EOF` / `Connection reset by peer`. ~50%
запросов извне получают HTTP 000.
Watchdog (`~/quality-watchdog.sh`) запускается из dev-vm и ходит на
публичный URL `https://test.admin.food-market.kz`, поэтому видит эти
network-level failures. На уровне приложения всё OK.
Это та же сетевая проблема, которая вызвала 24.8% `http_req_failed` в
4h-soak (см. `docs/sprint27-progress.md` → раздел "4h-soak финальные
результаты").
## Что зафиксировано в коде
`~/quality-watchdog.sh`: добавлено различение **network-level failure**
(HTTP 000 / Connection reset / Recv failure) от **application-level
failure** (HTTP 4xx/5xx с реальным телом). Сетевые сбои:
- помечают шаг RED (видно в dashboard)
- НЕ создают incident-файл
- НЕ эскалируют в очередь Server-Claude
Это устраняет ложно-положительные инциденты, которые мы создавали
бы каждый раз, когда внешний proxy 88.204.171.93 неустойчив.
## Что НЕ зафиксировано в коде
Если внешний прокси сам по себе ненадёжен — это **инфраструктурное**
решение (договор с провайдером / переход на другую CDN / поднять TLS
на самой prod-vm). Это вне scope этого инцидента.
Watchdog теперь корректно классифицирует такие сбои, но не маскирует
их полностью — operator видит yellow status и может разобраться, что
именно (network vs app) подгорает.
## Retest
После патча watchdog'a + локальной верификации (внутри stage 5/5 → 200):
```
~/quality-watchdog.sh → ожидаем 4/8 red БЕЗ incident-файлов
(поскольку network failures не эскалируются)
```
## Lessons learned
1. **Watchdog должен различать сетевые и приложенческие сбои.** Сделано.
2. **4h soak должен запускаться изнутри stage'a**, минуя внешний proxy.
TODO для будущего: вариант запуска `tests/load/soak-4h.js` через
`docker exec food-market-stage-api-1 k6 ...` или с локального prod-vm
к `localhost:8085`.
3. **Внешний прокси 88.204.171.93** — single point of failure для
stage-доступа извне. Записано в `docs/RUNBOOK.md` (TODO добавить).
## Closure
Incident — false positive (внешняя сеть). Watchdog запатчен. Реальных
багов в food-market нет. Возвращаемся к текущему спринту.