doc: план v3 от Соннета — разделение явлений A/B, port-forward первым; принят за основу
This commit is contained in:
@@ -989,3 +989,18 @@ cilium-operator, echo переоценён, нет PMTU/port-forward/второ
|
||||
Pro — методологически полнее, грубых ошибок нет.
|
||||
Рекомендованный синтез-порядок: nginx-логи → PMTU-зонд → сырые TCP →
|
||||
port-forward → tcpdump клиента → второй ISP → cilium monitor → echo → тикет.
|
||||
|
||||
## 2026-08-15 — план v3 от СОННЕТА + сравнение трёх планов
|
||||
|
||||
Сохранён: `doc/thinking/nubes-network-bug-plan-v3-sonnet.md`.
|
||||
|
||||
Оценка (основной агент): план Соннета — лучший из трёх. Ключевые достоинства:
|
||||
явное разделение явлений A (MTU/PMTUD, 51с = экспонента RTO 1-2-4-8-16) и
|
||||
B (регулярность 1/37с = таймер gateway/kube-vip/conntrack), port-forward первым
|
||||
kubectl-тестом, точный список размеров ping-зонда, корреляция по TCP seq.
|
||||
Поправки: fallback если ICMP закрыт (mtr --tcp/TCP-порог), добавить второй
|
||||
ISP и контрольный канал YMQ, port-forward идёт через API-сервер (исключает
|
||||
приложение, но не доказывает шлюз), точный интервал таймаутов мерить новым
|
||||
тестом с timestamp на каждый таймаут.
|
||||
Сравнение: Flash — ошибки и недооценка; Pro — силён, но без явного разделения
|
||||
явлений; Соннет — принять за основу с поправками.
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
# Plan: Доказательство сетевого бага Nubes — v3 (СОННЕТ)
|
||||
|
||||
> ✅ **ПОМЕТКА: это план от Соннета** (пользователь передал ответ Соннета).
|
||||
> Сохранено 2026-08-15. Сравнение с v1 (DeepSeek Flash) и v2 (DeepSeek Pro) —
|
||||
> в конце файла и в HISTORY.
|
||||
|
||||
## TL;DR
|
||||
|
||||
Два РАЗНЫХ явления с разными причинами — нельзя объяснять одной гипотезой и
|
||||
нельзя ловить одним методом. Цепочка: nginx-логи → port-forward (бесплатное
|
||||
доказательство невиновности приложения) → PMTUD-зонд → tcpdump → cilium
|
||||
monitor → echo-сервис (только если предыдущих данных не хватает).
|
||||
|
||||
## Разделение двух явлений (критически важно)
|
||||
|
||||
**Явление A — большие POST (~51с).** Причина: MSS=1448, underlay MTU=1450,
|
||||
сегменты 1488 → дроп. PMTUD сломан (ICMP Type 3 Code 4 заблокирован шлюзом) →
|
||||
TCP ретрасмитит по экспоненте: 1с,2с,4с,8с,16с ≈ 31с, ещё попытка → ~51с.
|
||||
Задача: подтвердить ping-зондом и зафиксировать в тикете.
|
||||
|
||||
**Явление B — малые POST 512 байт (~1/37с).** MTU-моделью НЕ объясняется.
|
||||
Ключевая улика: РЕГУЛЯРНОСТЬ 1/37с — это таймер, не случайные потери.
|
||||
Кандидаты: сессионный таймер gateway на VIP 185.247.187.151 (вероятнее всего),
|
||||
kube-vip ARP keepalive цикл (флап при смене лидера), conntrack GC с агрессивным
|
||||
idle-таймером.
|
||||
|
||||
## 1. Echo vs сырые TCP
|
||||
|
||||
Сырые TCP на 32391 — недостаточны (проверяют только фазу установления; проблемы
|
||||
в фазе ДАННЫХ; nginx ответит RST/400 на мусор — неинформативно).
|
||||
|
||||
Правильный порядок:
|
||||
1. kubectl port-forward (бесплатно, 5 минут) — чище и быстрее echo.
|
||||
2. Echo NodePort без ingress — если port-forward и логи не дали ответа.
|
||||
|
||||
Echo: принимает POST, возвращает тело; `?bytes=N` для размера ответа
|
||||
(обратный путь отдельно от прямого). Деплой БЕЗ ingress, прямой NodePort.
|
||||
|
||||
## 2. Как поймать таймаут: tcpdump
|
||||
|
||||
Клиент (запустить ДО теста, параллельно):
|
||||
`tcpdump -i <iface> -s 0 -w /tmp/sqs.pcap 'host 185.247.187.151 and port 32391'`
|
||||
|
||||
Явление A (51с, большой POST): ICMP Type 3 Code 4 от 185.x → PMTUD работает;
|
||||
нет ICMP, ретрасмиты 1/2/4/8/16с → PMTUD сломан (основная гипотеза); кто шлёт
|
||||
RST в конце и через сколько — чей таймаут (клиент vs nginx/шлюз).
|
||||
|
||||
Явление B (30с, 512 байт): ACK на запрос получен → запрос дошёл, ответ потерян
|
||||
на обратном пути; ACK нет → потеря до nginx (kube-vip/NodePort/gateway);
|
||||
точный интервал между таймаутами (~37с ± 1с → таймер подтверждён); RST от
|
||||
сервера — чей (nginx idle keepalive или gateway).
|
||||
|
||||
Ключевой приём: корреляция по TCP seq/ack, не по времени.
|
||||
|
||||
## 3. kube-vip / NodePort / nginx — только kubectl
|
||||
|
||||
nginx access log: `kubectl logs -n ingress <nginx-pod> --since=35m | grep -E " (499|5[0-9][0-9]) "`.
|
||||
Нужны поля `$request_time $upstream_response_time`. Если нет — проверить
|
||||
ConfigMap nginx.
|
||||
|
||||
| Запись в nginx log | Вывод |
|
||||
|---|---|
|
||||
| 499 + большой request_time | клиент ушёл до ответа (наш ReadTimeout) |
|
||||
| 200 + upstream <100мс, клиент получил таймаут | ответ потерян между nginx и клиентом |
|
||||
| записи нет | потеря ДО nginx: kube-vip/NodePort/gateway |
|
||||
|
||||
kube-vip: `kubectl get pods -A | grep -i vip`, логи (leader/ARP/flap/error).
|
||||
ARP-флап во время теста → кратковременная потеря VIP → дропы.
|
||||
|
||||
Cilium (на ПОДЕ, не на operator): `kubectl get pods -n kube-system -l k8s-app=cilium -o wide`;
|
||||
`kubectl exec -n kube-system <cilium-pod> -- cilium monitor --type drop`
|
||||
параллельно с тестом.
|
||||
|
||||
NodePort/SNAT: `externalTrafficPolicy` — Cluster → любая нода + SNAT (лишний хоп,
|
||||
conntrack); Local → только нода-держатель VIP (миграция VIP → brief outage).
|
||||
|
||||
port-forward: `kubectl port-forward -n <ns> svc/<sqs-svc> 14100:4100` — тот же
|
||||
скрипт на localhost:14100. 0 таймаутов → приложение невиновно.
|
||||
|
||||
## 4. Пошаговый план: дешевле → дороже
|
||||
|
||||
**Фаза 0 — бесплатно, уже есть данные:**
|
||||
1. nginx access log за период прошлого теста (499, request_time/upstream_response_time).
|
||||
2. kube-vip логи: флапы в тот же промежуток.
|
||||
3. Тикет Nubes: два явления отдельно — (A) MTU/PMTUD порог 1448, (B) таймер ~37с.
|
||||
|
||||
**Фаза 1 — клиентские тесты, 30 минут:**
|
||||
4. PMTUD-зонд: `ping -M do -s N 185.247.187.151` для N=1300,1400,1420,1422,
|
||||
1448,1450,1460,1472 — точный порог. Нет ответа ≥1448 → ICMP заблокирован →
|
||||
тикет с числами.
|
||||
5. tcpdump + тот же 30-мин тест. Wireshark: `tcp.analysis.retransmission || icmp`.
|
||||
Точный интервал между таймаутами.
|
||||
|
||||
**Фаза 2 — kubectl, без деплоя:**
|
||||
6. port-forward тест ПЕРВЫМ: 15-мин прогон через туннель. 0 таймаутов →
|
||||
приложение доказанно невиновно.
|
||||
7. cilium monitor параллельно со свежим тестом против внешнего IP.
|
||||
8. Если нет upstream_response_time в формате — обновить ConfigMap, повторить.
|
||||
|
||||
**Фаза 3 — echo (только если 0–2 не дали ответа):**
|
||||
9. Minimal Go echo (NodePort, без ingress), тот же тест. Воспроизвелось →
|
||||
nginx и приложение исключены → kube-vip/NodePort/gateway. Нет → echo через
|
||||
ingress → изоляция nginx.
|
||||
10. Матрица размеров 512/1000/1400/1448/1460/1500 × 10 мин, порог бинарным поиском.
|
||||
|
||||
**Фаза 4 — финальная корреляция для тикета:**
|
||||
11. Одновременно tcpdump + nginx access log + cilium monitor. Корреляция по
|
||||
seq: «запрос ушёл, ACK получен, ответа нет» = потеря между nginx и клиентом.
|
||||
Артефакты: pcap + логи + ping-зонд → тикет.
|
||||
|
||||
**Решения о приоритетах:**
|
||||
- port-forward — самый дешёвый и чистый способ изолировать приложение. ДО echo.
|
||||
- Сырые TCP на 32391 — пропустить.
|
||||
- Echo — только если port-forward + nginx-логи не дали ответа.
|
||||
- Явления A и B документировать в тикете РАЗДЕЛЬНО.
|
||||
|
||||
---
|
||||
|
||||
## Поправки основного агента (GitHub Copilot)
|
||||
|
||||
1. **ICMP может быть закрыт на шлюзе** — тогда ping-зонд не даст порога.
|
||||
Нужен fallback: mtr --tcp / tcptraceroute или TCP-сегменты переменного
|
||||
размера (то, что Соннет отбросил как «сырые TCP» — но для определения
|
||||
ПОРОГА размера они валидны).
|
||||
2. **Второй клиент с другого ISP** (был у Pro) — отсутствует. Дешёво исключает
|
||||
локальную сеть пользователя. Добавить в фазу 1.
|
||||
3. **Параллельный контрольный канал YMQ** — стоит сохранить во всех тестах:
|
||||
отделяет «плохой интернет вообще» от «плох путь до Nubes».
|
||||
4. **port-forward идёт через API-сервер** — не тот сетевой путь; чистый
|
||||
результат исключает приложение, но НЕ доказывает шлюз. Формулировка Соннета
|
||||
«доказательство невиновности приложения» — корректна, использовать её.
|
||||
5. **Точный интервал таймаутов** надо измерять новым тестом с timestamp на
|
||||
каждый таймаут (в прошлом тесте тайминги не логировались поштучно).
|
||||
6. Смена nginx log format (ConfigMap) на managed может требовать релода/помощи
|
||||
платформы — держать как запасной шаг.
|
||||
|
||||
## Сравнение трёх планов
|
||||
|
||||
| | Flash (v1) | Pro (v2) | Соннет (v3) |
|
||||
|---|---|---|---|
|
||||
| Разделение явлений A/B | нет | частично | **явно, с причиной B=таймер** |
|
||||
| Ошибки команд | cilium через operator | нет | нет |
|
||||
| PMTU-зонд | нет | есть | есть, точный список размеров |
|
||||
| port-forward | нет | есть | **первым kubectl-тестом** |
|
||||
| Сырые TCP | недооценены | да | отброшены (спорно для порога) |
|
||||
| Второй ISP | нет | есть | нет |
|
||||
| Критерии доказательства | слабые | таблица | таблицы + фазы |
|
||||
| Объяснение 51с | нет | «прикладной таймер» | **экспонента RTO 1-2-4-8-16** |
|
||||
|
||||
Вердикт: план Соннета — лучший из трёх. Принять за основу с поправками 1–6.
|
||||
Reference in New Issue
Block a user