Files
drhider/PROBLEM-AND-SOLUTION.md
T
2026-07-14 19:19:12 +04:00

84 lines
5.2 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.
# Проблема загрузки файлов: диагностика и решение
**Дата:** 2026-07-14
---
## Суть проблемы
При передаче данных через HTTP POST из внешней сети на managed-сервисы кластера (Flask и другие) периодически возникала константная задержка **51 секунда**. Проблема проявлялась на любом объёме данных — даже на 100 КБ. Внутри кластера (pod → ingress pod напрямую) передача работала мгновенно. Задержка возникала исключительно при прохождении трафика снаружи через VIP (kube-vip), который распределяет запросы по всем нодам кластера.
---
## Причина
**Несоответствие MTU:** канал между серверами — **1450 байт**, а каждый Geneve-туннель добавляет к пакету **50 байт**. При дефолтном MTU пода в 1500 байт любой cross-node-переход через туннель создаёт пакет размером 1550 байт, который не помещается в канал и дропается. Ядро ждёт повторной передачи — отсюда и 51-секундная пауза.
В зависимости от того, на каких нодах окажутся поды, запрос проходит через 0, 1 или 2 Geneve-туннеля:
| Путь | Туннелей | Размер пакета | Проходит? |
|------|----------|---------------|-----------|
| Клиент → нода с ingress → drhider на той же ноде | 0 | 1500 б | ✅ |
| Клиент → нода с ingress → drhider на другой ноде | 1 | 1500 + 50 = **1550 б** | ❌ |
| Клиент → нода без ingress → ingress → drhider | 2 | 1500 + 50 + 50 = **1600 б** | ❌ |
Снижение MTU пода до **1400 байт** устраняет проблему: 1400 + 50 = 1450, что точно вписывается в канал на каждом переходе.
---
## Архитектура кластера
Кластер `iot-naeel`: 4 ноды (3 worker + 1 control-plane), Cilium с Geneve-энкапсуляцией, kube-vip.
```
Ноды: 6f74n | bhbvs | v8zq4 | control-plane
Ingress: 2 пода (Штурвал, всегда на разных нодах)
Drhider: 1 под (размещается на случайной worker-ноде)
VIP: 185.247.187.151 → kube-vip анонсирует на все 4 ноды через ARP
```
**Маршрут запроса:** браузер → VIP (случайная нода) → kube-proxy → ingress-под → kube-proxy → drhider-под. Каждый переход между нодами — Geneve-туннель (+50 байт).
Примеры возможных размещений:
| Ситуация | Drhider | Ingress | Туннелей ingress→drhider |
|----------|---------|---------|--------------------------|
| A | 6f74n | 6f74n + bhbvs | 50% без туннеля, 50% через |
| B | bhbvs | 6f74n + v8zq4 | 100% через туннель |
| C | v8zq4 | bhbvs + v8zq4 | 50% без туннеля, 50% через |
Если клиент попадает на ноду без ingress-пода, kube-proxy добавляет ещё один Geneve-переход.
---
## Тестирование (curl с ВМ, 30 запросов, 63 КБ)
**Цель:** подтвердить, что только MTU 1400 работает стабильно при любом размещении подов.
| MTU пода | Размещение drhider / ingress | Результат |
|----------|------------------------------|-----------|
| **1400** | bhbvs / bhbvs + v8zq4 | **30/30** ✅ |
| **1400** | 6f74n / 6f74n + bhbvs | **30/30** ✅ |
| 1450 | 6f74n / 6f74n + bhbvs | 30/30 (50% без туннеля — повезло) |
| 1500 | 6f74n / 6f74n + bhbvs | 30/30 (50% без туннеля — повезло) |
| 1500 | v8zq4 / v8zq4 + ctrl | 23/30 |
| **1500** | bhbvs / 6f74n + bhbvs | **0/30** ❌ |
При MTU 1500 и drhider на bhbvs с ingress на 6f74n+bhbvs — все запросы идут через Geneve, результат 0/30.
**Вывод:** MTU 1500 работает только случайно (когда поды оказываются на одной ноде). MTU 1400 — единственно надёжное решение.
---
## Текущая конфигурация (2026-07-14)
| Параметр | По умолчанию | Текущее | Причина изменения |
|----------|-------------|---------|-------------------|
| Cilium `mtu` | 1500 | **1400** | 1400 + 50 (Geneve) = 1450 = underlay |
| `proxy-body-size` (ingress) | 8m | **1024m** | Поддержка загрузки файлов до 1 ГБ |
| HTTP/2 | включён | включён | — |
| `externalTrafficPolicy` | Cluster | Cluster | — |
| Реплик ingress | 2 | 2 | — |
Код v0.0.22: XHR-таймаут 30 с, cache-busting, обработка SSE `GeneratorExit`.