diff --git a/docs/architecture.md b/docs/architecture.md index 48201f8..81e1405 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -133,7 +133,7 @@ Killer молчит: Учётные данные на VM: application credential (или роль без `compute:create`), только delete/shelve. Файл не попадает в Output/Models. Истечение кредов = killer слеп; тогда спасает `gpu-rent status` с ноутбука. -Дефолты: `IDLE_MINUTES=30`, `IDLE_GRACE_MINUTES=45`. +Дефолты: `IDLE_MINUTES=60`, `IDLE_GRACE_MINUTES=90`. ## Watchdog туннеля (на ноутбуке) diff --git a/docs/cli.md b/docs/cli.md index e565493..f6447ce 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -200,8 +200,8 @@ FLAVOR_FALLBACK=true SCAN_POOLS=ru-6,ru-7 DEFAULT_SPOT=true KEEP_FLOATING_IP=false -IDLE_MINUTES=30 -IDLE_GRACE_MINUTES=45 +IDLE_MINUTES=60 +IDLE_GRACE_MINUTES=90 # LOCAL_WATCHDOG_GRACE_MINUTES=10 PULL_OUTPUT=false NOTIFY_READY=true diff --git a/docs/models.md b/docs/models.md index 41528c0..573727b 100644 --- a/docs/models.md +++ b/docs/models.md @@ -87,7 +87,7 @@ ComfyUI в `dlbackend` качается всегда. Речь только о * 8. Первый старт SwarmUI (папки чекпоинтов уже не пустые → установщик не предлагает свой SD; Extensions и Autocompletions уже на месте). 9. Ждать backend Idle, затем вооружить idle-killer. -Качание нескольких GB легко длиннее льготы 45 минут. Поэтому killer не живёт, пока не закончился seed. +Качание нескольких GB легко длиннее льготы 90 минут. Поэтому killer не живёт, пока не закончился seed. Позже тот же код: `gpu-rent seed-models` — докачать новые строки манифеста на уже живой диск (идемпотентно). diff --git a/docs/open-questions.md b/docs/open-questions.md index 5737e52..16825ea 100644 --- a/docs/open-questions.md +++ b/docs/open-questions.md @@ -10,4 +10,4 @@ - App cred с узкими access_rules на Selectel: код fail closed; на spike убедиться, что Keystone принимает rules. - Snapshot attached boot после Idle: время; create from snapshot ок. -Если 45 мин льготы мало на первый Comfy — подними `IDLE_GRACE_MINUTES`, не отключай killer. +Если 90 мин льготы мало на первый Comfy — подними `IDLE_GRACE_MINUTES`, не отключай killer. diff --git a/docs/roadmap.md b/docs/roadmap.md index 498254c..0595fe6 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -65,7 +65,7 @@ - [x] Clone `extensions.yaml` в Extensions / DLNodes до старта UI - [x] Autocomplete: danbooru.csv + Settings.fds; на каждом up — GitHub sha - [x] Civitai seed по манифесту; без токена — дефолт SwarmUI -- [x] systemd idle-killer + application credential; льгота 45 мин; hold-файл; очередь/loading = busy; затем 30 мин пустой очереди; вооружение после seed/start (качалка UI = hold) +- [x] systemd idle-killer + application credential; льгота 90 мин; hold-файл; очередь/loading = busy; затем 60 мин пустой очереди; вооружение после seed/start (качалка UI = hold) - [x] Один snapshot `gpu-rent-boot-ok` после первого backend Idle; следующие create — из snapshot если есть - [x] `gpu-rent hold` / `hold --clear` по SSH - [x] `ready` по HTTP, затем backend Idle diff --git a/docs/setup.md b/docs/setup.md index 413ab8a..7aacbbf 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -273,7 +273,7 @@ copy models.example.yaml models.yaml - **GPU** — пока жив compute. - **Data-диск** — тарифицируется **всегда** после создания. - Preemptible ~**24 ч** → `EXPIRED`; `tunnel` или `up` восстановят. -- Idle-killer: после льготы (~45 мин) + ~30 мин пустой очереди → delete compute. +- Idle-killer: после льготы (~90 мин) + ~60 мин пустой очереди → delete compute. - Цены в OpenStack API нет — смотри панель Selectel. Дальше: чеклист живого прогона [spike-notes.md](spike-notes.md), справочник команд [cli.md](cli.md). diff --git a/docs/spike-notes.md b/docs/spike-notes.md index e1e4427..a6c524c 100644 --- a/docs/spike-notes.md +++ b/docs/spike-notes.md @@ -120,7 +120,7 @@ - Имя GPU-образа в пуле: - Реальные flavor id (не в git): -- Хватает ли `IDLE_GRACE_MINUTES=45`: +- Хватает ли `IDLE_GRACE_MINUTES=90`: - Application credential с узкими access_rules: ок / ошибка (fail closed): - Прочее: diff --git a/env.example b/env.example index 7309651..50369c0 100644 --- a/env.example +++ b/env.example @@ -57,8 +57,8 @@ FLAVOR_FALLBACK=true SCAN_POOLS=ru-6,ru-7 DEFAULT_SPOT=true KEEP_FLOATING_IP=false -IDLE_MINUTES=30 -IDLE_GRACE_MINUTES=45 +IDLE_MINUTES=60 +IDLE_GRACE_MINUTES=90 # Optional local safety net (after: gpu-rent watchdog install) # LOCAL_WATCHDOG_GRACE_MINUTES=10 PULL_OUTPUT=false diff --git a/gpu-rent.vars.example b/gpu-rent.vars.example index 7f15c97..394c46d 100644 --- a/gpu-rent.vars.example +++ b/gpu-rent.vars.example @@ -23,8 +23,8 @@ # LLM_RUNTIME=none # OLLAMA_LOCAL_PORT=17811 # LLAMACPP_LOCAL_PORT=17812 -# IDLE_MINUTES=30 -# IDLE_GRACE_MINUTES=45 +# IDLE_MINUTES=60 +# IDLE_GRACE_MINUTES=90 # LOCAL_WATCHDOG_GRACE_MINUTES=10 # NOTIFY_READY=true # PULL_OUTPUT=false diff --git a/src/gpu_rent/config.py b/src/gpu_rent/config.py index 59d5ca6..5cc76c1 100644 --- a/src/gpu_rent/config.py +++ b/src/gpu_rent/config.py @@ -250,8 +250,8 @@ def load_config(*, require_auth: bool = True) -> Config: scan_pools=(os.environ.get("SCAN_POOLS") or "ru-6,ru-7").strip(), default_spot=_as_bool(os.environ.get("DEFAULT_SPOT"), True), keep_floating_ip=_as_bool(os.environ.get("KEEP_FLOATING_IP"), False), - idle_minutes=_as_int(os.environ.get("IDLE_MINUTES"), 30), - idle_grace_minutes=_as_int(os.environ.get("IDLE_GRACE_MINUTES"), 45), + idle_minutes=_as_int(os.environ.get("IDLE_MINUTES"), 60), + idle_grace_minutes=_as_int(os.environ.get("IDLE_GRACE_MINUTES"), 90), pull_output=_as_bool(os.environ.get("PULL_OUTPUT"), False), notify_ready=_as_bool(os.environ.get("NOTIFY_READY"), True), selectel_api_token=(os.environ.get("SELECTEL_API_TOKEN") or "").strip(), diff --git a/src/gpu_rent/remote/idle_killer.py b/src/gpu_rent/remote/idle_killer.py index 23413c7..5fbf92c 100644 --- a/src/gpu_rent/remote/idle_killer.py +++ b/src/gpu_rent/remote/idle_killer.py @@ -18,7 +18,7 @@ ARMED = DATA / ".gpu-rent-killer-armed" LOG = DATA / ".gpu-rent-killer.log" SERVER_ID_FILE = DATA / ".gpu-rent-server-id" # After this many seconds of continuous Swarm unreachable → treat as idle (don't bill forever). -SWARM_UNREACHABLE_IDLE_SEC = 60 * 60 +SWARM_UNREACHABLE_IDLE_SEC = 2 * 60 * 60 def log(msg: str) -> None: @@ -242,7 +242,7 @@ def main() -> int: now = time.time() grace_from = float(creds.get("grace_from") or 0) - grace_minutes = float(creds.get("grace_minutes") or 45) + grace_minutes = float(creds.get("grace_minutes") or 90) if now < grace_from + grace_minutes * 60: left = int(grace_from + grace_minutes * 60 - now) log(f"grace {left}s left") @@ -269,7 +269,7 @@ def main() -> int: log(f"busy: {llm_detail}") return 0 - idle_minutes = float(creds.get("idle_minutes") or 30) + idle_minutes = float(creds.get("idle_minutes") or 60) since = read_ts(IDLE_SINCE) if since is None: write_ts(IDLE_SINCE, now)