мануал ВМ: +раздел ПОЧЕМУ ВМ (опыт через кластер), приём на ВМ, сквозной сценарий

This commit is contained in:
“Naeel”
2026-08-23 06:39:17 +03:00
parent bed4d38468
commit 48a7cbb7c0
@@ -5,7 +5,25 @@ _Назначение: руководство для переделки логи
не проходит через managed-кластер._
---
## 0. ПОЧЕМУ через ВМ — хронология попыток через кластер (все провалились)
Что пробовали, чтобы большой файл прошёл ВХОД на managed-кластер, — и итог:
| Попытка | Результат | Итог |
|---|---|---|
| Прямой `POST /upload` (multipart) | тела >~64КБ → HTTP 000 ~10с | блокер входа |
| Аннотации ingress (`proxy-body-size`, таймауты, `request-buffering`, `client-body-*`) | не влияют | бесполезно (обрыв на внешнем шлюзе) |
| `Transfer-Encoding: chunked` (чанки 32КБ) | обрыв ~10-15с при любом размере | бесполезно |
| Чанки на клиенте (POST по 50КБ, в т.ч. в БД) | только первый чанк доходит | бесполезно |
| ConfigMap ingress (`client-body-timeout 60`, `proxy-body-size 1024m`) + replicas=число нод | РАБОТАЕТ, но ТОЛЬКО на своём кластере (kubectl) | костыль; на чужом кластере нельзя |
| **Egress (Flask сам тянет с ВМ)** | 1-50МБ стабильно 200 | ✅ единственный универсальный путь |
**Вывод:** вход в managed-кластер физически ограничен (~64КБ / ~10с) и не настраивается через
UI/аннотации. Выход (egress) — НЕ ограничен. Поэтому: файлы входят через ВМ, а Flask тянет их
сам (pull). Детали неудач: `History/2026-08-21-annotation-tests.md`,
`History/2026-08-21-root-cause-found.md`.
---
## 1. Проблема (что и почему не работает)
**Входной шлюз managed-кластеров Nubes** (внешний балансировщик перед кластером):
@@ -52,6 +70,35 @@ _Назначение: руководство для переделки логи
## 3. Как повторить (пошагово)
### 3.0 Приём файла на ВМ (первая половина схемы)
1. Браузер шлёт файл на ВМ напрямую (минуя managed). На ВМ нужен приёмный endpoint.
На ВМ уже работает `convert_server.py` (:8766) — добавить туда endpoint, либо отдельный
маленький сервис. Пример (Flask на ВМ):
```python
# ВМ: приём и временное хранение
@app.route("/upload-lt", methods=["POST"])
def upload_lt():
f = request.files["file"]
fid = uuid4().hex
path = f"/var/www/lt-serve/{fid}"
f.save(path)
return jsonify({
"ok": True, "id": fid, "size": os.path.getsize(path),
"url": f"https://contracts.kube5s.ru/lt-serve/{fid}",
})
```
2. nginx на ВМ: для этого пути `client_max_body_size 100m` (или больше) — БЕЗ лимита 64КБ.
3. После сохранения ВМ сообщает Flask: **маленький POST (<64КБ — проходит шлюз)** с метаданными:
```json
{ "id": "...", "url": "https://contracts.kube5s.ru/lt-serve/<id>", "name": "файл.pdf", "size": 47729215 }
```
4. Flask получает метаданные и САМ тянет файл по `url` (egress GET, см. `/fetch` в 3.2).
### 3.1 На ВМ (5.172.178.213) — раздача файлов через существующий nginx
1. Каталог: `/var/www/lt-serve/` (nginx-юзер `www-data` имеет доступ; `/home/naeel` — НЕТ, 403).
2. В `nginx-contracts.conf` (sites-enabled) добавлен location (отдельный блок, рядом с `/docs/`):
@@ -105,6 +152,14 @@ def fetch_url():
Добавление остальных (таймауты, request-buffering) → падение скрипта платформы
(`script returned exit code 1`, `No such property: name for class: Script2`).
### 3.4 Полный сквозной сценарий (5 шагов)
1. **Браузер** → `POST https://contracts.kube5s.ru/upload-lt` (nginx ВМ), файл 45МБ.
2. **ВМ** сохраняет в `/var/www/lt-serve/<id>`, отвечает `{id, size, url}`. Без лимита 64КБ.
3. **ВМ** (или клиент) → маленький `POST` на managed `.../upload-meta` `{url, name, size}` — проходит шлюз.
4. **Flask** по метаданным делает исходящий `GET url` (egress) и читает файл.
5. Flask обрабатывает (парсинг/БД/статусы). ВМ удаляет файл после загрузки или по TTL.
---
## 4. Кластеры (наблюдения 2026-08-21)