nanobot: 2026-09-14 07:29:02

This commit is contained in:
lachtan
2026-09-14 07:29:02 +02:00
parent bd14485ce3
commit a0ed986ce7
3 changed files with 518 additions and 2 deletions

View File

@@ -0,0 +1,498 @@
# Ollama na nvidia.hell — ucelený report
**Stav k:** 2026-09-13 21:30 (poslední ověřený záznam)
**Pro:** agenta, který na problému bude pokračovat
**Zdroje:** `history.md` (záznamy 2026-09-12 21:10 až 2026-09-13 21:30),
`knowledge.md`, `todo.md`, `done.md`, `explore/negativni-zjisteni.md`
---
## 1. Shrnutí v pěti větách
Ollama na `nvidia.hell` opakovaně shodila celý stroj (load 81 na 4 jádrech,
SSH neprošlo ani banner exchange, 45 minut nedostupnosti). Příčina není jeden
bug, ale **řetěz tří nezávislých mechanismů**: (1) ollama vypíná `mmap` podle
vzorce, který na tomhle stroji **nemůže být nikdy splněn**, takže model teče
do anonymní paměti místo zahoditelné page cache; (2) architektura PLE u
`gemma4` drží 5,9 GiB vah v RAM hostitele bez ohledu na volnou VRAM;
(3) každé přerušení loadu (kill i vlastní timeout scheduleru) **natrvalo
leakne napinovanou host paměť** v nvidia driveru — uvolní ji jen reboot.
Nasazená pojistka je cgroup strop na `ollama.service`; ověřeně drží dostupnost
stroje (240/240 heartbeatů), ale **retest v konečné podobě ještě neproběhl**.
---
## 2. Prostředí
| Položka | Hodnota |
|---|---|
| Stroj | `nvidia.hell` — VM pod Proxmox (`pve.hell`, 192.168.4.47) |
| RAM | původně 11,4 GiB, uživatel **snížil na 9,5 GiB** (viz §5.3) |
| Swap | 32 GB, `vm.swappiness=60` |
| CPU | 4 jádra |
| GPU | NVIDIA RTX 4060 Ti 16 GB (16380 MiB) |
| Ollama | 0.33.2 nativně (ne v kontejneru), unit `/etc/systemd/system/ollama.service` |
| Nejnovější upstream | v0.34.0 (5. 9. 2026) — release notes neřeší scheduler ani mmap |
| Frontendy | OpenWebUI (podman, `:8080`), LibreChat (192.168.4.45), **nanobot.hell (192.168.4.64)** |
| Další služby | `traefik`, `jupyterhub`, `docker`, `nvidia-persistenced`, `zabbix-agent` |
**Klienti jsou důležití:** `nanobot.hell` je skutečný zdroj zátěže — posílá
dávky desítek `POST /api/chat` a `/v1/chat/completions` přes ~10 různých modelů
během minut a drží `qwen3-embedding:0.6b` periodickými `POST /api/embed`.
LibreChat byl v obou incidentech jen **zesilovač** (po 15min timeoutu load
okamžitě zopakoval).
---
## 3. Kauzální řetěz — jak se stroj položí
```
nanobot.hell pošle dávku requestů přes ~10 modelů
[1] ollama rozhoduje "fits alongside existing models" podle VRAM,
ne podle volné RAM → pustí další model i při system_free = 115 MiB
[2] týmž dechem "disabling mmap due to host memory pressure"
(podmínka nemůže být na 9,5GiB stroji nikdy nesplněna)
→ model jde do ANONYMNÍ paměti místo page cache
[3] u gemma4 navíc PLE drží 5901 MiB vah v host bufferu
(do VRAM jde jen 2966 MiB z 16076 volných)
[4] RAM dojde → swap thrashing (pswpin 4512/s), %system 90 %, load 81
→ stroj nedostupný, SSH neprojde
[5] load je přerušen (kill zvenčí NEBO vlastní timeout scheduleru)
→ llama-server umírá uprostřed CUDA init
→ napinovaná host paměť se NEUVOLNÍ → trvalý leak
└──► leak ubere RAM → další load se vejde ještě hůř → smyčka
```
**Klíčové:** body [1] a [2] jdou proti sobě — jedno rozhodnutí říká „vejde se",
druhé v téže vteřině říká „je málo paměti". Bod [5] je ta část, která z jednoho
incidentu udělá degradaci trvající do rebootu.
---
## 4. Ověřená fakta (co platí a čím je to doloženo)
### 4.1 Vypínání mmapu
`sched.go`, `disableMmapForHostPressure`:
```
FreeMemory < modelSize + max(8 GB, TotalMemory/10) → vypni mmap
```
Headroom je **konstanta 7,45 GiB** až do 80 GB RAM. Pro `gemma4`
(`model_size="8.9 GiB"`) je potřeba **16,4 GiB volné RAM**. Stroj má 9,5 GiB
celkem → podmínka je splněná **nepodmíněně, bez ohledu na klienta i na to,
kolik je zrovna volno**.
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 |
**Kontraintuitivní důsledek:** čím prázdnější je karta, tím spíš se mmap vypne —
při těsné VRAM zůstává zapnutý (`sched.go` ř. 1235).
### 4.2 gemma4 / PLE
`gemma4:e4b` (8,95 GiB, `gemma4:latest` je alias téhož blobu) hlásí
`offloaded 43/43 layers to GPU`, ale reálně:
```
| - CUDA0 (RTX 4060 Ti) | 16076 = 15951 + (2966 = 2829 + 29 + 107) + -2842 |
| - Host | 5938 = 5901 + 0 + 37 |
```
Per-Layer Embeddings drží embeddingy na CPU **záměrně**
([HuggingFace blog](https://huggingface.co/blog/gemma3n): „PLE reduces
accelerator memory usage by offloading embeddings to the CPU"). Ollama si
ten CPU buffer započítá do předpovědi `predicted="9.4 GiB"`, jako by šel celý
do VRAM. Na 9,5GiB stroji je 5,9 GiB host bufferu neufinancovatelné —
**gemma4 se sem nevejde a nikdy nevejde**, ať je karta jakkoli prázdná.
### 4.3 Leak napinované paměti (nejzávažnější zjištění)
Každé přerušení loadu llama-serveru uprostřed CUDA inicializace natrvalo ztratí
host paměť napinovanou přes GUP (get_user_pages).
**Nezáleží na tom, kdo proces ukončil.** Doloženo pro obě varianty:
- externí `SIGTERM` od earlyoomu (~15 killů = 9,27 GiB),
- zrušení samotným ollama schedulerem (`Load failed: timed out waiting for
llama-server to start: context canceled` po odpadnutí klienta) = **5,19 GiB
z jednoho zrušení**.
**Diagnostika** (jediné, co leak ukáže):
```bash
# počet napinovaných stránek
awk '/nr_foll_pin_acquired/{a=$2} /nr_foll_pin_released/{r=$2} END{print a-r, "stránek =", (a-r)*4096/1073741824, "GiB"}' /proc/vmstat
# druhý příznak: Active(anon)+Inactive(anon) >> AnonPages
grep -E 'AnonPages|Active\(anon\)|Inactive\(anon\)|MemAvailable' /proc/meminfo
```
**Co leak NEUKÁŽE:** `ps -eo rss` (~250 MB přes všechny procesy),
`nvidia-smi` (2 MiB / 16380 MiB, „No running processes found"),
`systemd-cgtop` (žádná služba nic nedrží), `sar` (nemá pro to sloupec —
proto ve vzorcích z 13:40 nesedělo 9,4 GB do žádné kategorie).
**Co leak neuvolní:**
- `systemctl restart ollama` — `foll_pin` delta identická, navíc paměť
**uteče z cgroup do rodiče** (`memory.current` ollamy spadne na 18 MB,
`system.slice` si 5,9 GiB nese dál) → kontejnerování platí jen do prvního restartu.
- `rmmod nvidia_uvm nvidia_drm nvidia_modeset nvidia` — proběhl čistě
(`lsmod` prázdný), delta **bit za bit stejná** (2 307 318 stránek).
Ověřeno 2026-09-13 20:20. Tím padl dřívější předpoklad, že teardown pomůže.
**Co leak uvolní:** **jen reboot.** Ověřeno 2026-09-13 20:26 —
`MemAvailable` 89 MB → 7,6 GiB, `Inactive(anon)` 5,9 GiB → 0.
Poznámka: nenulová `foll_pin` delta při běžícím modelu je normál
(po rebootu 252 949 stránek = 0,96 GiB pro načtený `qwen3-embedding:0.6b`).
Leak se pozná podle toho, že delta zůstane, když neběží žádný llama-server.
### 4.4 Cgroup pojistka — co funguje
Nasazeno v `/etc/systemd/system/ollama.service.d/override.conf`
(záloha `override.conf.bak-20260913`):
```ini
MemoryMax=6G
MemorySwapMax=0 # nejdůležitější řádek
CPUQuota=200%
CPUWeight=20
# MemoryHigh záměrně NENASTAVENO — viz §5.1
```
Plus `/etc/systemd/system/ssh.service.d/10-oom-protect.conf`:
`OOMScoreAdjust=-900`, `MemoryMin=32M` (ověřeno, že `ssh.socket` má
`Accept=no`, takže listener žije v `ssh.service`).
**Zátěžový test 2026-09-13 16:5517:05** (heartbeat à 2 s, každý úder nové SSH
spojení; spouštěč `curl /api/generate` na `gemma4:latest`):
| Kritérium | Výsledek |
|---|---|
| Dostupnost SSH | **240/240 úderů, 0 výpadků** |
| `MemAvailable` minimum | 3204 MiB (kritérium bylo 2 GiB) |
| `loadavg` max | **3,41** (při incidentu 81) |
| OOM killer v `dmesg` | žádný |
`MemorySwapMax=0` je z toho nejdůležitější — **nedostupnost dělal swap thrash,
ne OOM**. `MemoryMax=` sám o sobě mapuje na `memory.max`, což je strop jen pro
RAM; po jeho dosažení kernel proces nezabije, ale začne ho swapovat.
### 4.5 Rozlišení, proč ollama spadla
```bash
dmesg | grep -i 'oom\|constraint'
```
- `constraint=CONSTRAINT_NONE ... global_oom` → **globální OOM killer**,
pojistka nezasáhla (stroj byl sežraný leakem, ollama se ke svému 6G stropu
vůbec nedostala)
- `constraint=CONSTRAINT_MEMCG` → **cgroup limit**, pojistka zafungovala
Smyčku `Start request repeated too quickly` dělá `Restart=always` +
`RestartSec=30` + `StartLimitBurst=3/300s` z drop-inu — **to je záměr**, ne chyba.
---
## 5. Slepé uličky — co nezkoušet znovu
### 5.1 `MemoryHigh` je past
Nastaveno `MemoryHigh=5G` + `MemoryMax=6G`. gemma4 potřebuje host buffer
5901 MiB → padlo **přesně doprostřed pásma**:
```
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. Pro chování „rychle selhat" se `MemoryHigh` **nesmí nastavit**.
Odstraněno.
### 5.2 earlyoom — zavržen, odinstalován
Nasazen 14:20, do večera pryč. Tři samostatné problémy:
1. **Ve výchozí konfiguraci by nezasáhl nikdy.** Podmínky `-m` a `-s` platí
**současně**. Ze swapu bylo obsazeno 1,4 z 32 GB (~95 % volných), takže
`swap <= 10 %` nemohlo nastat. Man page: „You can use `-s 100` to have
earlyoom effectively ignore swap usage."
2. **SIGKILL práh je polovina zadané.** `-s 100` dá kill až při `swap <= 50 %`
→ nutné psát `-s 100,100`.
3. **Je to zesilovač, ne pojistka.** Killy llama-serveru uprostřed CUDA init
leakují (§4.3). Po ~15 killech chybělo 9,27 GiB, práh `-m 10` se trvale
posunul pod klidovou spotřebu a ollama už nenačetla vůbec nic — každý nový
llama-server umíral už při 300 MiB RSS. **Kladná zpětná vazba.**
**Poučení: proti procesu, který drží GPU kontext, je externí zabíječ horší než
nic.** Totéž se dá čekat od `systemd-oomd` (PSI varianta téhož principu) —
nenasazováno, odvozeno, neověřeno měřením. Balík earlyoom je ve stavu `rc`,
zbývá `apt purge`.
### 5.3 Navýšení RAM neřeší nic
Headroom je konstanta 7,45 GiB do 80 GB RAM → pro gemma4 by mmap zůstal zapnutý
až u ~20GiB VM. Uživatel proto paměť naopak **ubral** z 11,4 na 9,5 GiB.
### 5.4 Konfigurace ollamy nemá páku
- **`OLLAMA_NO_MMAP` neexistuje.** [Issue #4895](https://github.com/ollama/ollama/issues/4895),
[PR #6854](https://github.com/ollama/ollama/pull/6854) nikdy nesloučen
(„upstream changes broke this patch"). V `ollama serve --help` volba pro mmap
není. Jediné, co existuje, je `PARAMETER use_mmap` v Modelfile — a **není
doloženo**, že `true` přebije automatické vypnutí kvůli host memory pressure.
- **Ollama nemá admission control.** Ověřeno z `--help` (v0.33.2): neexistuje
proměnná „odmítni load, když se nevejde do VRAM". 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`. Ollama je navržená tak, že do CPU přeteče vždycky.
- **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 vyhodil oprávněně:
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` nesahá.
- **Zvedat `OLLAMA_LOAD_TIMEOUT` zavrženo** (online se doporučuje jako „turns
a hard failure into a slow success") — u nás by jen prodloužilo thrashing
z 5 na 15 minut.
- **Upgrade ollamy neřeší nic** — v0.34.0 release notes: ChatGPT Desktop,
structured output na Apple Silicon, OpenAI tool search. Nic o scheduleru
ani mmapu.
### 5.5 Proxmox ballooning je pro LLM stroje nevhodný
`pvestatd` (`auto_ballooning`) počítá cíl z **volné paměti hostitele**, ne
z tlaku v guestu — ten určuje jen prioritu ve frontě. `maxchange` je 100 MB
na cyklus à 10 s (~10 MB/s): navýšení o 8 GB trvá ~14 minut, zatímco načtení
modelu 17 s. Během incidentu zůstalo `total` na 7,4 GiB, přestože guest padl
na 136 MB volných. **Řešení: `balloon: 0` a pevná paměť.**
---
## 6. Chybné závěry, které byly cestou opraveny
| Původní závěr | Oprava |
|---|---|
| „Viníkem je LibreChat" | Uživatel reprodukoval zatuhnutí i z `ollama` CLI. LibreChat byl jen zesilovač; spouštěčem je samotný model. |
| „Embedding drží LibreChat" | Drží ho **nanobot.hell (192.168.4.64)**, ne LibreChat (192.168.4.45). |
| „Regresi 0.32.10 způsobil Vulkan" | [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) ji připisuje Vulkanu na iGPU — na nás nesedí (CUDA, diskrétní karta). Náš log uvádí jiný spouštěč (`host memory pressure`), ale ústí do téhož `--load-mode none`. Potvrzuje #18373. |
| „Leakuje jen externí kill" | Leakuje i zrušení vlastním schedulerem — jedno stálo 5,19 GiB. |
| „Leak uvolní teardown nvidia driveru" | `rmmod` neuvolnil ani stránku. **Jen reboot.** |
| „`failed (Result: oom-kill)` = zafungoval cgroup strop" | `constraint=CONSTRAINT_NONE` → globální OOM. Pojistka nezasáhla. |
| „~9,4 GB v `sar` nesedí do žádné kategorie" | Byla to právě ta napinovaná paměť; `sar` pro ni nemá sloupec. |
---
## 7. 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 |
První výskyt `disabling mmap` v journalu nvidia.hell je **2026-06-05** —
předtím ani jednou za 13 měsíců. Jde tedy o regresi, ne o vlastnost od začátku.
---
## 8. Chyby v systemd konfiguraci (obecně použitelné)
- **`StartLimitIntervalSec` / `StartLimitBurst` patří do `[Unit]`, ne `[Service]`** —
tam se tiše ignorují. `RestartSec` naopak do `[Service]`. Property se navíc
jmenuje `RestartUSec` → `systemctl show -p RestartSec` nevrátí nic.
- **`MemoryMax` sám nelimituje swap** → nutné `MemorySwapMax` (§4.4).
- **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á → 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`).
- **⚠ Limity z 12. 9. ze stroje nevysvětleně zmizely.** Zapsány ve 21:10,
ve 21:44 už v `override.conf` nebyly (zůstaly jen `StartLimit*`, `RestartSec`,
`Environment`). Při incidentu 13. 9. proto `systemctl show ollama` hlásil
`MemoryMax=infinity`. **Příčina nikdy nezjištěna.** Proto existuje záloha
`override.conf.bak-20260913` a **kontrola limitů musí být součástí každého ověření**.
- **Překlep v drop-inu:** zakomentovaný řádek `Environment="LLAMA_MAX_LOADED_MODELS=1"`
— správně `OLLAMA_MAX_LOADED_MODELS`, nefungoval by ani po odkomentování.
---
## 9. Ostatní zjištění k ollamě / modelům
### `OLLAMA_KV_CACHE_TYPE=q4_0` rozbíjí modely s head_dim nedělitelným 32
`granite-code` (`n_embd_head_k=80`) padá na
`K cache type q4_0 with block size 32 does not divide n_embd_head_k=80`.
12. 9. kvůli tomu spadl **6× po sobě** (12:08:3612:09:04) a každý pokus přitom
nastartoval llama-server a načetl 1,9 GiB s vypnutým mmapem. Proměnná je
**globální** — nastavit jde jen pro všechny modely naráz.
**Stále nastaveno, neopraveno.**
### Capability `tools` neznamená, že model nástroje použije
Za 13. 9. odešly jen 3 `tools/call`: `gemma4:e4b` (2×) a `glm-5.3:cloud` (1×).
`mistral:latest` dostal ve stejné relaci **stejných 5 nástrojů** jako glm-5.3
a nezavolal ani jeden (job skončil za 4 s textovou odpovědí), přestože
v `ollama show` **má** capability `tools`. Flag říká jen to, že šablona
nástroje podporuje.
Modely **bez** `tools` (nikdy nebudou fungovat): `llama3`, `llama2-uncensored`,
`tinyllama`, `aya`, `phi4`, `phi3.5`, `codellama`, `exaone-deep`,
`deepseek-coder-v2`, `granite-code:8b`.
### `sar` přežije reboot a chybějící vzorek je sám o sobě důkaz
`/var/log/sysstat/saDD` + perzistentní journal umožnily dohledat incident až
po restartu VM. Kolektor `sa1` běží à 10 min z `/etc/cron.d/sysstat`; **když
vzorek ve výpisu chybí, stroj byl v tu chvíli tak zahlcený, že cron nedoběhl** —
tím se dá datovat začátek incidentu (vzorek 12:50 chyběl).
---
## 10. Aktuální stav (po rebootu 2026-09-13 20:26)
```
MemAvailable 7,6 GiB (bylo 89 MB)
MemFree 5,8 GiB
Inactive(anon) 0 (bylo 5,9 GiB)
foll_pin delta 252 949 stránek = 0,96 GiB ← legitimní, drží běžící model
OOM killů od bootu: 0
```
Běží: `ollama`, `nvidia-persistenced`, `traefik`, `jupyterhub`, `docker`, `ssh`.
Cgroup pojistka aktivní a ve správné podobě: `MemoryMax=6G`, `MemorySwapMax=0`,
`MemoryHigh=infinity`, `CPUQuota=200%`, `StartLimitBurst=3/5min`.
---
## 11. Co zbývá udělat
Seřazeno podle priority:
1. **Zastavit dávky z nanobot.hell (192.168.4.64)** — bez toho je leak zpátky
během minut. Zatím neuděláno.
2. **Retest cgroup pojistky bez `MemoryHigh`** — potvrdit, že load selže
v řádu sekund přes cgroup OOM (`memory.events` → `oom_kill > 0`) místo
desetiminutového plazení. **Odblokováno** rebootem. Kritéria z minulého testu:
SSH heartbeat à 2 s bez výpadku, `MemAvailable` > 2 GiB, `loadavg` pod kontrolou,
`dmesg` → `constraint=CONSTRAINT_MEMCG` (ne `CONSTRAINT_NONE`).
3. **Doladit `MemoryMax`** podle naměřeného `memory.peak` z retestu.
4. **Rozhodnout osud gemma4** — `gemma4:latest` / `gemma4:12b` / `gemma4:e4b`
potřebují kvůli PLE ~5,9 GiB host bufferu bez ohledu na volnou VRAM.
Na 9,5GiB stroji se nevejdou nikdy. *Otázka pro uživatele: vyřadit je?*
Jediné skutečné „admission control", které ollama nabízí, je nenabízet
nebezpečné modely.
5. **`OLLAMA_KV_CACHE_TYPE=q4_0`** — buď proměnnou zrušit, nebo `granite-code`
nepoužívat.
6. Drobnosti:
- `apt purge earlyoom` (balík ve stavu `rc`, zbyly `/etc/default/earlyoom`
a `/etc/default/earlyoom.bak-20260913`)
- snížit `--log-verbosity 4` u llama-serveru (journald při incidentu žral
1,9 % CPU, journal zaplevelený)
- opravit `Hostname=Zabbix server` v `/etc/zabbix/zabbix_agentd.conf`
na `nvidia` (agent běží a míří na `zabbix.hell`, ale s defaultním jménem)
- LibreChat: `titleConvo: true` + `titleModel: "current_model"` posílá na týž
model druhý souběžný požadavek (v logu `Title generation timeout`)
- *otázka:* jaký monitoring doinstalovat? `sysstat` na postmortem stačil.
Chybí (a) alerting v reálném čase a (b) hlídač, který zakročí — ale
pozor, „hlídač, který killuje" je právě ta zavržená cesta (§5.2).
---
## 12. Rychlá kuchařka pro triáž
```bash
# 1) Leakuje pinned paměť?
awk '/nr_foll_pin_acquired/{a=$2} /nr_foll_pin_released/{r=$2} \
END{print (a-r), "stránek =", (a-r)*4096/1073741824, "GiB"}' /proc/vmstat
grep -E 'MemAvailable|AnonPages|Active\(anon\)|Inactive\(anon\)' /proc/meminfo
# Active+Inactive(anon) >> AnonPages → leak.
# Když neběží žádný llama-server a delta je nenulová → leak. Řešení: REBOOT.
# 2) Platí vůbec limity? (už jednou zmizely!)
systemctl show ollama -p MemoryMax -p MemorySwapMax -p MemoryHigh -p CPUQuotaPerSecUSec
grep . /sys/fs/cgroup/system.slice/ollama.service/memory.{max,swap.max,high,current,peak}
cat /sys/fs/cgroup/system.slice/ollama.service/memory.events
# 3) Spadla ollama na cgroup stropu, nebo globálně?
dmesg | grep -iE 'oom|constraint'
# CONSTRAINT_MEMCG → pojistka zafungovala
# CONSTRAINT_NONE / global_oom → stroj byl sežraný leakem, pojistka se nedostala ke slovu
# 4) Kdo to spustil?
journalctl -u ollama --since -2h | grep -E 'disabling mmap|fits alongside|Load failed|system_free'
journalctl -u ollama --since -2h | grep -oE '192\.168\.4\.[0-9]+' | sort | uniq -c
# 192.168.4.64 = nanobot.hell (skutečný zdroj), 192.168.4.45 = LibreChat (zesilovač)
# 5) Postmortem po rebootu
sar -r -f /var/log/sysstat/sa$(date +%d) # chybějící vzorek = stroj nestíhal ani cron
sar -q -f /var/log/sysstat/sa$(date +%d) # ldavg
journalctl -b -1 -u ollama
```
---
## 13. Zálohy a rollback na stroji
| Co | Kde |
|---|---|
| Unit + skripty před zásahem 12. 9. | `~/backup/ollama-20260912-2108/` |
| Drop-in před cgroup pojistkou | `/etc/systemd/system/ollama.service.d/override.conf.bak-20260913` |
| earlyoom config | `/etc/default/earlyoom.bak-20260913` |
| SSH OOM ochrana (přidáno) | `/etc/systemd/system/ssh.service.d/10-oom-protect.conf` |
| Upgrade skripty | `~/bin/upgrade-ollama.sh`, `~/bin/upgrade-openwebui.sh` |
```bash
# rollback cgroup pojistky
sudo cp -a /etc/systemd/system/ollama.service.d/override.conf.bak-20260913 \
/etc/systemd/system/ollama.service.d/override.conf
sudo rm -f /etc/systemd/system/ssh.service.d/10-oom-protect.conf
sudo systemctl daemon-reload && sudo systemctl restart ollama ssh
# návrat driveru po rmmod (kdyby to někdo zkusil znovu — nemá to smysl)
sudo modprobe nvidia && sudo modprobe nvidia_uvm && sudo modprobe nvidia_modeset
sudo systemctl start nvidia-persistenced
```
**Pozn.:** `~/bin/nvidia-reload` na stroji existuje, ale **nemá smysl** —
postaven na předpokladu, že `rmmod` leak uvolní, což bylo vyvráceno (§4.3).
---
## 14. Plné záznamy
Chronologicky v `history.md`:
| Záznam | Obsah |
|---|---|
| 2026-09-12 21:10 | Paměťové limity přes systemd drop-in (limity pak záhadně zmizely) |
| 2026-09-13 12:05 | LibreChat: web search bez klíčů + Python přes MCP |
| 2026-09-13 13:40 | Průzkum: nvidia.hell zahlcená na 45 minut (load 81) |
| 2026-09-13 14:00 | Oprava diagnózy: viník není LibreChat, ale práh pro mmap |
| 2026-09-13 14:20 | Rešerše upstreamu + nasazení earlyoom |
| 2026-09-13 15:45 | Ollama nefunkční, 9,3 GiB leaklé pinned paměti |
| 2026-09-13 17:10 | Cgroup pojistka nasazena a otestována, `MemoryHigh` past |
| 2026-09-13 20:20 | `rmmod` nvidia leak NEuvolnil, leak vyrostl na 8,8 GiB |
| 2026-09-13 21:30 | Reboot uvolnil leak, stroj zdravý |
Další: `knowledge.md` (ověřená fakta), `todo.md` (otevřené body),
`explore/negativni-zjisteni.md` (podrobný soupis negativních zjištění).

View File

@@ -36,3 +36,21 @@ Shrnutí obsahu:
**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). **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. 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.
- 2026-09-14: Záznam druhého reportu od Claude Code: „Ollama na nvidia.hell — ucelený report" (stav k 2026-09-13 21:30). Uložen verbatim jako artifact: `projects/devops/artifacts/2026-09-13_ollama-nvidia-full-report.md`. Je to nadstavba předchozího „Negativní zjištění" reportu (uložený den předtím) — obsahuje kauzální řetěz, ověřená fakta, aktuální stav a todo list.
**Kauzální řetěz (5 kroků):** (1) ollama rozhoduje „fits alongside existing models" podle VRAM, ne volné RAM → pustí model i při system_free 115 MiB; (2) týž dechem vypne mmap (podmínka na 9,5 GiB stroji nesplnitelná nikdy) → model jde do anonymní paměti místo page cache; (3) gemma4 PLE drží 5,9 GiB host bufferu navíc; (4) RAM dojde → swap thrashing (pswpin 4512/s, %system 90 %, load 81, SSH nedostupné 45 min); (5) přerušený load → leak napinované paměti. Body [1] a [2] si odporují v téže vteřině.
**Nová fakta oproti předchozímu reportu:**
- **correction: rmmod nvidia driveru leak NEUVOLNÍ** — ověřeno 20:20, proběhl čistě, foll_pin delta bit za bit stejná (2 307 318 stránek). Moje předchozí shrnutí říkalo „uvolní ho jen driver teardown nebo reboot" — platí **jen reboot** (ověřeno 20:26: MemAvailable 89 MB → 7,6 GiB). Skript `~/bin/nvidia-reload` na stroji je tedy bezcenný.
- **Cgroup pojistka funguje a je ověřená**: `MemoryMax=6G`, `MemorySwapMax=0` (klíčový řádek — nedostupnost dělal swap thrash, ne OOM; MemoryMax sám swap nelimituje), `CPUQuota=200%`, `CPUWeight=20`, MemoryHigh záměrně vynechán. Plus SSH ochrana (`OOMScoreAdjust=-900`, `MemoryMin=32M` v ssh.service.d/10-oom-protect.conf). Zátěžový test 16:5517:05 (gemma4 load, SSH heartbeat à 2 s): 240/240 úderů, 0 výpadků, load max 3,41 (vs 81 při incidentu), MemAvailable min 3204 MiB.
- **Diagnostika OOM**: `dmesg` rozlišuje `constraint=CONSTRAINT_MEMCG` (pojistka zafungovala) vs `CONSTRAINT_NONE/global_oom` (stroj sežraný leakem, pojistka se ke slovu nedostala). `failed (Result: oom-kill)` tedy neznamená automaticky zafungovaný strop.
- **První výskyt `disabling mmap` v journalu je 2026-06-05** — předtím 13 měsíců čisto. Jde o regresi, ne stávající vlastnost.
- **`sar` chybějící vzorek = sám o sobě důkaz** (stroj nestíhal ani cron à 10 min) — datování začátku incidentu.
- **Zavržené nově:** zvedání `OLLAMA_LOAD_TIMEOUT` („turns a hard failure into a slow success" — jen by prodloužilo thrashing); Proxmox ballooning → řešení `balloon: 0` + pevná paměť (pvestatd počítá cíl z volné paměti hostitele, ~10 MB/s vs 17 s load modelu).
- **Capability `tools` ≠ model nástroje použije**: mistral:latest dostal stejných 5 nástrojů jako glm-5.3, nezavolal ani jeden; flag říká jen, že šablona podporuje tools. Seznam modelů bez `tools` capability (nikdy nebudou fungovat): llama3, llama2-uncensored, tinyllama, aya, phi4, phi3.5, codellama, exaone-deep, deepseek-coder-v2, granite-code:8b.
- **Prostředí:** VM pod pve.hell (192.168.4.47), RAM snížena 11,4 → 9,5 GiB, swap 32 GB swappiness=60, 4 jádra, RTX 4060 Ti 16 GB, ollama 0.33.2 nativně. Skutečný zdroj zátěže = nanobot.hell (192.168.4.64), LibreChat jen zesilovač.
- **Kuchařka pro triáž** (awk foll_pin delta, kontrola cgroup limitů — už jednou zmizely, constraint grep, journalctl IP grep, sar postmortem) + **zálohy a rollback** (override.conf.bak-20260913, ~/backup/ollama-20260912-2108/, upgrade skripty).
**Otevřené body (prioritně, z §11):** (1) zastavit dávky z nanobot.hell — bez toho leak zpátky během minut; (2) retest cgroup pojistky bez MemoryHigh (odblokováno rebootem, kritéria: heartbeat bez výpadku, MemAvailable > 2 GiB, constraint=MEMCG); (3) doladit MemoryMax podle memory.peak z retestu; (4) rozhodnout osud gemma4 (PLE ~5,9 GiB host bufferu, na 9,5 GiB stroji nikdy); (5) OLLAMA_KV_CACHE_TYPE=q4_0 zrušit nebo nepoužívat granite-code; (6) drobnosti: apt purge earlyoom, log-verbosity 4, zabbix Hostname, LibreChat titleConvo, otázka monitoringu (hlídač co killuje = zavržená cesta).
**Stav po rebootu 20:26:** stroj zdravý (MemAvailable 7,6 GiB, 0 OOM killů), pojistka aktivní ve správné podobě.

View File

@@ -7,9 +7,9 @@ timestamp: draft
## Kde to je ## Kde to je
- Projekt založen jako volný prostor pro admin/root poznámky o infrastruktuře a provozu. - 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. - 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). - Ollama na nvidia.hell: po incidentech 12.13. 9. 2026 zaevidován root cause pádů — kauzální řetěz: ollama rozhoduje load podle VRAM ne volné RAM + vypíná mmap (podmínka na 9,5 GiB stroji nesplnitelná nikdy, regrese od 2026-06-05) + PLE host buffer u gemma4 + přerušený load leakuje napinovanou host paměť (neviditelná pro ps/nvidia-smi/cgtop, detekce jen `nr_foll_pin` delta v /proc/vmstat), uvolní **jen reboot** (rmmod driveru ověřeně NE). Cgroup pojistka (`MemoryMax=6G`, `MemorySwapMax=0`, bez MemoryHigh) ověřena zátěžovým testem: 240/240 SSH heartbeatů, load 3,41 vs 81 při incidentu. Skutečný zdroj zátěže = nanobot.hell (dávky přes ~10 modelů + embedding), LibreChat jen zesilovač. Reporty v `artifacts/2026-09-13_ollama-nvidia-full-report.md` (ucelený, s kuchařkou pro triáž) a `artifacts/2026-09-13_ollama-nvidia-negative-findings.md` (negativní zjištění), 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ů, OLLAMA_LOAD_TIMEOUT, upgrade ollamy, mmap override (neexistuje), ballooning (`balloon: 0` + pevná paměť), rmmod jako remedy.
## Co dál ## 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). - 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. - Ollama open body dle priority (report §11): (1) zastavit dávky z nanobot.hell — bez toho leak zpátky během minut; (2) retest cgroup pojistky bez MemoryHigh (odblokováno rebootem; kritéria: heartbeat bez výpadku, MemAvailable > 2 GiB, dmesg constraint=MEMCG); (3) doladit MemoryMax podle memory.peak; (4) rozhodnout osud gemma4 (PLE ~5,9 GiB host bufferu, na 9,5 GiB stroji nikdy); (5) `OLLAMA_KV_CACHE_TYPE=q4_0` zrušit nebo nepoužívat granite-code; (6) drobnosti: `apt purge` earlyoom (rc), llama-server `--log-verbosity 4`, zabbix `Hostname=Zabbix server` → nvidia, LibreChat titleConvo duplicitní requesty, otázka real-time monitoringu (hlídač co killuje = zavržená cesta).
- Uživatel bude psát poznámky; podle obsahu doladit strukturu projektu. - Uživatel bude psát poznámky; podle obsahu doladit strukturu projektu.