Compare commits

..

2 Commits

Author SHA1 Message Date
Claude Agent
1203c24d63 docs(proxmox): document HA, corosync tuning, diagnostic tools and mail relay
Following the 2026-04-20 cluster outage, the cluster README now covers
HA resource limits, corosync token tuning (10s tolerance for USB glitches),
rasdaemon/netconsole/kdump diagnostic stack on pvemini, mail relay via
mail.romfast.ro with SMTP auth, OOM alerting via cron, and swap on pveelite.

VM 109 README now clearly states it was removed from HA and is only
started by the weekly DR test script.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 11:30:46 +00:00
Claude Agent
60c27e7232 fix(vm109-dr): trap cleanup to stop VM 109 on script exit
The DR test script used set -euo pipefail, so a failing SSH
shutdown command caused the script to exit before qm stop.
On 2026-04-20 this left VM 109 running for 2.5 days and
triggered an OOM cascade when pvemini HA-failed over to
pveelite.

Adds EXIT trap that force-stops VM 109 regardless of exit
path, and makes the Step 7 SSH shutdown tolerant of failure.
Incident details: proxmox/cluster/incidents/2026-04-20-cluster-outage.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 11:16:04 +00:00
5 changed files with 548 additions and 3 deletions

View File

@@ -7,8 +7,10 @@ proxmox/
├── README.md # Acest fișier (index principal)
├── cluster/ # Infrastructură cluster Proxmox
│ ├── README.md # Ghid SSH și administrare cluster
│ ├── README.md # Ghid SSH, HA, corosync tuning, diagnostic tools, mail relay, OOM alert
│ ├── cluster-ha-monitor.sh # Script monitorizare HA
│ ├── incidents/ # Post-mortems incidente cluster
│ │ └── 2026-04-20-cluster-outage.md # Cascadă OOM pveelite + USB LAN watchdog
│ └── ups/ # Sistem UPS pentru cluster
│ ├── README.md
│ ├── docs/

View File

