Alerta "OOM x2 on pvemini" (09:36) arata procese mici ucise (dbus-daemon, oom_score_adj:200), dar mesajul kernel dadea containerul real: oom_memcg=/lxc/102. OOM local containerului, nu presiune de host - pvemini avea 24Gi disponibili si zram functional. Baseline masurat cu ZERO sandbox-uri active: ~1.9GB (sbx 863M + claude 317M + VS Code Remote 450M + docker/tailscale/portainer 205M). Un sandbox real mai adauga ~1.9GB (containerd-shim) -> plafonul de 4GB era depasit sistematic. Contoare cumulate: oom_kill 24, 9279 depasiri memory.high, memory.peak fix pe limita, swap 510/512 epuizat. Verificat explicit ca sbx NU are memory leak: RSS urca la ~863M la pornire si se plafoneaza (esantionat la 10s timp de un minut). Fix: pct set 102 --memory 12288 --swap 4096 (live, fara restart). Tabelul de resurse din cluster/README.md era vechi (102 aparea ca "coolify stopped", lipseau 110 si 171, RAM gresit peste tot) - regenerat din pvesh. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.6 KiB
Incident 2026-07-31 — LXC 110 (moltbot): DNS mort după logout Tailscale + OOM
Severity: Medium (serviciu echo-core indisponibil ~8 min; fără pierdere de date)
Detected: 2026-07-31 ~09:28 EEST (user — „nu mai răspunde la SSH, nu mai merge echo")
Resolved: 2026-07-31 09:34 EEST (fix DNS) + 09:5x EEST (zram pe pve1)
Author: Claude Code (mmarius28@gmail.com)
TL;DR — lanțul cauzal
- 06:26 UTC — LXC 110 se oprește după 65 zile uptime. În log-urile de shutdown:
user-1000.slice: A process of this unit has been killed by the OOM killer. OOM local containerului (plafon 8GB), NU la nivel de host — pve1 nu a avut niciun OOM în 30 de zile și avea 18GB available. - 06:26:59 — la revenire,
tailscaledgenerează nodekey nou și rămâne delogat (machineAuthorized=false,authURL=true). - DNS moare complet. LXC 110 nu avea
nameserverînpct config, deci moștenea/etc/resolv.confde la host-ul pve1 — iar acolo fișierul e scris de Tailscale și conținea doar MagicDNS (100.100.100.100+fd7a:115c:a1e0::53). Cu Tailscale delogat, resolverul devine inaccesibil. echo-core.serviceintră în crash-loop cutelegram.error.TimedOut(restart counter ajunsese la 11).
Capcana de diagnostic: rețeaua L3 era perfect funcțională — ping 8.8.8.8 OK,
gateway OK, rută OK. Doar rezoluția numelor pica. Ușor de interpretat greșit ca
„bot stricat" sau „internet căzut".
SSH-ul „care nu răspundea" era doar containerul în curs de repornire — la verificare funcționa deja normal.
Diagnostic — comenzi cheie
# NU te lua după ping — verifică întâi rezoluția
getent hosts api.telegram.org # gol => DNS mort
cat /etc/resolv.conf # doar 100.100.100.100 => depinde de Tailscale
ping -c2 8.8.8.8 # OK => L3 e sănătos, problema e DNS
tailscale status # "Logged out."
# serviciile echo rulează ca user systemd (user moltbot)
su - moltbot -c 'XDG_RUNTIME_DIR=/run/user/1000 systemctl --user status echo-core'
Fix 1 — DNS explicit (aplicat)
# pe pve1
pct set 110 --nameserver '10.0.20.1 1.1.1.1' # persistent, aplicat la următorul start
# live, fără restart de container (backup: /etc/resolv.conf.bak-2026-07-31)
printf '# --- BEGIN PVE ---\nnameserver 10.0.20.1\nnameserver 1.1.1.1\n# --- END PVE ---\n' \
> /etc/resolv.conf
su - moltbot -c 'XDG_RUNTIME_DIR=/run/user/1000 systemctl --user restart echo-core'
Rezultat: Telegram getUpdates → 200 OK, Discord online, 0 restarturi ulterioare.
Expunere similară: orice alt LXC de pe pve1 fără
nameserverexplicit moștenește același resolv.conf Tailscale și va pica identic la un logout Tailscale.
Fix 2 — zram swap pe pve1 (aplicat)
pct config 110 avea swap: 4096, dar în container free -h arăta Swap: 0B.
Cauza: limita cgroup exista corect pe host…
/sys/fs/cgroup/lxc/110/memory.max = 8589934592 (8 GB)
/sys/fs/cgroup/lxc/110/memory.swap.max = 4294967296 (4 GB) <- plafon OK
/sys/fs/cgroup/lxc/110/memory.swap.current = 0 <- nimic nu-l umple
…dar pve1 nu avea niciun swap (swapon --show gol, nimic în /etc/fstab). Limita
cgroup e doar un plafon peste swap-ul host-ului; fără backing store fizic, kernelul nu
are unde scrie paginile. Root-ul pve1 e pe ZFS (rpool/ROOT/pve-1), deci swapfile e
exclus (risc de deadlock) — aceeași situație rezolvată pe pvemini în 2026-06-24.
# pe pve1 (host) — identic cu pvemini
apt install -y zram-tools
cat > /etc/default/zramswap <<'EOF'
# zram swap config - host buffer pentru spike-uri OOM (ex: LXC 110 moltbot)
ALGO=zstd
SIZE=8192
PRIORITY=100
EOF
systemctl restart zramswap.service # enabled persistent la boot
swapon --show # /dev/zram0 8G prio 100
Verificare în container — cei 4GB au acum backing real:
free -h → Swap: 4.0Gi
Vârfurile tranzitorii fac swap-out în loc de OOM-kill instant.
Rămas de făcut (necesită acțiune user)
| Item | Detalii |
|---|---|
| Re-auth Tailscale în LXC 110 | Necesită login interactiv din browser (tailscale up regenerează URL-ul). Până atunci IP-ul 100.120.119.70 nu răspunde; accesul pe 10.0.20.173 e normal. |
| Bridge WhatsApp deconectat | {"connected":false,"qr":null} pe 127.0.0.1:8098. Discord + Telegram merg. Probabil necesită re-pairing prin QR. |
| Monitorizare | De urmărit dacă MemoryHigh pe TTS chiar oprește recurența — următorul episod ar trebui să se manifeste ca throttling, nu ca kill. |
OOM-ul NU e izolat — istoric recurent
Verificarea jurnalului complet (nu doar boot-ul curent) arată că OOM-ul din 31 iulie e al cincilea episod, nu un accident:
Apr 25 08:34:53 echo-core.service: Failed with result 'oom-kill'
May 28 14:09:36 echo-core.service: Failed with result 'oom-kill' <- 1.4G memory peak
May 28 14:15:44 echo-core.service: Failed with result 'oom-kill'
May 28 14:18:13 echo-core.service: Failed with result 'oom-kill'
May 28 14:18:13 supertonic-tts.service: Failed with result 'oom-kill'
Jul 31 06:26:22 user-1000.slice: killed by the OOM killer -> reboot
Pe 28 mai: 4 kill-uri în 9 minute, echo-core luând cu el și supertonic-tts.
Log-ul de atunci confirmă lipsa swap-ului: 1.4G memory peak, 0B memory swap peak —
fără backing store, kernelul trece direct la kill.
Cauza structurală: servicii fără limite
Cele 7 servicii user systemd (echo-core, echo-taskboard, echo-whatsapp-bridge,
pocket-tts, supertonic-tts, romfast-website, dbus) rulează toate fără plafon:
MemoryMax=infinity
MemoryHigh=infinity
Deci orice serviciu poate consuma singur toți cei 8 GB ai containerului, iar OOM killer-ul
alege victime după oom_score_adj — de unde procesele mici ucise aiurea (dbus-daemon,
sd-pam) care fac diagnosticul derutant. Stiva TTS e cea mai grea:
pocket-tts ~945 MB + supertonic ~500 MB, în repaus.
Fix 3 — MemoryHigh pe stiva TTS (aplicat)
MemoryHigh face throttling + reclaim în loc de kill, deci serviciul degradează elegant
sub presiune. MemoryMax e plasa de siguranță: izolează un eventual kill în interiorul
serviciului, în loc să lase OOM killer-ul să aleagă victime aleatorii în tot containerul.
Drop-in-uri în ~/.config/systemd/user/<serviciu>.service.d/limits.conf (user moltbot):
| Serviciu | RSS repaus | MemoryHigh | MemoryMax |
|---|---|---|---|
pocket-tts |
~945 MB | 1536M | 2G |
supertonic-tts |
~500 MB | 1024M | 1536M |
su - moltbot
mkdir -p ~/.config/systemd/user/pocket-tts.service.d
cat > ~/.config/systemd/user/pocket-tts.service.d/limits.conf <<'EOF'
[Service]
MemoryHigh=1536M
MemoryMax=2G
EOF
export XDG_RUNTIME_DIR=/run/user/1000
systemctl --user daemon-reload
systemctl --user restart pocket-tts supertonic-tts
systemctl --user show pocket-tts -p MemoryHigh,MemoryMax,MemoryCurrent # verificare
Verificat post-aplicare: ambele active/running, porturile 7788 + 7789 deschise,
echo-core neîntrerupt. Consum după restart: pocket-tts 773M, supertonic 463M.
Restul serviciilor (
echo-core,echo-taskboard,echo-whatsapp-bridge,romfast-website) au rămas fără limite — TTS-ul e consumatorul dominant. De reevaluat dacă apar OOM-uri cu altă victimă.
Prevenție
- zram pe pve1 amortizează spike-urile (aplicat) — dar singur e paliativ: fără limite pe
servicii, swap-ul doar întârzie kill-ul. Fixul de fond e
MemoryHighpe TTS (aplicat). - DNS explicit pe LXC 110 elimină dependența de Tailscale (aplicat).
- De evaluat același
--nameserverpentru celelalte LXC-uri de pe pve1. - Alertare pe
NRestartsla serviciile user systemd ar fi prins crash-loop-ul mai devreme decât raportarea manuală.
Legături: ../../lxc110-moltbot/README.md · ../../lxc171-claude-agent/README.md
(secțiunea „Memorie & OOM" — incidentul zram pvemini 2026-06-24)
Al doilea OOM în aceeași zi, alt container, alt mecanism: LXC 102 (docker/sbx) a generat alertă „OOM x2 on pvemini" la 09:36. Acolo host-ul avea swap funcțional — pur și simplu containerul era subdimensionat (4GB pentru sbx + VS Code + Claude). Ridicat la 12GB. Detalii:
../../lxc102-docker/README.md→ „Memorie".Numitorul comun al ambelor cazuri: OOM local unui cgroup de container, deși host-ul avea marjă largă, plus victime alese după
oom_score_adj(procese mici, irelevante) care ascund adevăratul consumator. Primul reflex: citeșteoom_memcg=din mesajul kernel.