Files
nanobot-runtime/projects/devops/artifacts/2026-09-13_ollama-nvidia-full-report.md
2026-09-14 07:29:02 +02:00

498 lines
23 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.
# 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í).