@@ -483,11 +483,213 @@ systemctl restart pveproxy
---
## High Availability (HA)
Cluster-ul folosește HA pentru failover automat al containerelor critice. Configurația a fost revizuită după incidentul 2026-04-20 (vezi `incidents/2026-04-20-cluster-outage.md`).
### Grupuri HA
```
group: ha-group-main → pvemini (primar 100), pveelite (50), pve1 (33)
group: ha-group-elite → pveelite (primar 100), pve1 (33), pvemini (50)
```
### Resurse HA active
| Resursă | Grup | Home node | Max restart | Max relocate | Notă |
|---------|------|-----------|-------------|--------------|------|
| ct:100 portainer | ha-group-main | pvemini | 3 | 3 | |
| ct:101 minecraft | ha-group-elite | pvemini | 3 | 3 | Rulează pe pveelite |
| ct:104 flowise | ha-group-main | pvemini | 3 | 2 | Limite adăugate 2026-04-20 |
| ct:105 test | ha-group-elite | pvemini | - | - | Stopped |
| ct:106 gitea | ha-group-main | pvemini | 3 | 3 | |
| ct:108 central-oracle | ha-group-main | pvemini | 3 | 2 | Limite adăugate 2026-04-20 |
**VM 109 (oracle-dr-windows) NU mai e în HA** — scos intenționat 2026-04-20 după buclă OOM. Pornit exclusiv de scriptul DR test sâmbăta 06:00.
### Verificare HA
```bash
ssh root@10.0.20.201 "ha-manager status"
ssh root@10.0.20.201 "ha-manager config"
```
### Modificare limite HA (exemplu)
```bash
ha-manager set ct:108 --max_restart 3 --max_relocate 2
```
---
## Corosync Tuning
După incidentul 2026-04-20 (crash pveelite din USB LAN disconnect → pierdere cvorum → watchdog reset), tokenul corosync a fost mărit pentru a tolera glitch-uri scurte de rețea.
**Config curent** (`/etc/pve/corosync.conf`, `config_version: 16`):
```
totem {
token: 10000
token_retransmits_before_loss_const: 10
}
```
Impact: cluster-ul așteaptă **10 secunde** înainte să declare un nod mort (default era 1 sec). Tolerează USB disconnect scurt pe pveelite fără să forțeze reboot.
Verificare:
```bash
ssh root@10.0.20.201 "corosync-cmapctl | grep 'totem.token '"
# runtime.config.totem.token (u32) = 10650
# totem.token (u32) = 10000
```
---
## Diagnostic Tools (pvemini)
Instalate 2026-04-20 pentru a prinde cauza crash-ului din 00:23 (care nu a lăsat niciun log).
### rasdaemon — MCE + PCIe AER monitoring
```bash
# Verificare erori hardware istorice
ssh root@10.0.20.201 "ras-mc-ctl --summary"
# Memory errors / PCIe AER errors / Extlog / MCE
```
### netconsole — kernel logs către pve1
pvemini trimite log-uri kernel via UDP către pve1. Dacă pvemini crashează hard, ultimele linii kernel sunt captate pe pve1.
```bash
# Logs pre-crash pe pve1
ssh root@10.0.20.200 "tail /var/log/netconsole-pvemini.log"
# Status serviciu listener
ssh root@10.0.20.200 "systemctl status netconsole-receiver"
```
Config pe pvemini: `/etc/modules-load.d/netconsole.conf`
Config pe pve1: `/etc/systemd/system/netconsole-receiver.service` + `/var/log/netconsole-pvemini.log`
### kdump-tools — captură kernel crash dump
```bash
# Verificare configurare
ssh root@10.0.20.201 "cat /proc/cmdline | grep crashkernel"
ssh root@10.0.20.201 "systemctl is-active kdump-tools"
# La următorul crash, dump-ul va fi în:
ssh root@10.0.20.201 "ls /var/crash/"
```
Parametru: `crashkernel=128M` în `/etc/kernel/cmdline` (Proxmox folosește systemd-boot prin `proxmox-boot-tool`, nu GRUB).
### kernel.panic auto-reboot
```bash
ssh root@10.0.20.201 "sysctl kernel.panic"
# kernel.panic = 10 → auto-reboot după 10s la kernel panic
```
---
## Mail Notifications
Toate 3 nodurile trimit mail prin `mail.romfast.ro:465` cu autentificare SMTP SASL (cont `ups@romfast.ro`).
### Configurare Postfix
Config în `/etc/postfix/main.cf` pe fiecare nod:
```
relayhost = [mail.romfast.ro]:465
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_wrappermode = yes
smtp_tls_security_level = encrypt
```
Credentiale în `/etc/postfix/sasl_passwd` (permisiuni 600).
### Test rapid
```bash
ssh root@10.0.20.201 "echo 'test' | mail -r 'ups@romfast.ro' -s 'test $(hostname)' mmarius28@gmail.com"
ssh root@10.0.20.201 "journalctl -u postfix@- --since '1 min ago' | grep status="
# Trebuie să vezi: status=sent (250 OK ...)
```
### Dependințe
- `libsasl2-modules` (instalat 2026-04-20 — fără el: `SASL authentication failure: No worthy mechs found`)
---
## OOM Alerting
Cron pe fiecare nod verifică la 1 minut dacă au avut loc OOM-kills. Dacă da, trimite mail cu detalii.
### Configurare
- Script: `/opt/scripts/oom-alert.sh` pe fiecare nod (pve1, pvemini, pveelite)
- Cron: `* * * * * /opt/scripts/oom-alert.sh`
- Mail destinat: `mmarius28@gmail.com` (de la `ups@romfast.ro`)
### Verificare script instalat
```bash
for ip in 10.0.20.200 10.0.20.201 10.0.20.202; do
ssh root@$ip "crontab -l | grep oom-alert"
done
```
### Test simulare
```bash
# Generează OOM kill mesaj fals (NU omoară nimic, doar log)
ssh root@10.0.20.202 "logger -t kernel -p kern.warn 'Killed process 99999 (fake-test) total-vm:1kB'"
# Așteaptă 1 min, verifică inbox
```
---
## Swap pe pveelite
Adăugat 2026-04-20 ca insurance împotriva OOM cascade (pveelite are doar 16 GB RAM).
- Swap device: `/dev/zvol/rpool/swap` (ZFS zvol 8 GB)
- Mount: `/etc/fstab`
- swappiness: 10 (folosește swap doar sub presiune reală)
### Verificare
```bash
ssh root@10.0.20.202 "swapon --show; sysctl vm.swappiness"
```
### Recreare (dacă e nevoie)
```bash
zfs create -V 8G -b 4K -o compression=zle -o logbias=throughput \
-o sync=always -o primarycache=metadata -o secondarycache=none \
rpool/swap
mkswap -f /dev/zvol/rpool/swap
echo '/dev/zvol/rpool/swap none swap sw 0 0' >> /etc/fstab
swapon -a
```
---
## Documentație Asociată
### Index Principal
- **README.md** - `../README.md` - Index complet documentație Proxmox
### Incidents
- **2026-04-20 Cluster Outage:** `incidents/2026-04-20-cluster-outage.md` — post-mortem complet + plan prevenție
### LXC Containers
- **LXC 108 - Oracle Database:** `../lxc108-oracle/README.md`
@@ -495,6 +697,7 @@ systemctl restart pveproxy
- **VM 201 - Windows 11:** `../vm201-windows/README.md`
- SSL Certificates: `../vm201-windows/docs/vm201-certificat-letsencrypt-iis.md`
- Troubleshooting: `../vm201-windows/docs/`
- **VM 109 - Oracle DR Windows:** `../vm109-windows-dr/README.md` — NU mai e în HA din 2026-04-20
### Cluster Resources (acest director)
- **HA Monitor:** `cluster-ha-monitor.sh`
@@ -502,6 +705,6 @@ systemctl restart pveproxy
---
**Ultima actualizare:** 2026-01-27
**Ultima actualizare:** 2026-04-20
**Autor:** Marius Mutu
**Proiect:** ROMFASTSQL - Proxmox Infrastructure Documentation

