Собраны и проверены по источникам все факты из ~/nubes/drhider: - диагноз: ingress рвёт входящие тела >64КБ, egress не ограничен; - схема пофайлового транзита через ВМ-буфер + egress-GET (pull); - применённые фиксы платформы (cilium mtu:1400, keep-alive 10->75, proxy-body-size 1024m, HTTP/2 off) через ShturvalServiceConfig; - ложные следы, лимиты, SSRF/path-traversal защиты, тесты 25/25; - вывод: тикет в поддержку — не решение, нужен архитектурный обход.
12 KiB
Находки: как та же сетевая болезнь платформы уже решена в drhider (буфер на ВМ)
Дата: 2026-10-08
Источник находок: репозиторий ~/nubes/drhider (+ ~/nubes/drhider/upload-platform)
Зачем: у shared-sqs та же проблема (таймауты внешнего пути, большие тела), и
наивный путь «отправить тикет в Nubes» оказался тупиком — явление признано
болезнью платформы. В drhider ту же болезнь обошли архитектурно, а не починили.
⚠️ ГЛАВНЫЙ ВЫВОД
Ingress managed-кластера обрывает ВХОДЯЩИЕ тела больше порога, а ИСХОДЯЩИЙ трафик (egress) из кластера не ограничен. Отсюда рабочий приём: не «толкать» большие данные в кластер (push), а «вытягивать» их извне (pull) — данные кладутся на внешний хост-буфер, а приложение в кластере забирает их исходящим запросом. Тикет в поддержку проблему не решает.
1. Диагноз проблемы (цитаты из drhider)
upload-platform/HISTORY/2026-09-06-layer2-architecture-and-api-boundaries.md:18:
«Причина существования: Ingress-контроллер k8s-кластера (
pythonk8s) обрывает входящие запросы с телом более 64 КБ. ПрямойPOSTбольших файлов в кластер невозможен; исходящий трафик (egress) из кластера не ограничен.»
PLAN-upload-layers.md:27 (контекст, «что уже проверено»):
«Паттерн загрузки (шлюз managed-кластера рвёт тела >64КБ, egress не ограничен): браузер →
PUTна ВМ-буфер → FlaskPOST /api/upload_refs→ egressGET(pull) → сессия.»
Это ровно тот же класс, что явление A у shared-sqs (большие POST), только у
drhider порог «тело >64 КБ» на ingress, а у SQS — MSS/MTU-порог ~1.4 КБ на
внешнем шлюзе (doc/thinking/nubes-ticket.md, явление A). Причина на стороне
платформы в обоих случаях.
2. Схема обхода, применённая в drhider (пошагово)
upload-platform/HISTORY/2026-09-06-layer2-architecture-and-api-boundaries.md:19-27
— «Пофайловый транзит (Per-File Transit)»:
- Файл №k браузер отправляет методом
PUTв буфер на ВМ (вне кластера). - Браузер сразу шлёт в приложение (Flask в кластере)
POST /api/upload_refs— тело запроса маленькое (только ссылка на файл), поэтому ingress его пропускает. - Приложение само забирает файл исходящим потоковым
GETпрямо в память сессии — egress не режется. - Приложение немедленно отправляет
DELETEна ВМ — буфер очищен. - Браузер переходит к файлу №k+1. В буфере на ВМ в любой момент максимум один файл.
Дополнительные принципы оттуда же:
- RAM-only: без постоянной записи на диск ни в кластере, ни на ВМ.
- Zero hardcode: адрес буфера и префикс — параметры конфигурации
(
vmUploadUrlна фронте,vmUploadPrefixна бэке для обязательной SSRF-проверки). - Автономный mock-буфер (in-memory WebDAV) для тестов без внешней сети.
upload/README.md:13 подтверждает ту же механику:
«Пофайловый стриминг: для каждого файла выполняется
PUTв буфер на ВМ, немедленныйPOST /api/upload_refsв бэкенд, и после подтверждения приёма буфер на ВМ очищается.»
3. Что нельзя потерять при переносе (накоплено в drhider)
PLAN-upload-layers.md (раздел «Требования/что НЕЛЬЗЯ потерять»):
- дедупликация «имя+размер» (иначе суффикс
_2); - раскрытие ZIP с путями и фильтр расширений (
.pdf .doc .docx .txt .md); - рекурсивный обход папок (
webkitdirectory); - SSRF-валидация URL (
url.startswith(VM_UPLOAD_PREFIX)); _safe_name— защита от path traversal с сохранением подпапок;- повторы pull (3 попытки, пауза 2 с);
- лимиты 50 МБ на файл / 500 МБ на сессию;
- различение «сессия не найдена» и «превышен лимит»;
- статусы «пропущен (лимит)» / «не извлечён»;
- экранирование имён для защиты от self-XSS.
4. Фиксы платформы, которые уже применили (и их границы)
PROBLEM-AND-SOLUTION.md (drhider, v0.0.31, 2026-07-16):
Проблема 1 — пауза 51 с (MTU). Underlay MTU 1450, Cilium Geneve добавляет
50 байт, дефолт пода 1500 → пакет 1550 → фрагментация → дроп → ядро ждёт
повторной передачи 51 с. Решение: cilium-config → mtu: 1400
(1400+50 = 1450). Задокументировано 2026-07-13, применено 2026-07-14.
Проблема 2 — ERR_CONNECTION_RESET в браузере. Истинная причина —
keep-alive: 10 вместо дефолта 75: пока пользователь выбирал файлы (>10 с),
nginx закрывал idle-соединение, браузер не замечал FIN и слал POST в закрытый
сокет → RST. Решение (в платформе Штурвала, 2026-07-15) — через
ShturvalServiceConfig, а не через kubectl:
controller:
config:
keep-alive: "75"
proxy-body-size: "1024m"
client-body-timeout: "60"
client-header-timeout: "30"
hostPort:
enabled: true
replicaCount: 2
service:
type: LoadBalancer
Важно: правки ingress на платформе делаются через
ShturvalServiceConfig— через kubectl нельзя, ArgoCD откатывает.
Ложные следы, которые опровергли (та же таблица): kube-vip ARP flapping, hostPort на 2 из 4 нод, upstream keepalive, conntrack, MTU (для проблемы 2), HTTP/2.
Результаты после фиксов (v0.0.29, 2026-07-15): 10× POST 63 КБ — 10/10 OK; полный UI-цикл (5 файлов + SSE + ZIP + CSV) — OK; 5× POST с интервалом 75 с — 5/5 OK; PDF 5 МБ через curl — 200 OK за 0.62 с. Итого 25/25, 0 RST.
⚠️ Но это вылечило ingress-таймер и MTU-фрагментацию, а не порог размера тела: обходной слой через ВМ-буфер остался нужен и является рабочим решением.
5. Обходы «не по сети» — тот же принцип pull/вынос
PROBLEM-AND-SOLUTION.md:71: doc_to_markdown() переписали — вместо локального
soffice (LibreOffice на ВМ, тяжёлый и не тянул) HTTP-вызов внешнего сервиса
liberta.containerk8s.dev.nubes.ru/convert через httpx. То есть тяжёлую/медленную
работу тоже вынесли наружу и ходят к ней по HTTP.
Смежное (из кода drhider): конвертация .doc через liberta выполняется
последовательно (_LLM_CONCURRENCY = 1) — сервис не выдерживает
конкурентность (drhider/extractor.py:160-194, drhider/scanner.py:122).
6. Готовый переиспользуемый модуль (для справки)
PLAN-upload-layers.md — слои выделены так, чтобы их можно было перенести в
любой проект копированием (без общей репы):
| Слой | Где | Ответственность |
|---|---|---|
| 0. Конфиг | общий | адрес ВМ-буфера, расширения, лимиты |
| 1. Выбор файлов | фронт | таблица, дедуп, ZIP, дерево папок, статусы |
| 2. Закачка через ВМ | фронт + бэк | PUT на ВМ → upload_refs pull → сессия |
| 3. Логика приложения | бэк | обработка (у каждого своя) — не выносится |
Реализация-эталон: ~/nubes/drhider/upload-platform/ (Слой 1 v0.1.13 готов,
Слой 2 в работе на 2026-09-06), а также рабочий образец ~/nubes/drhider/upload/.
7. Инфраструктурные факты
- ВМ-буфер:
5.172.178.213(вне кластера). Nginx WebDAV, каталоги/var/www/drhider-upload/,/var/www/contracts-upload/, cron-очистка каждые 5 минут (find … -mmin +30 -delete). Для целевого прода — перевод в RAM/in-memory буфер. - SSH к ВМ:
ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213(README.md:141). - Кластеры/неймспейсы:
pythonk8s(ingress режет >64 КБ); сервисы drhider, contractor, uploader-dev.
8. Выводы (что берём из чужого опыта)
- Тикет в Nubes — не решение. Это болезнь платформы; в drhider её не «починили»,
а обошли. Тикет (
doc/thinking/nubes-ticket.md) имеет смысл только как фиксация для истории, не как способ получить рабочий сервис. - Рабочий приём — pull вместо push: внешний буфер + исходящий
GETиз кластера. Egress свободен, ingress режется. - Правки ingress на платформе — только через
ShturvalServiceConfig(kubectl откатывается ArgoCD). - MTU-фикс (
cilium mtu: 1400) нужен как гигиена, но порога больших тел не снимает. - Тяжёлые/медленные операции тоже выносятся наружу и вызываются по HTTP
(пример:
liberta).
Источники (файл:строка)
| Источник | Что |
|---|---|
~/nubes/drhider/PROBLEM-AND-SOLUTION.md |
MTU-фикс, keep-alive 10→75, ложные следы, тесты 25/25 |
~/nubes/drhider/PLAN-upload-layers.md:27 |
паттерн «шлюз рвёт >64 КБ, egress свободен» |
~/nubes/drhider/upload/README.md:13 |
пофайловый стриминг через ВМ-буфер |
~/nubes/drhider/upload-platform/HISTORY/2026-09-06-layer2-architecture-and-api-boundaries.md:18-27 |
диагноз + пошаговый пофайловый транзит, RAM-only, mock-буфер |
~/nubes/drhider/docs/MSS-CLAMPING-PLAN.md, docs/about1500.md, docs/INGRESS-SOLUTIONS.md |
сопутствующие материалы по MTU/MSS/ingress |
~/nubes/drhider/drhider/extractor.py:160-194, drhider/scanner.py:122 |
вынос конвертации в сервис liberta, последовательные вызовы |