diff --git a/proxmox/cluster/README.md b/proxmox/cluster/README.md index 0556717..7283287 100644 --- a/proxmox/cluster/README.md +++ b/proxmox/cluster/README.md @@ -870,7 +870,7 @@ swapon -a - **2026-04-20 Cluster Outage:** `incidents/2026-04-20-cluster-outage.md` — post-mortem complet + plan prevenție - **2026-04-30 pvemini backup SSD hang:** `incidents/2026-04-30-pvemini-backup-ssd-hang.md` — Kingston thermal hang → emergency mode - **2026-07-31 LXC 110 DNS + OOM:** `incidents/2026-07-31-lxc110-dns-tailscale-oom.md` — logout Tailscale → DNS mort; zram instalat pe pve1 -- **2026-08-27 pveelite down:** `incidents/2026-08-27-pveelite-down.md` — **DESCHIS** — reset spontan 16:01, cădere definitivă 17:26, jurnal tăcut ⇒ suspiciune alimentare/hardware. Verificare la repornire: `scripts/verifica-pveelite.ps1` +- **2026-08-27 pveelite down:** `incidents/2026-08-27-pveelite-down.md` — **DESCHIS** — nodul dispare la 16:01, revine, apoi cade definitiv la 17:26. Două ipoteze hardware: alimentare sau adaptorul USB de rețea. Verificare la revenire: `scripts/verifica-pveelite.ps1` ### LXC Containers - **LXC 108 - Oracle Database:** `../lxc108-oracle/README.md` diff --git a/proxmox/cluster/incidents/2026-08-27-pveelite-down.md b/proxmox/cluster/incidents/2026-08-27-pveelite-down.md index 3076ad8..ae35b07 100644 --- a/proxmox/cluster/incidents/2026-08-27-pveelite-down.md +++ b/proxmox/cluster/incidents/2026-08-27-pveelite-down.md @@ -19,9 +19,10 @@ pveelite e oprită) 2. **13:20:26–13:20:41** — toate trei nodurile pornesc la loc și reformează clusterul complet (membership `1.1c7`, Members: 1 2 3). **pveelite a revenit normal** și a funcționat 2h40m. 3. **16:01:48 → 16:03:17** — pveelite dispare din corosync și revine după ~89 de secunde. - Nu a fost un flap de rețea: la 16:03:10 se reatașează ca **client NFS** (`rpc.mountd: v4.2 - client attached from 10.0.20.202:986`), iar mount-ul NFS se reface doar la boot. **Nodul - s-a resetat singur.** Nimeni nu i-a comandat asta. + La 16:03:10 se reatașează ca **client NFS** (`rpc.mountd: v4.2 client attached from + 10.0.20.202:986`), iar curba de memorie din RRD se resetează — **probabil s-a repornit + singur**, deși o întrerupere de rețea de 89 s explică și ea reatașarea NFS (vezi + *Ipoteza alternativă* mai jos). Cert e că nimeni nu i-a comandat nimic. 4. **17:15:01** — ultimul semn de viață: cronul de pe pveelite se conectează prin SSH la pvemini, ca la fiecare 15 minute. 5. **17:26:44** — pveelite pică definitiv. **Nu a mai revenit.** @@ -32,15 +33,17 @@ pveelite e oprită) 8. **17:31** — alerta a plecat pe email, după cele 5 minute de prag din script. Lanțul de alertare a funcționat end-to-end. -**Root cause:** nedeterminabilă de la distanță — nodul e mort la nivel L2. Dovezile -disponibile exclud însă cauzele software și indică **defect hardware / de alimentare pe -cutia pveelite**, cel mai probabil declanșat de ciclul de oprire-pornire de la prânz: +**Root cause:** nedeterminabilă de la distanță — nodul nu răspunde nici la ARP. Dovezile +disponibile **exclud cauzele software** și lasă în picioare două ipoteze hardware: defect de +alimentare pe cutia pveelite (declanșat probabil de ciclul de oprire-pornire de la prânz) +sau cedarea adaptorului USB de rețea. Ce se poate afirma acum: - **Nu e resurse:** RRD-ul de pe pvemini arată nodul complet inactiv în ora dinaintea căderii — CPU 0,4 %, load 0,10, RAM 2,15 din 15,3 GB, rootfs 18,5 GB constant. Nu e repetarea scenariului OOM din aprilie. -- **Nu e rețea:** în ultimele 7 zile nu există niciun flap knet în afara zilei de azi. - pve1 ↔ pvemini sunt stabile continuu de la 13:20. +- **Nu e rețeaua clusterului ca întreg:** în ultimele 7 zile nu există niciun flap knet în + afara zilei de azi, iar pve1 ↔ pvemini sunt stabile continuu de la 13:20. Asta **nu** + exclude însă o problemă strict pe portul / adaptorul lui pveelite. - **Nu e UPS:** `ups.status: OL`, baterie 100 %, input 239,6 V, load 8 %. Ultimul test de autonomie de azi a fost pe UPS-ul serverului 36, nu pe cel al clusterului. - **Nu e comandă de la noi:** singura rulare `ups-shutdown` de azi (14:12) a fost în @@ -48,6 +51,37 @@ cutia pveelite**, cel mai probabil declanșat de ciclul de oprire-pornire de la - **Tiparul e de hardware:** reset spontan la 16:01, apoi moarte definitivă 85 de minute mai târziu, pe o mașină idle. Semnătură clasică de PSU / RAM / termic. +### Ipoteza alternativă, care trebuie exclusă prima: adaptorul USB de rețea + +**pveelite are placă de rețea pe USB**, iar deconectarea ei e modul de defectare deja +documentat al acestui nod: incidentul [2026-04-20](2026-04-20-cluster-outage.md) a pornit +de la un *USB LAN disconnect*, iar tokenul corosync a fost mărit la 10 s tocmai ca să +tolereze „glitch-uri USB pveelite" (`cluster/README.md`, secțiunea Corosync Tuning). + +**Din exterior, cele două scenarii sunt indistinctibile.** Un nod care s-a oprit și un nod +care și-a pierdut adaptorul de rețea arată identic: fără ping, fără ARP, fără corosync, +fără SSH. Toate observațiile din acest document sunt compatibile cu ambele. + +Ce înclină totuși spre repornire la 16:01 — dar **nu** dovedește nimic despre 17:26: + +- Curba de memorie din RRD urcă constant după boot-ul de la 13:20 (2,19 → 2,43 GB la 16:00), + apoi **coboară la 2,10 GB la 16:30** — sub valoarea de imediat după boot — și reîncepe să + urce (2,15 GB la 17:00). Tiparul unei reporniri, nu al unei întreruperi de rețea. +- La 16:03:10, `rpc.mountd` înregistrează `v4.2 client attached` de la 10.0.20.202. Un mount + NFS se reface la boot — deși o reatașare NFSv4 după expirarea lease-ului într-o partiție + de 89 de secunde rămâne posibilă. + +Pentru **17:26 nu există niciun indiciu echivalent** — nodul pur și simplu a încetat să fie +vizibil. O deconectare USB explică asta la fel de bine ca o pierdere de alimentare. + +> **Consecință practică, înainte de orice altceva:** când ajungi la nod, **prima observație +> e dacă mașina merge** — ventilatoare, LED-uri, imagine pe monitor. Dacă e pornită, nu a +> fost o cădere de alimentare, jurnalul e intact și complet, iar reparația e la dongle / +> cablu / port de switch. Nu apăsa butonul de power înainte să te uiți. + +Testul decisiv, automatizat în scriptul de verificare: **jurnalul continuă după 17:26:44?** +Dacă da, mașina a mers mai departe și a căzut doar rețeaua. + --- ## Cronologie (EEST) @@ -66,7 +100,7 @@ cutia pveelite**, cel mai probabil declanșat de ciclul de oprire-pornire de la | 16:00:02 | pvemini | cron de pe pveelite, SSH normal | `sshd` | | **16:01:48** | pvemini | `link: host: 3 link: 0 is down` — pveelite dispare | `corosync` | | 16:02:07 | pvemini | `Members left: 3`, `Failed to receive the leave message` | `corosync` | -| 16:03:10 | pvemini | `rpc.mountd: v4.2 client attached from 10.0.20.202` — **remount NFS ⇒ pveelite a bootat** | `rpc.mountd` | +| 16:03:10 | pvemini | `rpc.mountd: v4.2 client attached from 10.0.20.202` — remount NFS ⇒ probabil a bootat | `rpc.mountd` | | 16:03:17 | pvemini | `Members joined: 3` — pveelite revine în cluster | `corosync` | | 16:15 / 16:30 / 16:45 / 17:00 | pvemini | cronurile de pe pveelite rulează normal | `sshd` | | **17:15:01** | pvemini | **ultimul semn de viață** al lui pveelite | `sshd` | @@ -163,9 +197,10 @@ Nodul se pornește fizic. Imediat după ce revine, se rulează Scriptul acoperă, în ordine: -1. **De ce s-a resetat la 16:01 și de ce a murit la 17:26** — `journalctl -b -1` și `-b -2` - pentru erori, `mcelog`/MCE în `dmesg`, evenimente termice, `Hardware Error`. - **Dacă log-urile sunt tăcute (ca la pvemini în aprilie), concluzia e alimentare/hardware, +1. **S-a oprit mașina, sau doar a dispărut din rețea?** Testul decisiv: există intrări în + jurnal după 17:26:44? Dacă da → a mers mai departe, a căzut rețeaua (adaptorul USB), iar + reparația e la dongle/cablu/switch. Dacă nu → mașina chiar s-a oprit, și atunci contează + dacă jurnalul e tăcut înainte (MCE, termic, panic, EDAC). **Tăcere = alimentare/hardware, nu software** — și atunci nodul nu mai e de încredere ca țintă de failover. 2. **Integritatea ZFS** — `zpool status -v` după două opriri necurate; se așteaptă eventual un resilver automat, ca în aprilie. @@ -194,18 +229,35 @@ Dacă `journalctl -b -1` nu conține nimic înainte de 17:26 (tăcere completă, 2026-04-20), atunci **cauza e hardware și nodul trebuie tratat ca nesigur** până la înlocuirea sursei / testare RAM. Nu se lasă concluzia „a mers, deci e bine". -**3. Textul alertei — scos exportul NFS inexistent.** +**3. Notează adresa MAC a lui pveelite — acum nu o mai are nimeni.** +În timpul incidentului s-a pus întrebarea dacă nodul poate fi trezit cu un magic packet +(Wake-on-LAN). **Nu s-a putut nici măcar încerca:** intrarea ARP expirase peste tot — +`ip neigh` pe pvemini (`INCOMPLETE`) și pe pve1 (`FAILED`), tabela ARP a stației de admin, +LXC-urile de pe LAN. Nodurile au IP static, deci nu există lease DHCP, iar MAC-ul nu e +consemnat în documentație. Singurele surse rămase: tabela ARP/DHCP a routerului 10.0.20.1 +sau citirea fizică de pe nod. + +Separat de asta, **WoL are șanse mici pe acest nod**: placa de rețea e pe USB, iar un +adaptor USB rămâne nealimentat în stare soft-off, deci nu poate asculta după magic packet. +De verificat la repornire, împreună cu MAC-ul: +```bash +ssh root@10.0.20.202 "ip -br link; ethtool | grep -iE 'Wake-on|Supports Wake'" +``` +Dacă apare `Supports Wake-on: g` și se activează și în BIOS, WoL devine posibil. Dacă nu, +concluzia se scrie explicit aici, ca să nu se reia discuția la următorul incident. + +**4. Textul alertei — scos exportul NFS inexistent.** `/opt/scripts/pveelite-down-alert.sh` menționează `10.0.20.202:/mnt/pve/oracle-backups`, care nu mai e în `storage.cfg`. Cine citește alerta la 3 noaptea o ia pe o pistă falsă. ### 🟡 Tier 2 — de decis după verdictul hardware -**4. Ce se întâmplă cu marja de quorum.** +**5. Ce se întâmplă cu marja de quorum.** Cât timp pveelite e nesigur, clusterul funcționează pe 2 din 3 voturi. Nu se umblă la `expected votes` cât timp e quorate — dar dacă nodul urmează să stea oprit zile întregi, merită decis conștient dacă rămâne în cluster sau se scoate temporar. -**5. `local-zfs` pe pvemini la 92 %.** +**6. `local-zfs` pe pvemini la 92 %.** Separat de incident, dar pe același nod pe care stă acum toată producția. --- diff --git a/proxmox/cluster/scripts/verifica-pveelite.ps1 b/proxmox/cluster/scripts/verifica-pveelite.ps1 index dce0ff0..bb39c7f 100644 --- a/proxmox/cluster/scripts/verifica-pveelite.ps1 +++ b/proxmox/cluster/scripts/verifica-pveelite.ps1 @@ -3,19 +3,28 @@ Verificare completa a nodului pveelite dupa revenirea din incidentul 2026-08-27. .DESCRIPTION - Nodul pveelite s-a resetat singur la 16:01 pe 27.08.2026 si a murit definitiv la - 17:26, pe o masina complet idle. Cauza nu s-a putut stabili de la distanta - nodul - era mort la nivel L2. Scriptul asta se ruleaza IMEDIAT dupa ce nodul e pornit fizic - la loc si raspunde la doua intrebari, in ordinea asta: + Nodul pveelite a disparut din retea la 16:01 pe 27.08.2026, a revenit dupa 89 de + secunde, apoi a disparut definitiv la 17:26, pe o masina complet idle. Cauza nu s-a + putut stabili de la distanta - nodul nu raspundea nici la ARP. Scriptul se ruleaza + IMEDIAT dupa ce nodul e accesibil din nou si raspunde la doua intrebari: - 1. DE CE a cazut - din log-urile boot-urilor anterioare, care acum sunt citibile. + 1. DE CE a cazut - din jurnalul care abia acum devine citibil. 2. E nodul in stare buna acum - ZFS, cluster, replicare, HA, SMART, Tailscale. - Verdictul de la pasul 1 conteaza mai mult decat restul. Daca log-urile boot-ului - anterior sunt TACUTE inainte de ora caderii - fara MCE, fara eroare termica, fara - panic - atunci cauza e alimentare/hardware, exact ca la pvemini pe 2026-04-20, iar - nodul NU e de incredere ca tinta de failover pana la testarea sursei si a memoriei. - "A pornit, deci e bine" nu e o concluzie valida aici. + Pasul 1 conteaza mai mult decat tot restul, si incepe cu intrebarea care imparte + incidentul in doua: s-a OPRIT masina, sau doar a disparut din RETEA? Din afara + arata identic - fara ping, fara ARP, fara corosync - dar remediul difera complet. + Testul decisiv e daca jurnalul continua dupa ora caderii: daca da, masina a mers + mai departe si a cazut doar reteaua. + + Ipoteza de retea nu e teoretica pe nodul asta: pveelite are adaptor USB de retea, + iar incidentul 2026-04-20 a pornit exact de la un USB LAN disconnect - motivul + pentru care tokenul corosync a fost marit la 10 s. + + Daca insa jurnalul se opreste brusc si e TACUT inainte - fara MCE, fara eroare + termica, fara panic - atunci cauza e alimentare/hardware, ca la pvemini pe + 2026-04-20, iar nodul NU e de incredere ca tinta de failover pana la testarea + sursei si a memoriei. "A pornit, deci e bine" nu e o concluzie valida aici. Context complet: ../incidents/2026-08-27-pveelite-down.md @@ -132,33 +141,101 @@ try { $uptime = Invoke-Node -Node pveelite -Command 'uptime -p; uptime -s' Write-Info ($uptime -join ' | ') -# ================================================= 1. DE CE a cazut (esentialul) +# ============================== 1. s-a oprit, sau doar a disparut din retea? -Write-Step "1. De ce a cazut - log-urile boot-urilor anterioare" +Write-Step "1. S-a oprit masina, sau doar a disparut din retea?" +Write-Info "Intrebarea asta se pune PRIMA, pentru ca imparte incidentul in doua" +Write-Info "scenarii cu remedii complet diferite:" +Write-Info " (a) masina s-a oprit sau resetat -> alimentare / RAM / termic" +Write-Info " (b) masina a mers tot timpul, dar a pierdut adaptorul USB de retea" +Write-Info " -> exact tiparul documentat pe nodul asta la 2026-04-20" +Write-Info "Din afara, cele doua arata identic: fara ping, fara ARP, fara corosync." + +Write-Host "" Write-Info "boot-uri inregistrate:" -$boots = Invoke-Node -Node pveelite -Command 'journalctl --list-boots --no-pager | tail -5' +$boots = Invoke-Node -Node pveelite -Command 'journalctl --list-boots --no-pager | tail -6' $boots | ForEach-Object { Write-Info " $_" } -# Boot -1 = fereastra 16:03 -> 17:26 (caderea definitiva). -# Boot -2 = fereastra 13:20 -> 16:01 (resetul spontan). +# TESTUL DECISIV: exista intrari in jurnal DUPA ora la care nodul a disparut din +# retea? Daca da, masina a continuat sa mearga si a cazut doar reteaua. +$dupaCadere = Invoke-Node -Node pveelite -Command ` + "journalctl --since '$CadereFinala' --until '2026-08-28 06:00' --no-pager | wc -l" +$nrDupa = 0 +[void][int]::TryParse((($dupaCadere | Select-Object -First 1) -replace '\D',''), [ref]$nrDupa) + +# Al doilea test: a existat un boot in fereastra resetului de la 16:01? +$bootLa16 = Invoke-Node -Node pveelite -Command ` + "journalctl --since '2026-08-27 15:55' --until '2026-08-27 16:15' --no-pager | grep -ci 'Linux version'" +$nrBoot16 = 0 +[void][int]::TryParse((($bootLa16 | Select-Object -First 1) -replace '\D',''), [ref]$nrBoot16) + +Write-Host "" +$scenariuRetea = $false +if ($nrDupa -gt 0) { + Write-Bad "SCENARIUL (b): jurnalul CONTINUA dupa $CadereFinala ($nrDupa linii)." + Write-Info "Masina nu s-a oprit - a mers mai departe si doar a disparut din retea." + Write-Info "Cauza e adaptorul USB de retea, nu alimentarea. Vezi sectiunea USB de mai jos." + Add-Rezultat 'Cauza caderii' 'bad' 'masina a mers mai departe => cadere de retea (USB LAN), nu alimentare' + $scenariuRetea = $true +} else { + Write-Info "Jurnalul se opreste la $CadereFinala - masina chiar a incetat sa mearga." +} + +if ($nrBoot16 -gt 0) { + Write-Info "La 16:01 a existat un boot real ($nrBoot16 x 'Linux version') - deci s-a resetat." +} else { + Write-Info "La 16:01 NU exista boot in jurnal - a fost tot o disparitie din retea, nu un reset." +} + +# Liniile din jurul fiecarui eveniment, cautate dupa ora - nu dupa indexul boot-ului, +# care difera intre cele doua scenarii. foreach ($b in @( - @{ Idx = -1; Cand = $CadereFinala; Ce = 'caderea definitiva de la 17:26' }, - @{ Idx = -2; Cand = $ResetSpontan; Ce = 'resetul spontan de la 16:01' } + @{ Cand = $CadereFinala; Ce = 'caderea definitiva de la 17:26' }, + @{ Cand = $ResetSpontan; Ce = 'evenimentul de la 16:01' } )) { Write-Host "" - Write-Info "--- boot $($b.Idx): ultimele linii inainte de $($b.Ce) ---" - $tail = Invoke-Node -Node pveelite -Command "journalctl -b $($b.Idx) --no-pager | tail -15" + Write-Info "--- ultimele linii dinainte de $($b.Ce) ---" + $tail = Invoke-Node -Node pveelite -Command ` + "journalctl --since '$IncidentStart' --until '$($b.Cand)' --no-pager | tail -15" if ($tail) { $tail | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray } } - else { Write-Warn "boot $($b.Idx) nu mai exista in jurnal (rotit sau volatile)" } + else { Write-Warn "nimic in jurnal pentru fereastra asta (rotit sau volatile)" } +} - $err = Invoke-Node -Node pveelite -Command "journalctl -b $($b.Idx) -p err --no-pager | tail -20" - if ($err) { - Write-Warn "erori in boot $($b.Idx):" - $err | ForEach-Object { Write-Host " $_" -ForegroundColor Yellow } - } else { - Write-Info "fara erori de prioritate >= err in boot $($b.Idx)" - } +$err = Invoke-Node -Node pveelite -Command ` + "journalctl --since '$IncidentStart' --until '2026-08-28 06:00' -p err --no-pager | tail -25" +if ($err) { + Write-Warn "erori de prioritate >= err in fereastra incidentului:" + $err | ForEach-Object { Write-Host " $_" -ForegroundColor Yellow } +} else { + Write-Info "fara erori de prioritate >= err in fereastra incidentului" +} + +# --------------------------------------------- adaptorul USB de retea + +Write-Host "" +Write-Info "--- adaptorul USB de retea (istoric de defectiuni pe nodul asta) ---" + +$nic = Invoke-Node -Node pveelite -Command @' +echo "interfete:"; ip -br link 2>/dev/null | head -8 +echo "drivere:" +for n in /sys/class/net/*; do + d=$(basename $(readlink -f $n/device/driver) 2>/dev/null) + [ -n "$d" ] && echo " $(basename $n) -> $d" +done +echo "adaptoare USB:"; lsusb 2>/dev/null | grep -iE 'ethernet|network|realtek|asix|lan' || echo " niciunul raportat de lsusb" +'@ +$nic | ForEach-Object { Write-Info $_ } + +$usbEv = Invoke-Node -Node pveelite -Command ` + "journalctl -k --since '$IncidentStart' --no-pager | grep -iE 'usb [0-9-]+: (USB )?disconnect|usb .*reset (high|super|full)-speed|r8152|ax88179|cdc_ncm|cdc_ether|NIC Link is (Down|Up)|link is not ready|eth[0-9] speed' | tail -25" +if ($usbEv) { + Write-Bad "evenimente USB / link pe placa de retea:" + $usbEv | ForEach-Object { Write-Host " $_" -ForegroundColor Red } + Add-Rezultat 'Adaptor USB LAN' 'bad' 'deconectari/reseturi USB in jurnal - vezi liniile' +} else { + Write-Info "niciun eveniment de deconectare USB in fereastra incidentului" + if (-not $scenariuRetea) { Add-Rezultat 'Adaptor USB LAN' 'ok' 'fara deconectari in jurnal' } } # Cautarea tintita de semnaturi hardware, peste toate boot-urile de ieri. @@ -188,21 +265,29 @@ $necurate = Invoke-Node -Node pveelite -Command ` Write-Info "istoric reboot/shutdown:" $necurate | Select-Object -Skip 1 | ForEach-Object { Write-Info " $_" } -if (-not $verdictHw) { +if (-not $verdictHw -and -not $scenariuRetea) { Write-Host "" - Write-Bad "VERDICT: jurnalul e TACUT inainte de ambele caderi." - Write-Info "Masina a disparut fara sa apuce sa scrie nimic - exact tiparul pvemini" - Write-Info "din 2026-04-20. Cauza e alimentare sau hardware (sursa / RAM / termic)," + Write-Bad "VERDICT: masina a incetat sa mearga si jurnalul e TACUT inainte de asta." + Write-Info "A disparut fara sa apuce sa scrie nimic - exact tiparul pvemini din" + Write-Info "2026-04-20. Cauza e alimentare sau hardware (sursa / RAM / termic)," Write-Info "NU software. Nodul nu e de incredere ca tinta de failover pana cand:" Write-Info " - sursa e testata sau inlocuita" Write-Info " - memoria e testata (memtest86+, minim o trecere completa)" Write-Info " - se verifica praful si ventilatia (vezi temperaturile de la pasul 6)" Add-Rezultat 'Cauza caderii' 'bad' 'jurnal tacut => alimentare/hardware, nod nesigur' +} elseif ($scenariuRetea) { + Write-Host "" + Write-Bad "VERDICT: nu a fost o cadere de alimentare - a fost reteaua." + Write-Info "Masina a mers tot timpul. Remediul e la adaptorul de retea, nu la sursa:" + Write-Info " - daca e adaptor USB, scoate-l din USB si pune-l inapoi, apoi verifica" + Write-Info " daca revine ca acelasi nume de interfata (altfel vmbr0 ramane fara port)" + Write-Info " - pe termen lung: NIC pe PCIe in loc de USB, sau al doilea link corosync" + Write-Info " - verifica si cablul si portul de switch, nu doar dongle-ul" } # ============================================================ 2. integritate ZFS -Write-Step "2. Integritate ZFS (dupa doua opriri necurate)" +Write-Step "2. Integritate ZFS (relevant daca au fost opriri necurate)" $zpool = Invoke-Node -Node pveelite -Command 'zpool status -v' $zpool | ForEach-Object { Write-Info $_ }