12 KiB
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, ověřená pozitivní fakta v knowledge.md.
Rozsah: jen stroj nvidia.hell a ollama. Slepé uličky z PVE migrace tu nejsou — ty jsou v 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 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 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, PR #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 rsspřes všechny procesy dohromady ~250 MBnvidia-smi: 2 MiB / 16380 MiB, No running processes foundsystemd-cgtop: žádná služba nic nedrží/proc/meminfo:AnonPages135 MiB, aleActive(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
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.
„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 | 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 | 200 GB RAM, 80 GB VRAM, ollama sama nasadí --no-mmap a load selže. |
zavřené bez řešení |
| #10341 | gemma plní RAM navzdory volné VRAM, na RTX 4060 Ti 16 GB — stejná karta. | duplikát #10040 |
| #8654 | „Available memory check should be disabled when mmap is in use" | otevřené od 1/2025 |
| #4895 + PR #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-agentběží a míří nazabbix.hell, ale máHostname=Zabbix server(defaultní hodnota) — stroj se nehlásí jakonvidia.llama-serverběží 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 loguTitle generation timeout). - Balík
earlyoomje ve stavurc— zbýváapt purge, na disku jsou/etc/default/earlyooma/etc/default/earlyoom.bak-20260913.