View File

@@ -0,0 +1,306 @@
# Incident 2026-04-20 — Cluster outage pvemini + pveelite
**Severity:** Major (LXC/VM downtime pe 2 din 3 noduri, ~12h impact intermitent)
**Detected:** 2026-04-20 ~12:45 EEST (user)
**Resolved:** 2026-04-20 12:49 EEST (reboot manual toate nodurile)
**Author:** Claude Code (mmarius28@gmail.com)
---
## TL;DR — lanțul cauzal (versiune finală)
**Topologie reală:** pvemini (64 GB) = gazdă primară pentru TOATE: CT 100, 101, 104, 106, 108 + VM 109. pveelite (16 GB) = gazdă secundară de failover HA. pve1 (32 GB) = quorum-only, nu găzduiește servicii.
1. **Luni 2026-04-20 00:23:24**`pvemini` îngheață total, **fără niciun log kernel**. Cauză necunoscută (nu avem mcelog, kdump, IPMI SEL, UPS logs).
2. **00:39:47** — pvemini revine SINGUR (BIOS auto-power-on sau watchdog reset). **User nu a intervenit** — primul reboot manual de la user a fost abia la 12:49.
3. **00:40:17** — pveelite devine HA master, declanșează fence pe pvemini (pentru că pvemini era deja booted dar HA nu știa să-l recunoască imediat post-crash).
4. **00:41:28** — HA recovery masiv: CT 100 + CT 104 + CT 106 + CT 108 mutate de pe pvemini pe pveelite. VM 109 (HA state=`started` de la scriptul DR de sâmbătă, care n-a reușit să-l oprească) re-pornită pe pveelite (preferred în `ha-group-elite`).
5. **00:42:29** — primul OOM kill pe pveelite: VM 109 (kvm, 6.3 GB RSS) omorât. pveelite avea brusc CT 108 Oracle (8 GB) + VM 109 (6 GB) + CT 104 flowise + CT 100 portainer + CT 106 gitea + overhead. CT 101 minecraft NU era pe pveelite (era tot pe pvemini). Total cerere mult peste 16 GB.
6. **00:42 → 11:45****Buclă OOM infinită timp de ~3 ore**: HA LRM reporniseș VM 109 la fiecare 20 s, OOM killer îl omora. CT 104 și CT 108 erau de asemenea killed — amândouă **n-au `max_restart`/`max_relocate`** configurat → repornire infinită. CT 100 și CT 106 aveau limite, s-au oprit după 3 încercări.
7. **11:45:35** — pveelite devine nefuncțional, user intervine cu reboot la 11:46.
8. **12:49** — user reboot general manual pe ambele noduri → cluster stabil.
**Root cause dublu:**
- **Trigger:** crash misterios pvemini fără diagnostic + DR test script lasă VM 109 în HA state=`started` (bug `set -e`).
- **Amplificator:** pveelite (16 GB) nu are capacitate să preia load-ul pvemini (care rulează ~25 GB de servicii). Limite HA incoerente (CT 104, CT 108, VM 109 fără `max_restart`). pve1 (32 GB) nefolosit.
---
## Cronologie (EEST)
| Ora | Nod | Eveniment | Sursa |
|-----|-----|-----------|-------|
| 2026-04-18 06:00 | pveelite | DR test script pornește VM 109. SSH `10.0.20.37` nu răspunde în 180s. Script crashează la STEP 7 (`ssh shutdown` fail + `set -e`). **VM 109 rămâne RUNNING** | `/var/log/oracle-dr/dr_test_20260418_060001.log` |
| 2026-04-18 → 04-20 | pveelite | VM 109 stă pornit 2.5 zile (~6 GB). CT 101 (minecraft, 8 GB) rula deja → total ~14 GB pe 16 GB host | - |
| 2026-04-20 00:23:24 | pvemini | **Ultimul log** (`pmxcfs data verification successful`), apoi tăcere. Mașina îngheață total. | `journalctl -b -2` |
| 00:40:17 | pveelite | HA CRM detectează pvemini offline, devine master. pvemini trece în `unknown`. | `pve-ha-crm` |
| 00:41:17 | pveelite | pvemini trece în `fence`. Serviciile ct:100, ct:104, ct:106, ct:108 marcate `fence`. | `pve-ha-crm` |
| 00:41:27 | pveelite | HA obține lock-ul de fence, pvemini considerat oficial DOWN. | `pve-ha-crm` |
| **00:41:28** | pveelite | **Recovery masiv:** ct:100, ct:104, ct:106, ct:108 mutate de pe pvemini pe pveelite. VM 109 era deja pe pveelite. | `pve-ha-crm` |
| 00:42:29 | pveelite | **Primul OOM-kill VM 109** (kvm, 6.3 GB RSS). CT 108 (oracle 8 GB) tocmai pornea. | kernel oom-killer |
| 00:42 → 11:45 | pveelite | Buclă OOM infinită: HA repornește VM 109 și alte servicii fără limită (CT 104, CT 108 nu au `max_restart`). Zeci de OOM-kill per oră. | `pve-ha-lrm` + kernel |
| 00:39:47 | pvemini | Boot automat kernel 6.8.12-15-pve (BIOS auto-power-on, **NU** intervenție user). | kernel boot |
| 00:43 → 12:47 | pvemini | pvemini rulează normal ~12h (serviciile sale erau fence-uite pe pveelite). Chill. | - |
| 11:30 → 11:45 | pveelite | OOM începe să omoare și alte procese (containerd, tailscaled, pvefw-logger, ora_w003_xe, python3). | kernel |
| 11:45:35 | pveelite | Host nefuncțional, ultim log. | `journalctl --list-boots` |
| 11:46:41 | pveelite | Reboot (utilizator). | reboot history |
| 11:51:37 | pveelite | HA shutdown controlat VM 109 (user a schimbat HA state la `stopped`). | `pve-ha-lrm` |
| 11:53:37 | pveelite | HA shutdown controlat CT 105. | `pve-ha-lrm` |
| 12:02:09 | pveelite | Al doilea reboot (utilizator, cleanup). | reboot history |
| **12:47:30** | pvemini | Shutdown (**utilizator, prima intervenție pe pvemini azi**). | reboot history |
| 12:47:53 | pveelite | Shutdown. | reboot history |
| 12:49:50 | pvemini + pveelite | Boot simultan, cluster Quorate 3/3. | kernel boot |
---
## Analiză detaliată
### 1. Crash pvemini 00:23 — CAUZĂ NECUNOSCUTĂ
`pvemini` = HP ProDesk 600 G2 DM (i7-6700T, 32 GB RAM)... Actually corecție — sistemul DMI raportează "Venus Series" pentru pvemini (posibil Minisforum/Beelink mini PC). Verificare necesară.
Revenirea automată la 00:39 (fără power button) sugerează:
- **BIOS "AC Power Loss Recovery: Power On"** activ.
- **Kernel panic + automatic reboot** (dacă `kernel.panic=N` setat) — dar 16 min e prea lung pentru automatic reboot.
- **Hardware watchdog reset** cu delay — posibil.
- **Pană de curent scurtă** — neverificat (nu există `apcupsd` activ pe pvemini sau pveelite pentru jurnalizare evenimente UPS).
**Gol diagnostic total:** nu există `mcelog`, `kdump`, `netconsole`, IPMI SEL. Următoarea oară nu vom ști mai mult decât acum.
### 2. DR test script bug — CAUZĂ PRINCIPALĂ PREVENTIBILĂ
`proxmox/vm109-windows-dr/scripts/weekly-dr-test-proxmox.sh`, linia 507-511:
```bash
ssh -p "$DR_VM_PORT" "$DR_VM_USER@$DR_VM_IP" "shutdown /s /t 30" 2>/dev/null
sleep 60
qm stop "$DR_VM_ID" 2>/dev/null
track_step "VM Shutdown" true "VM stopped" "$step_start"
```
Scriptul are `set -euo pipefail`. Când VM 109 nu e SSH-reachable (cazul Apr 18, 03-21→04-18 toate), comanda ssh eșuează cu non-zero. **`set -e` termină scriptul imediat**, înainte de `qm stop`. VM 109 rămâne pornit.
Logurile tuturor testelor eșuate (21 martie → 18 aprilie, 5 săptămâni) au exact 1069 bytes — același punct de crash. VM 109 a fost pornit și nu a fost oprit niciodată după Apr 18.
### 3. HA recovery overload — CAUZĂ ARHITECTURALĂ
Când pvemini a căzut, HA a aplicat politica de recovery. `ha-group-main` are:
```
nodes pve1:33, pvemini:100, pveelite:50
```
pve1 = quorum-only (confirmat de user, dar HA nu știe asta — are pondere 33 în grup). HA a ales pveelite (pondere 50 > 33) pentru recovery.
Dar **pveelite (16 GB) nu poate găzdui serviciile pvemini** în stare normală, darămite peste ce rulează deja:
- CT 101 (minecraft, 8 GB) — deja pe pveelite
- CT 108 (central-oracle, 8 GB) — mutat de pe pvemini
- VM 109 (6 GB) — deja pe pveelite (din bug-ul DR)
- CT 100 + CT 104 + CT 106 — overhead ~3-4 GB
Total cerință ≥25 GB pe 16 GB host → OOM inevitabil.
În plus, CT 104 (flowise) și CT 108 (central-oracle) **nu aveau** `max_restart`/`max_relocate` definite. CT 100, CT 101, CT 106 aveau `max_restart=3 max_relocate=3`. Incoerență de configurare.
### 4. pve1 ca quorum-only — capacitate nefolosită
pve1 are i7-6700T (8 core) + 32 GB RAM. **Dar user confirmă**: este folosit exclusiv pentru quorum, nu pentru găzduire. Deci la failover HA nu are target adecvat pentru serviciile pvemini.
---
## Plan de prevenție
Ordinea reflectă **impactul real asupra incidentului**.
### P0 — Oprește bug-ul DR test (5 minute, OBLIGATORIU)
Scriptul trebuie să garanteze oprirea VM 109 chiar dacă SSH eșuează:
```bash
# Editare /opt/scripts/weekly-dr-test-proxmox.sh pe pveelite, linia ~505-511
# ÎNLOCUIEȘTE:
# ssh -p "$DR_VM_PORT" "$DR_VM_USER@$DR_VM_IP" "shutdown /s /t 30" 2>/dev/null
# sleep 60
# qm stop "$DR_VM_ID" 2>/dev/null
# CU:
# Încearcă shutdown soft; ignoră eșecul pentru a NU ieși din script
ssh -p "$DR_VM_PORT" -o ConnectTimeout=10 "$DR_VM_USER@$DR_VM_IP" \
"shutdown /s /t 30" 2>/dev/null || log_warning "SSH shutdown failed, forcing qm stop"
sleep 60
# Forțează oprire indiferent de starea SSH
qm stop "$DR_VM_ID" --skiplock 2>/dev/null || true
# Verificare finală — dacă încă pornit, forțează stop
if qm status "$DR_VM_ID" | grep -q "running"; then
qm stop "$DR_VM_ID" --skiplock --timeout 30 2>/dev/null || true
sleep 5
qm status "$DR_VM_ID" | grep -q "stopped" && log "VM $DR_VM_ID confirmed stopped" \
|| log_error "VM $DR_VM_ID still running after force stop"
fi
```
**Alternativ, cleanup global la sfârșitul scriptului** (pattern `trap`):
```bash
cleanup_vm() {
log "Cleanup: ensuring VM $DR_VM_ID is stopped"
qm stop "$DR_VM_ID" --skiplock 2>/dev/null || true
}
trap cleanup_vm EXIT # rulează la orice ieșire, inclusiv set -e
```
### P0 — Limite de restart pe toate resursele HA (1 minut)
CT 104 și CT 108 lipsesc limitele. Uniformizează:
```bash
ssh root@10.0.20.200 bash <<'EOF'
ha-manager set ct:104 --max_restart 3 --max_relocate 2
ha-manager set ct:108 --max_restart 3 --max_relocate 2
ha-manager set vm:109 --max_restart 0 --max_relocate 0
# VM 109 nu trebuie gestionat de HA deloc
ha-manager config
EOF
```
`max_restart=0 max_relocate=0` pentru VM 109 = HA nu încearcă să-l repornească. Combinat cu `state stopped` → VM 109 rămâne oprit până cineva îl pornește explicit (scriptul DR).
### P0 — Scoate VM 109 din HA (recomandare)
VM 109 e un DR test VM, nu un serviciu live. Nu ar trebui gestionat de HA.
```bash
# Șterge complet din HA
ha-manager remove vm:109
```
Scriptul DR va folosi `qm start 109` pe pveelite (unde rulează scriptul). HA nu va mai interveni. Eliminarea rezolvă și failover-ul nedorit către pveelite.
### P1 — Re-arhitecturare HA recovery pentru pvemini crash
**Problema:** dacă pvemini cade, serviciile sale (CT 108 Oracle 8 GB + CT 104 flowise + CT 100 portainer + CT 106 gitea) nu încap pe pveelite (16 GB).
**3 opțiuni, alege una:**
**Opțiunea A — Acceptă downtime pentru Oracle la crash pvemini (SIMPLU)**
```bash
# Scoate CT 108 din HA (acceptă manual restart dacă pvemini cade)
ha-manager remove ct:108
# CT 108 va porni doar cu onboot=1, pe pvemini, manual după crash
```
**Pro:** pveelite nu mai e sufocat. **Contra:** Oracle DB (serviciul critic) nu se recuperează automat.
**Opțiunea B — Permite pve1 să preia serviciile critice (SCALARE)**
User a spus că pve1 e quorum-only, dar are 32 GB RAM liberi. Dacă rolul ar putea fi extins:
```bash
# Modifică ha-group-main să prefere pve1 peste pveelite
cat > /etc/pve/ha/groups.cfg <<'EOF'
group: ha-group-main
nodes pvemini:100,pve1:75,pveelite:25
nofailback 0
restricted 0
EOF
```
**Pro:** CT 108 ar putea merge pe pve1 (32 GB) în loc de pveelite. **Contra:** pve1 devine parte activă din cluster, nu mai e doar quorum.
**Opțiunea C — Investește în redundanță pvemini (HARDWARE)**
Dacă pvemini e singurul punct de failure real, atunci: RAID, UPS dedicat, backup nod identical. Scump, dar evită problema.
**Recomandare:** Opțiunea A pentru CT 108 (Oracle DB acceptă downtime de 5-10 min pentru reintervenție manuală) + păstrează HA pentru CT 100/104/106 (lightweight, pot sta pe pveelite temporar).
### P1 — Swap pe pveelite (10 minute, insurance)
```bash
ssh root@10.0.20.202 bash <<'EOF'
zfs create -V 8G -b 4K -o compression=zle -o logbias=throughput \
-o sync=always -o primarycache=metadata -o secondarycache=none \
rpool/swap
mkswap -f /dev/zvol/rpool/swap
echo "/dev/zvol/rpool/swap none swap sw 0 0" >> /etc/fstab
swapon -a
echo "vm.swappiness=10" > /etc/sysctl.d/99-swap.conf
sysctl -p /etc/sysctl.d/99-swap.conf
EOF
```
Swap = scade OOM-killer trigger (dă timp pentru migrare/fallback) dar e bandage, nu fix.
### P2 — Diagnostic crash pvemini
```bash
ssh root@10.0.20.201 bash <<'EOF'
apt update && apt install -y mcelog kdump-tools
systemctl enable --now mcelog
# kdump: în /etc/default/grub adaugă crashkernel=256M
# netconsole către pve1
modprobe netconsole netconsole=@10.0.20.201/vmbr0,6666@10.0.20.200/
echo "options netconsole netconsole=@10.0.20.201/vmbr0,6666@10.0.20.200/" >> /etc/modprobe.d/netconsole.conf
# Watchdog NMI pentru hang detection
echo "kernel.nmi_watchdog=1" > /etc/sysctl.d/99-nmi.conf
sysctl -p /etc/sysctl.d/99-nmi.conf
EOF
# Verifică BIOS update la Minisforum/Beelink — ultimul versiune disponibilă
# memtest86+ bootabil la următoarea mentenanță
```
### P2 — Configurare UPS monitoring
Niciun nod nu are `apcupsd`/`nut` pornit → nu există log când pică curentul. Dacă pvemini e pe UPS, configurează monitorizare:
```bash
apt install apcupsd
# Configurare /etc/apcupsd/apcupsd.conf per setup UPS
# Jurnalizare evenimente în /var/log/apcupsd.events
```
### P3 — Alertare OOM + node-down
```bash
# /opt/scripts/oom-alert.sh — cron */1 * * * *
#!/bin/bash
COUNT=$(journalctl --since "1 minute ago" -k | grep -c "Killed process")
[ "$COUNT" -gt 0 ] && echo "OOM x$COUNT on $(hostname)" | \
mail -s "[ALERT] OOM $(hostname)" proxmox@romfast.ro
```
Plus: fix DKIM/SPF pe `romfast.ro` (Gmail a respins notificarea în dimineața incidentului — vezi log 00:00:02).
---
## Acțiuni — executate 2026-04-20 13:0014:00
- [x] **P0-1** Fix `weekly-dr-test-proxmox.sh` — trap `cleanup_vm EXIT` + SSH shutdown `|| log_warning` (pveelite:/opt/scripts/)
- [x] **P0-2** `ha-manager set ct:104 ct:108 --max_restart 3 --max_relocate 2`
- [x] **P0-3** `ha-manager remove vm:109` — VM 109 nu mai e gestionat de HA
- [x] **P1-1** Corosync token mărit la 10 s (`config_version: 16`) — tolerează glitch-uri USB pveelite
- [x] **P1-2** Swap 8 GB pe pveelite (ZFS zvol `rpool/swap`, `vm.swappiness=10`)
- [x] **P2-1** `rasdaemon` instalat + activ pe pvemini (MCE + PCIe AER monitoring)
- [x] **P2-2** `netconsole` pvemini → pve1 (log: `/var/log/netconsole-pvemini.log`, systemd unit `netconsole-receiver`)
- [x] **P2-3** `kernel.panic=10` pe pvemini (auto-reboot la panic după 10s)
## Rămas de făcut (opțional, necesită reboot sau decizie)
- [ ] **kdump-tools** pe pvemini — captură kernel crash dump (necesită `crashkernel=256M` în GRUB + reboot)
- [ ] **Fix DKIM/SPF `romfast.ro`** — Gmail respinge notificările (vezi log 2026-04-20 00:00:02)
- [ ] **apcupsd/nut** monitorizare UPS pe pvemini (cablul UPS Cypress USB-to-Serial e conectat, dar nu există jurnal evenimente power event)
- [ ] **Al 2-lea link corosync** pentru pveelite prin eno1 (necesită cablu fizic în NIC integrat)
- [ ] **Alertare OOM** — cron `oom-alert.sh` cu mail la fiecare `Killed process`
- [ ] **Cauza 00:23 crash pvemini****necunoscută**. Dacă se repetă, `netconsole` + `rasdaemon` ar trebui să dea indicii.
---
## Anexă — verificări
```bash
# Confirmare VM 109 oprit
ssh root@10.0.20.202 "qm status 109; ha-manager status | grep 109"
# Verificare limite HA după fix
ssh root@10.0.20.200 "ha-manager config"
# Confirmare pveelite stabil
ssh root@10.0.20.202 "free -h; journalctl -k --since today | grep -c 'Killed process'"
# Verificare DR script fix
ssh root@10.0.20.202 "head -520 /opt/scripts/weekly-dr-test-proxmox.sh | tail -25"
```

