nanobot: 2026-09-14 07:24:46
This commit is contained in:
@@ -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`
|
||||
54–126 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`.
|
||||
Reference in New Issue
Block a user