Files
gpu-rent/docs/architecture.md
T
Leonid Pershin 71f4e4c2e3 Update extensions and documentation for LLM integration and CLI enhancements
- Added support for a new extension, `swarm-assistent`, in `extensions.example.yaml` with a requirement for `ollama`.
- Enhanced the README.md to clarify the setup process and provide a quick start guide for using extensions.
- Updated documentation in `llm.md` to reflect the opt-in nature of LLM support and provide clearer instructions for enabling it.
- Improved the `autocomplete.md` to detail the automatic setup of word lists during the initial launch.
- Revised `cli.md` to include new commands and options related to LLM runtime handling and extension management.
- Enhanced the `spike-notes.md` to guide users through the first live run with a focus on LLM integration.
2026-08-21 05:49:34 +03:00

177 lines
10 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.
# Архитектура
## Обзор
```
┌─ локальная машина (Windows / Linux) ─────────────────────────┐
│ gpu-rent CLI │
│ up / stop / status / doctor / hold │
│ tunnel / open — SSH localhost:17801 → VM :7801 │
│ state <repo>/.gpu-rent/state.json │
│ │
│ браузер / MCP / curl API → http://127.0.0.1:17801 │
│ локальный SwarmUI → http://127.0.0.1:7801 (не трогаем)
└───────────────────────────────┬──────────────────────────────┘
│ SSH :22 и OpenStack API
┌─ Selectel, сегмент пула (например ru-7a) ────────────────────┐
│ GPU VM (tag preemptible + gpu-rent) │
│ SwarmUI : 127.0.0.1:7801 │
│ idle-killer: очередь / hold / LLM busy → delete this server │
│ app cred: DELETE/GET только этот server_id (fail closed) │
│ optional: Ollama :11434 / llama.cpp :8080 (туннель 17811/12)│
│ │
│ boot volume (network) ОС + NVIDIA + SwarmUI нативно + snapshot │
│ data volume (network) Models, Output, Data, workflows │
│ floating IP только SSH, удаляется на stop │
└──────────────────────────────────────────────────────────────┘
```
Два сетевых диска. После удаления VM boot-диск снова указывают как `--volume` при create.
Разделение **жизни GPU** и **локального туннеля** — следствие [decisions.md](decisions.md): ноут можно закрыть.
## Слои CLI
| Модуль | Ответственность |
| --- | --- |
| `cli` | Typer: `up`, `setup`, `tunnel`, `open`, `status`, `stop`, `destroy`, `logs`, `ssh`, `doctor`, `hold`, `seed-*`, `push` / `pull-output`, `resize-data`, `watchdog`, `dry-run` |
| `config` / `varsfile` | `.env` + `gpu-rent.vars`, пути |
| `state` | JSON сессии: ids, фаза, timestamps |
| `os_client` / `cloud` / `pools` | openstacksdk, ресурсы, скан пулов |
| `inventory` | Flavors/images, квоты, фоллбек flavor |
| `session` | `cmd_up` / `cmd_stop` / adopt |
| `bootstrap` + `remote/bootstrap.sh` | Идемпотентный first-boot; light без apt |
| `provision` | extensions, autocomplete, civitai seed, push, idle-killer arm, start SwarmUI |
| `doctor` | Preflight без mutating compute |
| `sync_files` | SFTP `Models` / Wildcards / workflows / Output |
| `notify` | Toast/звук при backend Idle |
| `tunnel` | sshtunnel + Nova EXPIRED watchdog |
| `local_watchdog` | Опциональный локальный тик → stop при unclean exit |
| `llm_runtime` / `setup_wizard` | Opt-in Ollama/llama.cpp + `ollama-models.yaml` |
| `idle_killer` / `hold` | systemd на VM + hold-файл |
| `ready` / `snapshot` | Idle backend + boot snapshot |
Каталог сервисов — из Keystone, не из выдуманного `api.selectel.ru/v3/`.
## Два диска
### Boot volume
Сетевой, тот же сегмент, что VM. Первый раз — GPU-optimized образ **без Docker**. `delete_on_termination=false`. Локальный boot запрещён (preemptible сотрёт ОС).
После bootstrap: NVIDIA из образа, `/opt/swarmui` + systemd, unit idle-killer, application credential в `/root/.gpu-rent/` (mode 600).
После **первого** успешного `waiting_ui` + backend Idle: один snapshot boot-диска `gpu-rent-boot-ok` (если ещё нет). Следующий create VM может идти из snapshot, не из сырого GPU-образа. Старый snapshot не плодить каждый `up`.
### Data volume
Второй BDM при create (не attach после ACTIVE). FS один раз, маркер `/mnt/swarm_data/.gpu-rent-ready`. Первый seed: [extensions.md](extensions.md), [autocomplete.md](autocomplete.md), [models.md](models.md), [local-folders.md](local-folders.md).
| На хосте (data volume) | В дереве SwarmUI (`/opt/swarmui`, bind) |
| --- | --- |
| `/mnt/swarm_data/Models` | `/opt/swarmui/Models` |
| `/mnt/swarm_data/Output` | `/opt/swarmui/Output` |
| `/mnt/swarm_data/Data` | `/opt/swarmui/Data` |
| `/mnt/swarm_data/dlbackend` | `/opt/swarmui/dlbackend` |
| `/mnt/swarm_data/Extensions` | `/opt/swarmui/src/Extensions` |
| `/mnt/swarm_data/DLNodes` | `/opt/swarmui/src/BuiltinExtensions/ComfyUIBackend/DLNodes` |
| `/mnt/swarm_data/CustomWorkflows` | `/opt/swarmui/src/BuiltinExtensions/ComfyUIBackend/CustomWorkflows` |
`mkfs` только если нет маркера **и** `blkid` подтвердил пустое устройство по serial/by-id. Не хардкодить `scsi-0Selectel_Volume_…`.
## Стейт-машина
Фазы в `state.json` (код пишет только эти):
```
idle
│ gpu-rent up
provisioning ← create volumes / server
bootstrapping ← SSH + bootstrap + seed (пока не ready)
ready_cloud ← compute жив, idle-killer вооружён
│ gpu-rent tunnel (или up с туннелем)
ready_tunneled ← localhost:17801
│ stop | idle-killer | local-watchdog | destroy
idle
```
Подшаги seed (extensions / autocomplete / models) идут внутри `bootstrapping`, отдельными фазами в state не пишутся. `ready_cloud` ≠ Nova `ACTIVE` (ACTIVE бывает раньше SSH и UI).
На EXPIRED туннель сам делает unshelve → снова `bootstrapping`/`ready_*`.
## Idle-killer (на VM)
Пока очередь SwarmUI пуста дольше **30 минут**, скрипт удаляет **этот** compute через OpenStack (диски не трогать). Открытый браузер без джобы жизнь **не** продлевает.
Killer молчит:
- clone расширений, Civitai-seed, push локальных папок;
- первые **45 минут** после ACTIVE или unshelve;
- пока backend/ComfyUI ещё не Idle;
- пока существует hold: файл `/mnt/swarm_data/.gpu-rent-hold-until` с unix ts (пишет `gpu-rent hold`);
- пока SwarmUI качает модель в UI (Model Downloader / активный download — точный JSON на spike). Нет сигнала — пользователь жмёт `hold`.
`gpu-rent hold` без аргументов = +`IDLE_MINUTES` от сейчас. `--minutes 90` — hold до now+90 мин (заменяет предыдущий, не складывает). `--until` ISO опционально. `hold --clear` снимает.
Потом счётчик 30 минут пустой очереди.
Почему не `shutdown -h now`: у Selectel останов из гостя не обязан снять GPU с биллинга. Нужен API delete/shelve.
Почему не только локальный CLI: ноут спит — процесса нет — GPU продолжает тарифицироваться.
Учётные данные на VM: application credential (или роль без `compute:create`), только delete/shelve. Файл не попадает в Output/Models. Истечение кредов = killer слеп; тогда спасает `gpu-rent status` с ноутбука.
Дефолты: `IDLE_MINUTES=30`, `IDLE_GRACE_MINUTES=45`.
## Watchdog туннеля (на ноутбуке)
Работает только пока открыт туннель:
1. Refresh IAM-токена (TTL 24 ч, как у preemptible).
2. `EXPIRED` → unshelve → переоткрыть туннель.
3. `ERROR` / нет GPU → выход, не бесконечный recreate.
4. Туннель мёртв при ACTIVE → reconnect.
`Ctrl+C` здесь закрывает туннель, **не** вызывает `stop`.
## Teardown (`gpu-rent stop`)
Compute удаляется через OpenStack без SSH. Optional pull Output — только если VM ещё отвечает по SSH:
1. Если `PULL_OUTPUT` и SSH жив — забрать новые файлы в `./Output` (`--no-pull` пропускает).
2. Закрыть туннель этого процесса, если открыт.
3. Удалить compute. Volumes оставить.
4. Дождаться исчезновения сервера.
5. Удалить floating IP (`KEEP_FLOATING_IP=false`).
6. State → `idle`, сохранить volume ids.
`destroy` — то же + диски после `--i-understand-data-loss`.
Reconcile: сервер с тегом `gpu-rent` есть, локального процесса нет — это норма (`ready_cloud`). Сирота = нет тега в state и наоборот; `status` показывает «жив, туннеля нет, idle-killer: …».
## Сеть на VM
- Private net + subnet + router — один раз на пул, переиспользовать.
- SG: ingress TCP/22 с IP оператора. **Не** открывать 7801 наружу.
- SwarmUI: `--host 127.0.0.1 --port 7801` (systemd `swarmui`).
- Туннель: `127.0.0.1:17801``127.0.0.1:7801` на VM.
## Стек
| Слой | Выбор |
| --- | --- |
| Python 3.11+ | openstacksdk, paramiko, sshtunnel, Typer, Rich, dotenv, httpx, pyyaml |
| SSH | paramiko + sshtunnel (Windows без системного `ssh -L`) |
| Конфиг | `<repo>/.env` + `gpu-rent.vars` + runtime в `<repo>/.gpu-rent/` |
| Лицензия | MIT |