View File

@@ -4,6 +4,26 @@
**VMID:** 109
**Rol:** Disaster Recovery pentru Oracle Database (backup RMAN de pe server Windows extern)
## ⚠️ Important — VM 109 NU este în HA (din 2026-04-20)
După incidentul 2026-04-20 (vezi `../cluster/incidents/2026-04-20-cluster-outage.md`), VM 109 a fost scos din HA cu `ha-manager remove vm:109`. Motivele:
- VM 109 este un DR test VM, nu un serviciu live
- Scriptul DR test de sâmbătă (`scripts/weekly-dr-test-proxmox.sh`) pornește/oprește VM 109 manual cu `qm start/stop`
- Cu HA activ, un bug `set -e` în script a lăsat VM 109 pornit 2.5 zile, apoi la crashul pvemini HA a relocat VM 109 pe pveelite (16 GB) → OOM cascade
**Efecte:**
- VM 109 NU mai e repornit automat la crash node
- VM 109 NU se mai mută de pe pvemini
- VM 109 pornește DOAR la invocarea scriptului DR sau manual cu `qm start 109`
- Scriptul DR are acum `trap cleanup_vm EXIT` care garantează `qm stop 109` la orice ieșire
**Verificare status:**
```bash
ssh root@10.0.20.201 "qm status 109" # trebuie stopped
ssh root@10.0.20.201 "ha-manager status | grep 109 || echo 'nu e în HA'"
```
---
# 🛡️ Oracle DR System - Complete Architecture

