Files
naeel f6b4fab5c2
Deploy loadtest / validate (push) Has been cancelled
docs: README — project overview, problem, fix, usage
2026-07-11 15:22:13 +04:00

78 lines
4.1 KiB
Markdown
Raw Permalink 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.
# loadtest — загрузка файлов через Managed Flask (Shturval)
Тестовый проект для проверки Managed Flask на платформе Shturval 2.12.1.
Задача: принять загрузку файлов 3-5 MB через веб-интерфейс стабильно и быстро.
## Как работает
- **Фронтенд:** HTML + vanilla JS, выбор файлов, прогресс-бар, drag-and-drop
- **Бэкенд:** Flask 3.1 + flask-sock (WebSocket) + Gunicorn (gevent worker)
- **Загрузка:** WebSocket, 64KB чанки, один connection на все файлы
- **Деплой:** git push → Shturval auto-deploy
## Проблема: 51-секундный TCP stall
### Симптом
Файл 3.7 MB — 90% мгновенно, затем пауза ровно 51 секунда. В ~80% соединений.
### Корень
`externalTrafficPolicy: Cluster` (дефолт) на LoadBalancer-сервисе `shturval-ingress-controller-controller`. Kube-vip в ARP-режиме форвардил трафик на ноды без локального ingress-пода → cross-node форвардинг через Geneve → TCP zero window oscillation → 51 секунда.
### Исправление (платформа)
```bash
kubectl patch svc -n ingress shturval-ingress-controller-controller \
-p '{"spec":{"externalTrafficPolicy":"Local"}}'
kubectl scale deploy -n ingress shturval-ingress-controller-controller --replicas=4
```
С `Local` трафик идёт только на ноды с локальными ingress-подами. Cross-node форвардинг исключён.
### Что НЕ помогло
- Flow control на клиенте (`bufferedAmount`, ACK)
- Gunicorn вместо Werkzeug
- nginx keepalive, buffering, таймауты
- nodeSelector, hostNetwork
- HTTP POST вместо WebSocket
Внутри кластера всё работало мгновенно — проблема была только при проходе через VIP извне.
## Как юзать загрузку
1. Открыть https://loadtest.pythonk8s.dev.nubes.ru/
2. Нажать «Выбрать файлы» или перетащить файлы в зону загрузки
3. Нажать «Загрузить»
4. Прогресс-бар показывает реальный прогресс
5. После загрузки — ✓ с временем и скоростью
Поддерживается множественная загрузка (несколько файлов подряд через один WebSocket).
## Структура проекта
```
.
├── Dockerfile # Gunicorn CMD (не используется Shturval)
├── requirements.txt # flask, gunicorn, gevent, flask-sock
├── site/
│ ├── app.py # Flask: /, /health, /upload (HTTP), /ws-upload (WS)
│ ├── static/
│ │ └── app.js # Клиент: выбор файлов, WebSocket загрузка
│ └── templates/
│ └── index.html # UI
└── History/ # Полная история расследования
├── 2026-07-11-fix-externalTrafficPolicy.md # Финальный фикс
├── 2026-07-11-sonnet-review.md # Отчёт для ревью
└── 2026-07-11-review-response.md # Рецензия и выводы
```
## Выводы для других проектов на Shturval
1. **Managed Flask может принимать большие файлы** — после фикса платформы
2. **Всегда проверять «работает ли изнутри кластера»** — это изолирует платформу от кода
3. **WebSocket через managed ingress работает**с правильным `externalTrafficPolicy`
4. **Если платформа не чинится** — вынести загрузку на ВМ с родным nginx (как в проекте `contracts`)
## Версия
Текущая: **1.0.25** (baseline WebSocket + Gunicorn gevent)