nanobot: 2026-09-14 07:24:46

This commit is contained in:
lachtan
2026-09-14 07:24:46 +02:00
parent 5e98beca1f
commit bd14485ce3
7 changed files with 569 additions and 150 deletions

View File

@@ -0,0 +1,278 @@
# Negativní zjištění — nvidia.hell / ollama
Co selhalo, co nefunguje a co jsme zkusili marně. Sesbíráno z incidentů
12.13. 9. 2026. Plné záznamy jsou v [history.md](history.md), ověřená
pozitivní fakta v [knowledge.md](knowledge.md).
Rozsah: jen stroj nvidia.hell a ollama. Slepé uličky z PVE migrace tu nejsou —
ty jsou v [knowledge.md](knowledge.md).
---
## 1. Pojistky, které selhaly
### earlyoom jako ochrana ollamy — zavrženo, odinstalováno
Nasazen 13. 9. ve 14:20, do večera odinstalován. Killoval `llama-server`
uprostřed CUDA inicializace a nvidia driver při tom natrvalo ztratil
napinovanou host paměť. Po ~15 killech chybělo **9,27 GiB** a ollama nenačetla
vůbec nic.
Tím vznikla kladná zpětná vazba: leak ubere RAM → práh `-m 10` je blíž →
earlyoom zabíjí dřív → další leak. Nakonec umíral každý nový `llama-server`
už při 300 MiB RSS.
**Poučení:** proti procesu, který drží GPU kontext, je externí zabíječ horší
než nic. Náhradou je cgroup strop, který nenechá tlak vzniknout.
→ [history.md](history.md) 2026-09-13 15:45
### earlyoom ve výchozí konfiguraci by nezasáhl nikdy
Balík byl na stroji nainstalovaný a běžel už před incidentem, jen ve výchozím
`-m 10 -s 10`. earlyoom zabíjí **jen když jsou obě podmínky splněné současně**.
Ze swapu bylo obsazeno 1,4 z 32 GB, tedy ~95 % volných — podmínka
`swap <= 10 %` nemohla nastat. Běžící earlyoom tedy nebyl žádná ochrana.
### earlyoom odvozuje SIGKILL práh jako polovinu zadaného
První pokus s `-s 100` dal SIGKILL práh `swap <= 50 %`, takže při 95 % volného
swapu by eskalace nikdy nenastala. Musí se psát `-s 100,100`.
### MemoryHigh mezi spotřebou a MemoryMax = past
Nastaveno `MemoryHigh=5G` + `MemoryMax=6G`. gemma4 potřebuje host buffer
**5901 MiB**, což padlo přesně doprostřed. Výsledek při testu 13. 9. 17:05:
```
memory.events: high 84358 max 0 oom 0 oom_kill 0
memory.peak: 5,46 GiB
```
Cgroup 84 tisíckrát reclaimovala, proces se plazil, tvrdý strop nezasáhl ani
jednou a load **visel 600 s bez jediné chybové odpovědi**. Ani neselhal, ani
neproběhl.
**Poučení:** když má konfigurace „rychle selhat", `MemoryHigh` se nesmí
nastavit — ať se narazí rovnou do `MemoryMax`. Odstraněno.
→ [history.md](history.md) 2026-09-13 17:10
### systemd-oomd — nepoužito
Na stroji není nainstalovaný. Nenasazovali jsme ho: je to PSI varianta téhož
principu jako earlyoom, tedy SIGKILL zvenčí, takže se dá čekat týž leak.
Neověřeno měřením, jen odvozeno.
---
## 2. Slepé uličky v konfiguraci ollamy
### Ollama nemá admission control
Ověřeno z `ollama serve --help` (v0.33.2): **neexistuje proměnná typu
„odmítni load, když se nevejde do VRAM"**. Ollama je navržená tak, že přeteče
do CPU vždycky. K dispozici je jen `OLLAMA_MAX_LOADED_MODELS`,
`OLLAMA_MAX_QUEUE`, `OLLAMA_NUM_PARALLEL`, `OLLAMA_GPU_OVERHEAD`,
`OLLAMA_CONTEXT_LENGTH`, `LLAMA_ARG_FIT_TARGET`, `OLLAMA_LOAD_TIMEOUT`
nic z toho není admission control.
Jediné skutečné odmítnutí je nenabídat nebezpečné modely.
### `OLLAMA_NO_MMAP` neexistuje
Žádost o globální řízení mmapu je [#4895](https://github.com/ollama/ollama/issues/4895),
[PR #6854](https://github.com/ollama/ollama/pull/6854) nebyl nikdy sloučen
(„upstream changes broke this patch"). Lidé to žádají ještě 6/2026.
Vypnutý mmap se tedy konfigurací obejít nedá.
### Navýšení RAM problém neřeší
Podmínka je `FreeMemory < modelSize + max(8 GB, TotalMemory/10)`. Headroom je
tedy **konstanta 7,5 GiB** až do 80 GB RAM. Pro gemma4 (8,9 GiB) je potřeba
16,4 GiB *volné* RAM, takže mmap by zůstal zapnutý až u ~20GiB VM.
Důkaz z journalu — tři loady při zcela různé volné paměti, všechny tři
`disabling mmap ... headroom="7.5 GiB"`:
| čas | `system_free` |
|---|---|
| 12:09:20 | 8,4 GiB |
| 12:44:50 | 3,4 GiB |
| 13:00:03 | 115,1 MiB |
Volná paměť nikdy nehrála roli. Uživatel proto paměť naopak **ubral**
z 11,4 na 9,5 GiB.
### Omezování počtu modelů — zavrženo
`OLLAMA_MAX_LOADED_MODELS=1` + `NUM_PARALLEL=1` + `MAX_QUEUE=8` byly v plánu
a uživatel je oprávněně vyhodil: stroj shodila **hostitelská RAM, ne VRAM**
(karta má 16 GB volných), a 49 requestů z nanobotu nepoložilo stroj frontou,
ale sekvencí loadů — na což `MAX_QUEUE` vůbec nesahá. Byly to škrty
bez vazby na příčinu, které by degradovaly běžný provoz.
### Upgrade ollamy problém neřeší
Nainstalovaná 0.33.2, nejnovější v0.34.0 (5. 9. 2026). Release notes obsahují
jen ChatGPT Desktop, structured output na Apple Silicon a OpenAI tool search —
**nic o scheduleru ani mmapu**.
### `OLLAMA_KV_CACHE_TYPE=q4_0` rozbíjí modely
Proměnná je globální a shodí modely s `n_embd_head_k=80`. `granite-code` kvůli
ní 12. 9. spadl **6× po sobě** na `K cache type q4_0 with block size 32 does
not divide n_embd_head_k=80` — a každý pokus přitom nastartoval llama-server
a načetl 1,9 GiB s vypnutým mmapem. Stále nastaveno, neopraveno.
### gemma4 se na tenhle stroj nevejde a nikdy nevejde
Není to otázka velikosti modelu. Architektura Per-Layer Embeddings drží
embeddingy na CPU **záměrně**:
```
| - CUDA0 (RTX 4060 Ti) | 16076 = 15951 + (2966 = 2829 + 29 + 107) + -2842 |
| - Host | 5938 = 5901 + 0 + 37 |
```
Do VRAM jde 2966 MiB z 16076 volných, zatímco host drží 5901 MiB. Kontraintuitivní
důsledek: **čím prázdnější karta, tím spíš se mmap vypne** — při těsné VRAM
zůstává zapnutý. Ollama si navíc CPU buffer započítá do předpovědi
`predicted="9.4 GiB"` jako by šel celý do VRAM.
---
## 3. Chyby v systemd konfiguraci
### `StartLimitIntervalSec` / `StartLimitBurst` v `[Service]` se tiše ignorují
Patří do `[Unit]`. `RestartSec` naopak do `[Service]`. Property se navíc
jmenuje `RestartUSec``systemctl show -p RestartSec` nevrátí nic.
### `MemoryMax` sám o sobě nelimituje swap
Mapuje na `memory.max`, což je strop **jen pro RAM**. Po jeho dosažení kernel
proces nezabije, ale začne ho swapovat. Se swapem 32 GB to znamená thrashing
místo rychlého OOM killu. Tvrdý strop vznikne až s `MemorySwapMax`.
### Instalátor ollamy přepisuje unit soubor
`install.sh` (ř. 215) bezpodmínečně přepíše `/etc/systemd/system/ollama.service`
přes `tee`. Do `ollama.service.d/` nesahá, takže vlastní nastavení patří
do drop-inu.
Zavrženo: držet kopii unitu a po upgradu ji kopírovat zpět — konzervuje
i upstream řádky (`ExecStart`, `User`, `PATH`), takže upstream změna se ztratí.
### Limity z 12. 9. ze stroje nevysvětleně zmizely
Zapsány v 21:10, v 21:44 už v `override.conf` nebyly (zůstaly jen
`StartLimit*`, `RestartSec` a `Environment`). Při incidentu 13. 9. proto
`systemctl show ollama` hlásil `MemoryMax=infinity`. **Příčina zmizení
nebyla nikdy zjištěna.** Proto teď existuje záloha
`override.conf.bak-20260913` a kontrola limitů je součástí ověření.
### Překlep `LLAMA_MAX_LOADED_MODELS`
V drop-inu je zakomentovaný řádek `Environment="LLAMA_MAX_LOADED_MODELS=1"`.
Proměnná se jmenuje `OLLAMA_MAX_LOADED_MODELS` — nefungovala by ani po
odkomentování.
---
## 4. Co nástroje neukážou
### Napinovanou paměť neukáže `ps`, `nvidia-smi` ani `systemd-cgtop`
Při leaku 9,27 GiB hlásily:
- `ps -eo rss` přes všechny procesy dohromady ~250 MB
- `nvidia-smi`: 2 MiB / 16380 MiB, **No running processes found**
- `systemd-cgtop`: žádná služba nic nedrží
- `/proc/meminfo`: `AnonPages` 135 MiB, ale `Active(anon)+Inactive(anon)` 9,4 GiB
Jediné, co to ukáže, je rozdíl `nr_foll_pin_acquired nr_foll_pin_released`
ve `/proc/vmstat`. Na to je teď skript `~/bin/nvidia-reload` na nvidia.hell.
### Nedopočet paměti v `sar` z 13. 9. byl tentýž leak
Záznam z 13:40 skončil otevřeným bodem: `kbmemused` 10,6 GB proti `kbanonpg`
54126 MB, `kbcached` 975 MB, `kbslab` 187 MB — ~9,4 GB nesedělo do žádné
kategorie a po rebootu to nešlo dovyšetřit. **Vysvětleno až v 15:45:** byla
to právě ta napinovaná paměť. `sar` pro ni nemá sloupec.
### Restart ollamy leak neuvolní a vystrčí ho z cgroup
Během incidentu je leak účtovaný cgroup ollamy (`memory.current` 5,59 GiB
při `anon` jen 15,9 MB), takže ho `MemoryMax` drží. Po `systemctl restart
ollama` je `foll_pin` delta **identická**, ale `memory.current` spadne
na 18 MB a paměť si nese `system.slice`.
Kontejnerování tedy platí jen do prvního restartu; pak leak uteče ze stropu
a trvale ubere stroji RAM. Uvolní ho až teardown nvidia driveru nebo reboot.
### Proxmox ballooning je pro LLM stroje nevhodný
`pvestatd` (`auto_ballooning`) počítá cíl z **volné paměti hostitele**, ne
z tlaku v guestu. `maxchange` je 100 MB na cyklus á 10 s, tedy ~10 MB/s:
navýšení o 8 GB trvá ~14 minut, zatímco načtení modelu 17 s. Během OOM
incidentu zůstalo `total` na 7,4 GiB, přestože guest padl na 136 MB volných.
---
## 5. Chybné závěry, které jsme museli opravit
### „Viníkem je LibreChat" — ne
První diagnóza (13:40) označila LibreChat za spouštěč. Uživatel zatuhnutí
reprodukoval i z `ollama` CLI, čímž závěr padl. LibreChat byl jen zesilovač:
po 15minutovém timeoutu load okamžitě zopakoval při 115 MiB volných.
Spouštěčem je samotný model.
### „Embedding drží LibreChat" — ne
`qwen3-embedding:0.6b` drží **nanobot.hell (192.168.4.64)**, ne LibreChat
(192.168.4.45). Periodické `POST /api/embed`. Nanobot je zároveň zdrojem
dávek desítek requestů přes ~10 různých modelů během minut.
### „Regresi 0.32.10 způsobil Vulkan" — na nás nesedí
[Rozbor na dev.to](https://dev.to/milkyway008/ollama-model-loads-time-out-after-the-03210-upgrade-the-load-mode-change-and-the-fix-25m)
připisuje regresi Vulkanu na integrovaných GPU. Máme CUDA a diskrétní kartu.
Náš log uvádí jiný spouštěč (`host memory pressure`), ale ústí do téhož
`--load-mode none`. Že to není jen Vulkan, potvrzuje
[#18373](https://github.com/ollama/ollama/issues/18373).
### „Leakuje jen externí kill" — ne
Leak vznikne i když load zruší **sám ollama scheduler**
(`Load failed: timed out waiting for llama-server to start: context canceled`
po odpadnutí klienta). Jedno takové zrušení stálo 5,19 GiB. Nezáleží tedy
na tom, kdo `llama-server` ukončí — záleží na tom, že byl ukončen uprostřed
loadu.
---
## 6. Upstream — nahlášené a neopravené
| Issue | Co říká | Stav |
|---|---|---|
| [#18373](https://github.com/ollama/ollama/issues/18373) | Regrese načítání: 0.33.3 load 2m34s vs. 0.23.4 28s, SSD 600 MB/s místo 3 GB/s. Explicitně „all models", hlášeno i na NVIDII. | otevřené, bez reakce maintainerů |
| [#10104](https://github.com/ollama/ollama/issues/10104) | 200 GB RAM, 80 GB VRAM, ollama sama nasadí `--no-mmap` a load selže. | zavřené bez řešení |
| [#10341](https://github.com/ollama/ollama/issues/10341) | gemma plní RAM navzdory volné VRAM, **na RTX 4060 Ti 16 GB** — stejná karta. | duplikát #10040 |
| [#8654](https://github.com/ollama/ollama/issues/8654) | „Available memory check should be disabled when mmap is in use" | otevřené od 1/2025 |
| [#4895](https://github.com/ollama/ollama/issues/4895) + [PR #6854](https://github.com/ollama/ollama/pull/6854) | Žádost o globální řízení mmapu. | PR nesloučen |
Námitka uživatele, že by tohle muselo trápit spoustu lidí, byla správná —
jen míří opačným směrem: problém je široce hlášený a upstream ho neřeší.
---
## 7. Drobnosti k opravě
- `zabbix-agent` běží a míří na `zabbix.hell`, ale má `Hostname=Zabbix server`
(defaultní hodnota) — stroj se nehlásí jako `nvidia`.
- `llama-server` běží s `--log-verbosity 4`; journald kvůli tomu při incidentu
žral 1,9 % CPU a journal je zaplevelený.
- LibreChat `titleConvo: true` + `titleModel: "current_model"` posílá na týž
model druhý souběžný požadavek (v logu `Title generation timeout`).
- Balík `earlyoom` je ve stavu `rc` — zbývá `apt purge`, na disku jsou
`/etc/default/earlyoom` a `/etc/default/earlyoom.bak-20260913`.

View File

@@ -17,3 +17,22 @@ Závěry nasazení:
- Alternativa: běží-li Docker VM jako čistý AI stack (LibreChat + interpreter, žádná produkční data), je jeden host logický celek. Na obecném provozním Docker hostu raději dedikovaná malá VM (1.5-2 GB RAM).
- Rootless podman nefunkční out-of-the-box (user namespace v user namespace, cgroup delegace) — projekt to netestuje; rootful podman/quadlet OK.
- Kompromis vs oficiální codeapi: ta řeší stejný problém microVM režimem (libkrun), ale stojí 5 komponent + Redis + MinIO.
- 2026-09-14: Záznam reportu od Claude Code (uživatel ho přinesl 2026-09-13): „Negativní zjištění — nvidia.hell / ollama" — co selhalo a co je slepá ulička z incidentů 12.13. 9. 2026. Plný report uložen verbatim jako artifact: `projects/devops/artifacts/2026-09-13_ollama-nvidia-negative-findings.md` (report odkazuje na history.md a knowledge.md na stroji, ty v workspace nejsou — jen v artifactu).
Shrnutí obsahu:
**Pojistky, které selhaly:** earlyoom zavržen a odinstalován — killuje llama-server uprostřed CUDA initu, čímž nvidia driver natrvalo ztratí napinovanou host paměť (po ~15 killech 9,27 GiB, kladná zpětná vazba: méně RAM → dřívější killy). Výchozí earlyoom konfigurace by nezasáhla nikdy (obě podmínky mem+swap musí platit současně); SIGKILL práh je polovina zadané hodnoty, musí se psát `-s 100,100`. MemoryHigh mezi spotřebou a MemoryMax = past (gemma4 host buffer 5901 MiB padl doprostřed → 84k reclaimů, load visel 600 s bez chyby) — při „rychlém selhání" se MemoryHigh nesmí nastavit. systemd-oomd nepoužit (PSI varianta earlyoomu, čekali by týž leak).
**Slepé uličky v konfiguraci ollamy:** žádný admission control v 0.33.2 (přeteče do CPU vždycky); `OLLAMA_NO_MMAP` neexistuje (issue #4895, PR #6854 nesloučen); navýšení RAM neřeší nic — podmínka mmap disable je `FreeMemory < modelSize + max(8GB, Total/10)`, headroom konstanta 7,5 GiB, potvrzeno 3 loady při různé volné paměti (uživatel RAM naopak ubral z 11,4 na 9,5 GiB); limitování počtu modelů vyhozeno (stroj shodila host RAM, ne VRAM, a MAX_QUEUE nesahá na sekvenci loadů); upgrade na 0.34.0 nic řeší; `OLLAMA_KV_CACHE_TYPE=q4_0` globálně rozbíjí modely s `n_embd_head_k=80` (granite-code padl 6×, stále nastaveno, neopraveno); gemma4 se na stroj nevejde nikdy (Per-Layer Embeddings drží embeddingy na CPU záměrně, host drží 5901 MiB i při 16 GB volné VRAM; kontraintuitivně: čím prázdnější karta, tím spíš se mmap vypne).
**Chyby v systemd konfiguraci:** StartLimit* patří do `[Unit]` (v `[Service]` se tiše ignorují); `systemctl show` property je `RestartUSec`; MemoryMax nelimituje swap → s 32 GB swapu thrashing místo OOM killu, tvrdý strop až MemorySwapMax; instalátor ollamy bezpodmínečně přepisuje unit soubor (vlastní nastavení do drop-inu, ne kopírování unitu); limity z 12. 9. z override.conf nevysvětleně zmizely (21:10 zapsány, 21:44 pryč) — příčina nezjištěna, proto záloha override.conf.bak-20260913; v drop-inu překlep `LLAMA_MAX_LOADED_MODELS` (má být OLLAMA_).
**Co nástroje neukážou:** napinovanou paměť nevidí ps/nvidia-smi/systemd-cgtop/proc-meminfo (AnonPages 135 MiB, ale anon sum 9,4 GiB) — jediný indikátor je `nr_foll_pin_acquired nr_foll_pin_released` v /proc/vmstat (skript ~/bin/nvidia-reload na nvidia.hell); sar dopad „unaccounted" paměti z 13:40 vysvětlen jako týž leak; restart ollamy leak neuvolní — paměť uteče z cgroup do system.slice, uvolní jen driver teardown/reboot; Proxmox ballooning nevhodný pro LLM stroje (počítá cíl z volné paměti hostitele, ~10 MB/s navýšení vs 17 s load modelu).
**Opravené chybné závěry:** spouštěčem nebyl LibreChat (jen zesilovač — retry po timeoutu), ale samotný model; embedding drží nanobot.hell (192.168.4.64), ne LibreChat — nanobot je zdroj dávek desítek requestů přes ~10 modelů; regrese 0.32.10 není jen Vulkan na iGPU (my CUDA + diskrétní karta, jiný spouštěč, stejný `--load-mode none`, potvrzuje #18373); leak vzniká i při zrušení loadu vlastním schedulerem po odpadnutí klienta (5,19 GiB) — nezáleží na tom, kdo llama-server ukončí, ale že to bylo uprostřed loadu.
**Upstream (otevřené/neopravené):** #18373 load regrese (2m34s vs 28s), #10104 zavřen bez řešení, #10341 gemma RAM na RTX 4060 Ti 16 GB (stejná karta, duplikát #10040), #8654 memory check vs mmap, #4895+PR#6854 mmap řízení. Problém široce hlášený, upstream neřeší.
**Drobnosti k opravě (otevřené):** zabbix-agent má defaultní `Hostname=Zabbix server` (má být nvidia); llama-server `--log-verbosity 4` (journald žral 1,9 % CPU, zaplevelený journal); LibreChat titleConvo posílá druhý souběžný požadavek na týž model; earlyoom ve stavu `rc` — zbývá `apt purge` (na disku /etc/default/earlyoom a .bak).
Koresponduje s dřívějším zjištěním z projektu ai (2026-09-13): Ollama na nvidia.hell v praxi nepoužitelná, memory watchdog zabíjí llama-server. Tenhle report dodává root cause: kill uprostřed CUDA loadu → leak napinované paměti, kterou neukáží standardní nástroje.

View File

@@ -7,7 +7,9 @@ timestamp: draft
## Kde to je
- Projekt založen jako volný prostor pro admin/root poznámky o infrastruktuře a provozu.
- LibreChat: běží jako podman kontejnery; jako Code Interpreter sandbox vybrán LibreCodeInterpreter (nsjail, 3 kontejnery). Research hotový (2026-09-13), rozhodnutí o nasazení (sdílená Docker VM vs dedikovaná Proxmox VM) ještě nepadlo.
- Ollama na nvidia.hell: po incidentech 12.13. 9. 2026 zaevidován root cause pádů — kill llama-serveru uprostřed CUDA loadu způsobí leak napinované host paměti (neviditelný pro ps/nvidia-smi/cgtop, detekce jen přes `nr_foll_pin` delta v /proc/vmstat), uvolní ho jen driver teardown/reboot. Report „Negativní zjištění" uložen v `artifacts/2026-09-13_ollama-nvidia-negative-findings.md`, shrnutí v memory.md 2026-09-14. Zavržené cesty: earlyoom (i jakákoli externí kill varianta), MemoryHigh pod MemoryMax, navýšení RAM (headroom konstanta 7,5 GiB), limit počtu modelů, upgrade ollamy, mmap override (neexistuje).
## Co dál
- Rozhodnout umístění LibreCodeInterpreter (AI stack VM vs dedikovaná VM) a nasadit — viz memory.md 2026-09-13 pro capability požadavky (SYS_ADMIN, NET_ADMIN, apparmor:unconfined).
- Otevřené drobnosti z ollama reportu: `OLLAMA_KV_CACHE_TYPE=q4_0` stále nastaveno a rozbíjí granite-code; zabbix-agent `Hostname=Zabbix server` (má být nvidia); llama-server `--log-verbosity 4` → zaplevelený journal; earlyoom ve stavu `rc``apt purge`; LibreChat titleConvo duplicitní souběžné requesty.
- Uživatel bude psát poznámky; podle obsahu doladit strukturu projektu.