View File

@@ -22,6 +22,19 @@
set -euo pipefail
# Cleanup trap: ensure VM 109 is always stopped on script exit
# Fixes incident 2026-04-20: script crashed at SSH step and left VM 109 running
# for 2.5 days, causing OOM cascade on pveelite after pvemini HA failover.
cleanup_vm() {
local rc=$?
if qm status "${DR_VM_ID:-109}" 2>/dev/null | grep -q running; then
echo "[trap] VM ${DR_VM_ID:-109} still running at exit (rc=$rc), forcing stop"
qm stop "${DR_VM_ID:-109}" --skiplock 2>/dev/null || true
fi
exit $rc
}
trap cleanup_vm EXIT
# Set proper PATH for cron execution
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
@@ -504,7 +517,8 @@ run_dr_test() {
step_start=$(date +%s)
log "STEP 7: Shutting down VM"
ssh -p "$DR_VM_PORT" "$DR_VM_USER@$DR_VM_IP" "shutdown /s /t 30" 2>/dev/null
ssh -p "$DR_VM_PORT" -o ConnectTimeout=10 "$DR_VM_USER@$DR_VM_IP" "shutdown /s /t 30" 2>/dev/null \
|| log_warning "SSH shutdown failed, will force qm stop"
sleep 60
qm stop "$DR_VM_ID" 2>/dev/null