# Oprire planificată a clusterului (lucrări la rețeaua electrică) Procedura de oprire controlată a tuturor celor 3 noduri Proxmox **fără ca HA să relocheze resursele** și **fără ca watchdog-ul să reseteze hard vreun nod**. Se aplică oricărei opriri planificate a întregului cluster: lucrări electrice, mutare rack, mentenanță UPS, intervenții la switch. **Autor:** Claude Code · **Ultima verificare pe cluster live:** 2026-08-29 --- ## Varianta cea mai rapidă — din dashboard sau Discord `/infra` De preferat variantei de mai jos (stație de admin), pentru o oprire/pornire simplă, fără lucrări la insula `10.10.10.0/24` sau la switch: 1. **Oprire:** tab Infrastructură → *Oprește* (sau Discord `/infra actiune:oprire`, confirmare). Rulează `cluster-shutdown.sh --allow-on-node --yes` pe **pvemini**, lansat detașat prin `systemd-run` (vezi [dashboard/README.md § Tab Infrastructură](../../lxc171-claude-agent/discord-bridge/dashboard/README.md#tab-infrastructur%C4%83)). CT 171 (claude-agent) **rămâne pornit** — moare odată cu pvemini la poweroff, iar `ha: shutdown_policy=freeze` îl repornește la revenirea nodului. La final se postează (și se încearcă fixarea) în Discord un mesaj cu instrucțiunile de pornire de mai jos + un email către `mmarius28@gmail.com`. 2. **Pornire, când revine curentul:** - JuiceSSH (prin Tailscale) → `10.0.20.36:22122` → rulează `C:\wolcluster.bat` (vezi [docs/acces-agenti-windows-birou-server36.md](../../../docs/acces-agenti-windows-birou-server36.md) pentru accesul pe .36 și alias-ul ssh `oracle-prod-admin` folosit și de acțiunea `wol` din dashboard). - Așteaptă mesajul „Cluster sus" în Discord (postat automat de `infra_boot_check` când clusterul are iar cvorum, dar crontab-ul e încă în mentenanță). - Apasă *Pornește guest-urile* (buton pe mesajul din Discord, sau tab Infrastructură → *Pornește*) — rulează `cluster-startup.sh --allow-on-node --yes` pe pvemini. 3. **Dacă CT 171 nu revine** (dashboard/bot nu mai răspund după poweroff): `ssh root@10.0.20.201 /opt/scripts/cluster-startup.sh --allow-on-node --yes` 4. **Fallback dacă WoL nu merge:** `wolmarius.bat` (de pe .36) trezește stația de birou, apoi `wake-cluster.ps1` de acolo. `cluster-shutdown.sh`/`cluster-startup.sh` au acum flag-ul `--allow-on-node`, care le permite să ruleze *pe* un nod (pvemini) în loc de pe stația de admin — guard-ul care le blochează pe un nod Proxmox e condiționat de acest flag; CT 171 rămâne exclus din lista de oprire explicită (`KEEP_RUNNING=171`) și din verificările de la pasul 7/8. Restul procedurii (varianta de pe stația de admin, PowerShell/Bash, fără `--allow-on-node`) rămâne valabilă neschimbată — vezi mai jos. tmux e acum instalat pe toate cele 3 noduri, pentru rulări manuale lungi din consolă (nu e folosit de `--allow-on-node`, care lansează prin `systemd-run`). --- > **Atenție, s-a schimbat ceva important pe 2026-08-29.** Clusterul are acum o rețea > dedicată, `10.10.10.0/24` („insula"), pe un switch separat — vezi > [switch 2.5G dedicat nodurilor](switch-2.5g-dedicat-noduri.md). De ea atârnă > **toată replicarea ZFS** (`migration: network=10.10.10.0/24` în `datacenter.cfg`) > și storage-ul NFS `backup-pvemini-nfs` (server `10.10.10.201`). Pe pve1 și > pveelite IP-ul de insulă stă pe **dongle-ul USB**, deci la revenire trebuie > verificat că a urcat — vezi [Repornirea, pasul 3](#repornirea). --- ## Varianta automată Toată procedura de mai jos e implementată în două scripturi, de rulat **de pe stația de admin** (nu de pe un nod). Există în două variante echivalente — folosește-o pe cea potrivită shell-ului tău. **PowerShell (Windows, varianta obișnuită aici):** ```powershell cd E:\proiecte\ROMFASTSQL\proxmox\cluster\scripts .\cluster-shutdown.ps1 -DryRun # arată exact ce ar face, nu atinge nimic .\cluster-shutdown.ps1 # oprire completă, cu confirmări # ... după revenirea curentului ... .\wake-cluster.ps1 # trezește nodurile prin Wake-on-LAN .\cluster-startup.ps1 # repornire completă ``` **Wake-on-LAN merge pe toate trei nodurile** — verificat pe 2026-08-29, trezire în ~15 secunde. E posibil abia de la mutarea lui `vmbr0` pe interfețele onboard: dongle-urile USB nu suportă WoL și pierd alimentarea la oprire. Dacă lucrarea e la rețeaua electrică și nodurile sunt oprite de tine, `wake-cluster.ps1` te scutește de drumul până la ele. Stația de admin trebuie să fie pe același segment L2 (`10.0.20.0/24`) — magic packet-ul e broadcast, nu trece prin router. Cere doar clientul OpenSSH din Windows (`C:\Windows\System32\OpenSSH\ssh.exe`), deja prezent, și cheia SSH pentru root pe noduri. Testate pe PowerShell 5.1. Dacă politica de execuție blochează scriptul: `powershell -ExecutionPolicy Bypass -File .\cluster-shutdown.ps1 -DryRun` **Bash (Git Bash, WSL sau de pe CT 171 claude-agent):** ```bash cd proxmox/cluster/scripts ./cluster-shutdown.sh --dry-run ./cluster-shutdown.sh ./cluster-startup.sh ``` Cele două variante scriu același fișier de stare, deci poți opri cu una și porni cu cealaltă. `cluster-shutdown.sh` salvează local ce guest-uri rulau, iar `cluster-startup.sh` pornește **exact** ce era pornit — nu repornește VM-uri oprite intenționat. **Rulează întâi cu `--dry-run`.** Restul documentului explică de ce fiecare pas e necesar și cum se face manual din GUI, dacă preferi. --- ## TL;DR (procedura manuală) 1. **Shutdown Policy = `Freeze`** ← fără asta, HA mută resursele. Din 2026-08-29 e deja setat permanent — doar verifică (Pas 0), nu adăuga o linie nouă în `datacenter.cfg` 2. Dezactivează cron-urile de alertă (`pvemini-down-alert`, `vm109-watchdog`, `pveelite-down-alert`, `oom-alert`) 3. Oprește guest-urile manual — **Oracle CT 108 primul**, cu `shutdown immediate` în DB 4. `ha-manager status` → toate serviciile trebuie să fie `stopped` 5. Oprește nodurile: **pveelite → pve1 → pvemini** La revenire: pornești **toate trei nodurile aproape simultan** (altfel nu ai quorum), apoi verifici că insula `10.10.10.0/24` a urcat pe pve1 și pveelite **înainte** de a porni guest-urile. --- ## De ce nu poți pur și simplu să apeși „Shutdown" ### Capcana 1 — politica implicită de shutdown este `conditional` Fără o linie `ha:` în `/etc/pve/datacenter.cfg`, PVE folosește default-ul `shutdown_policy=conditional`: | Acțiune pe nod | Comportament HA cu `conditional` | |----------------|----------------------------------| | **Reboot** | freeze — serviciile rămân pe nod | | **Shutdown (poweroff)** | **failover** — serviciile se relochează pe alt nod | Adică exact ce vrei să eviți: un „Shutdown" pe pvemini trimite CT 108 Oracle, VM 201 și restul resurselor HA pe pve1/pveelite — pe noduri care oricum urmează să fie și ele oprite, cu 16 GB RAM pe pveelite și riscul din [incidentul 2026-04-20](../incidents/2026-04-20-cluster-outage.md). > **Din 2026-08-29 capcana asta e deja dezamorsată permanent.** Fișierul > `/etc/pve/datacenter.cfg` **există** și conține `ha: shutdown_policy=freeze`. > Pasul 0 de mai jos e, în mod normal, doar o verificare. Nu presupune că fișierul > lipsește — mai conține și linia `migration:`, care nu trebuie pierdută. ### Capcana 2 — watchdog-ul se auto-fence la pierderea quorumului Cu 3 noduri, quorum = 2. Dacă oprești două noduri și al treilea **încă are servicii HA active**, LRM-ul pierde agent lock-ul și watchdog-ul face **reset hard** după ~60 s. Nu shutdown curat — reset brutal, peste Oracle pornit. Soluția e la Pasul 3: cu toate resursele HA în state `stopped`, LRM-ul nu mai are nimic activ, **watchdog-ul nu mai e armat**, iar pierderea quorumului devine inofensivă. ### Ce să NU faci - ❌ **Nu folosi node maintenance mode** (`ha-manager crm-command node-maintenance enable `) — acela migrează *intenționat* resursele, exact opusul scopului. - ❌ **Nu opri două noduri și nu lăsa unul pornit cu servicii HA active** — vezi capcana 2. - ❌ **Nu lăsa nodul să oprească el guest-urile** — Oracle și Windows au nevoie de shutdown curat, nu de timeout. --- ## Pas 0 — Shutdown Policy = Freeze De obicei **nu ai nimic de făcut aici** — politica e `freeze` din 2026-08-29. Verifică întâi: ```bash ssh root@10.0.20.201 "cat /etc/pve/datacenter.cfg" ``` Așteptat (ambele linii): ``` ha: shutdown_policy=freeze migration: network=10.10.10.0/24,type=insecure ``` Dacă `shutdown_policy` **nu** e `freeze`, **nu adăuga o linie nouă cu `>>`** — fișierul are deja o linie `ha:`, iar a doua e o duplicare. Comanda corectă înlocuiește linia existentă și lasă `migration:` neatinsă: ```bash ssh root@10.0.20.201 "cp /etc/pve/datacenter.cfg /root/datacenter.cfg.backup-mentenanta && \ sed -i '/^ha:/d' /etc/pve/datacenter.cfg && \ printf 'ha: shutdown_policy=freeze\n' >> /etc/pve/datacenter.cfg && \ cat /etc/pve/datacenter.cfg" ``` **GUI (echivalent):** `Datacenter → Options → HA Settings → Edit → Shutdown Policy: Freeze` > **Nu șterge linia `migration:`.** Fără ea replicarea ZFS se întoarce tăcut pe > rețeaua de producție — merge, dar pe altă cale decât cea proiectată, iar > traficul de replicare ajunge peste producție. `Freeze` = la oprirea nodului serviciile HA sunt înghețate, **nu relocate**; repornesc pe același nod când nodul revine. > **Recomandare permanentă:** lasă `freeze` și după intervenție. Docul de failover > descrie deja un incident în care VM 201 a migrat nedorit în timpul unei > mentenanțe — `freeze` e politica potrivită pentru acest cluster. --- ## Pas 1 — dezactivează alertele automate Altfel primești zeci de mailuri, iar `vm109-watchdog.sh` conține un `qm start 109` care poate porni VM 109 fix când nu trebuie. Ce trebuie dezactivat pe fiecare nod: | Nod | Script | De ce | |-----|--------|-------| | pveelite | `pvemini-down-alert.sh` | mail la fiecare minut cât pvemini e jos | | pveelite | `vm109-watchdog.sh` | conține `qm start 109` | | pveelite | `oom-alert.sh` | zgomot | | **pvemini** | **`vm109-watchdog.sh`** | **rulează și aici, nu doar pe pveelite** | | pvemini | `pveelite-down-alert.sh` | zgomot | | pvemini | `oom-alert.sh` | zgomot | | pve1 | `oom-alert.sh` | zgomot | Comandă unică, rulată pe fiecare nod — face backup și comentează exact liniile astea, lăsând restul crontab-ului neatins: ```bash for h in 10.0.20.200 10.0.20.201 10.0.20.202; do ssh root@$h 'crontab -l > /root/crontab.backup-mentenanta.txt; \ crontab -l | sed -E "/^[^#]/ s%^(.*(oom-alert|pvemini-down-alert|pveelite-down-alert|vm109-watchdog)\.sh.*)$%#MENTENANTA \1%" | crontab -' done ``` Restaurare după intervenție: ```bash for h in 10.0.20.200 10.0.20.201 10.0.20.202; do ssh root@$h 'crontab /root/crontab.backup-mentenanta.txt && crontab -l | grep -c MENTENANTA' done # trebuie sa intoarca 0 pe fiecare nod ``` > `pvemini-down-alert.sh` doar **trimite mail** cu comanda de failover, nu o > execută singur — verificat în cod. `vm109-watchdog.sh` însă chiar pornește VM 109, > și rulează pe **ambele** noduri (pvemini și pveelite). ### ⚠️ Dacă fereastra de lucrări prinde sâmbătă dimineața `weekly-dr-test-proxmox.sh` rulează **sâmbătă la 06:00, pe pvemini ȘI pe pveelite**, și **pornește VM 109**. Conform [incidentului 2026-04-20](../incidents/2026-04-20-cluster-outage.md), scriptul are istoric de a lăsa VM 109 pornit după un eșec (bug `set -e`) — exact declanșatorul buclei OOM de atunci. Dacă intervenția atinge sâmbătă 06:00, comentează-l pe ambele noduri. La fel `vm109-patch-window.sh` (zilele 1-7 ale lunii, ora 03:00) dacă fereastra prinde începutul de lună. ### Job-uri de backup Verifică dacă fereastra de lucrări prinde un job vzdump. Dacă da, dezactivează-l din `Datacenter → Backup` înainte: | Job | Program | |-----|---------| | `backup-impare-oracle` (CT 108) | zile impare 02:00 | | `backup-impare-rest` (100, 103, 106, 171) | zile impare 03:00 | | `backup-pare-flowise` (CT 104) | zile pare 02:00 | | `backup-pare-windows` (VM 201) | zile pare 03:30 | | `backup-pve1-minecraft` (CT 101) | zile impare 22:00 | | `backup-f1c87584` (VM 109) | sâmbătă 15:00, prima săptămână | Replicarea ZFS (`pvesr`) nu trebuie dezactivată — job-urile ratate se recuperează singure la primul tick după revenire. --- ## Pas 2 — oprește guest-urile manual Ordinea corectă e cea de **dependențe: consumatorii întâi, Oracle ULTIMUL**. VM 201 (IIS) și CT 104 (flowise) folosesc baza din CT 108. | # | Nod | Guest | În HA | Cum | |---|-----|-------|-------|-----| | 1 | pvemini | VM 303 Win11-Adina | Nu | Shutdown | | 2 | pvemini | VM 304 Win11-Marius | Nu | Shutdown | | 3 | pvemini | VM 302 oracle-test | Nu | Shutdown | | 4 | pvemini | VM 201 roacentral | Da | Shutdown (guest agent) | | 5 | pve1 | CT 101 minecraft | Da | Shutdown | | 6 | pve1 | CT 110 moltbot | Da | Shutdown | | 7 | pvemini | CT 104 flowise | Da | Shutdown | | 8 | pvemini | CT 106 gitea | Da | Shutdown | | 9 | pvemini | CT 103 dokploy | Da | Shutdown | | 10 | pvemini | CT 102 docker.romfast.ro | Nu | Shutdown | | 11 | pvemini | CT 100 portainer | Da | Shutdown | | 12 | pvemini | CT 171 claude-agent | Da | Shutdown | | 13 | pvemini | **CT 108 central-oracle** | Da | `shutdown immediate` în DB, apoi Shutdown CT | pveelite nu are nimic pornit în mod normal (CT 301 e template, nepornibil; VM 109 e `stopped`). > **Din CLI, folosește `ha-manager set --state stopped` pentru guest-urile > din HA**, nu `pct shutdown` / `qm shutdown`. Din linia de comandă acestea **nu** > actualizează state-ul HA, iar CRM-ul poate reporni guest-ul în mijlocul opririi. > Din GUI nu e o problemă — butonul Shutdown trece oricum prin HA. ### Oracle CT 108 — shutdown curat al bazei ```bash ssh root@10.0.20.201 "pct exec 108 -- docker exec oracle-xe bash -lc \ \"printf 'shutdown immediate\nexit\n' | sqlplus -s / as sysdba\"" ``` Abia după ce comanda întoarce `Database closed / Database dismounted / ORACLE instance shut down`, oprești containerul din GUI. ### Restul După ce Oracle e jos, poți folosi **Bulk Actions → Bulk Shutdown** pe fiecare nod. > Oprirea unui guest HA din GUI îi setează automat state-ul HA pe `stopped` — CRM-ul > nu îl va reporni. **Consecință:** la revenire trebuie să le pornești tu manual > (pornirea îi pune state-ul înapoi pe `started`). --- ## Pas 3 — verificare obligatorie înainte de oprirea nodurilor ```bash ssh root@10.0.20.201 "ha-manager status" ``` **Toate** liniile `service ...` trebuie să arate `(nod, stopped)`. Dacă vreuna arată `started`, `migrate`, `relocate` sau `fence` — **oprește-te**. Nu opri niciun nod până nu se stabilizează, altfel intri fix în scenariul de la capcana 2. Verificare rapidă că nu a mai rămas nimic pornit: ```bash for h in 10.0.20.200 10.0.20.201 10.0.20.202; do echo "=== $h ===" ssh root@$h "pct list; qm list" done ``` --- ## Pas 4 — oprirea nodurilor Ordine: **pveelite (.202) → pve1 (.200) → pvemini (.201)** pvemini ultimul: e nodul principal și serverul NFS. GUI: selectezi nodul în arbore → **Shutdown** (dreapta sus). Așteaptă ca nodul să nu mai răspundă la ping înainte de a-l opri pe următorul. --- ## Repornirea 1. **Pornește toate trei nodurile aproximativ simultan** — fizic, sau cu `.\wake-cluster.ps1` (Wake-on-LAN, verificat pe 2026-08-29). Un singur nod pornit nu are quorum → `/etc/pve` rămâne read-only → nu poți porni niciun guest și nu poți modifica nimic în GUI. 2. Așteaptă quorum complet: ```bash ssh root@10.0.20.201 "pvecm status" # Quorate: Yes, Total votes: 3 ssh root@10.0.20.201 "ha-manager status" ``` 3. **Verifică rețeaua de cluster `10.10.10.0/24` — pasul cel mai ușor de uitat.** Pe pve1 și pveelite IP-ul de insulă stă pe dongle-ul USB, adus la boot de un `auto enx...` din `/etc/network/interfaces`. Dacă nucleul enumerează adaptorul USB **după** ce `networking.service` a terminat, interfața rămâne fără IP. Nodul pornește perfect normal pe producție — dar **replicarea ZFS și storage-ul NFS `backup-pvemini` tac**, fără nicio alertă. ```bash ssh root@10.0.20.200 "ip -br a | grep -E 'vmbr0|enx'" # 10.10.10.200 pe dongle ssh root@10.0.20.202 "ip -br a | grep -E 'vmbr0|enx'" # 10.10.10.202 pe dongle ssh root@10.0.20.201 "ip -br a | grep -E 'vmbr0|enp87s0'" # 10.10.10.201 pe enp87s0 ssh root@10.0.20.201 "ping -c1 -W2 10.10.10.200; ping -c1 -W2 10.10.10.202" ssh root@10.0.20.200 "findmnt -no SOURCE /mnt/pve/backup-pvemini" # 10.10.10.201:/mnt/backup ``` Dacă un IP lipsește, reparația e `ifreload -a` pe nodul respectiv: ```bash ssh root@10.0.20.202 "PATH=/usr/sbin:/sbin:/usr/bin:/bin ifreload -a" ``` pvemini are interfața de insulă onboard (Intel `enp87s0`) — el nu are problema asta. **Testat pe 2026-08-29, la o oprire completă reală: insula a urcat singură pe toate trei nodurile.** Ipoteza enumerării târzii nu s-a materializat. Pe pve1 s-a declanșat în plus și regula udev `usb-lan-hotplug@` la boot, care oricum ar fi reparat-o. Verificarea rămâne totuși în procedură — un singur test reușit nu exclude o cursă de sincronizare care depinde de temporizări. **Ce a găsit totuși testul:** o linie rămasă în `/etc/fstab` pe pve1 și pveelite monta storage-ul NFS de pe `10.0.20.201` (producție) înainte ca `pvestatd` să apuce, deci backup-ul mergea tăcut pe rețeaua greșită, cu `storage.cfg` arătând corect. Liniile au fost comentate (backup: `/root/fstab.bak-2026-08-29`). Dacă vezi vreodată NFS-ul montat de pe alt server decât `10.10.10.201`, acolo să te uiți întâi. `cluster-startup` verifică asta automat. 4. **Pornește guest-urile în ordine inversă:** CT 108 Oracle întâi, apoi VM 201, apoi restul. Pornirea unui guest HA îi repune state-ul pe `started`. 5. Verifică Oracle: ```bash ssh root@10.0.20.201 "pct exec 108 -- docker exec oracle-xe bash -lc \ \"printf 'select status from v\\\$instance;\nexit\n' | sqlplus -s / as sysdba\"" ``` 6. **Re-activează cron-urile** dezactivate la Pasul 1 și job-urile de backup. 7. Verifică replicarea: ```bash ssh root@10.0.20.201 "pvesr status" ``` Job-urile `*/15` (108, 171, 201) au ratat rulări; recuperează la primul tick. 8. Decide ce faci cu Shutdown Policy — vezi recomandarea de la Pasul 0. În mod normal rămâne `freeze`, deci nu ai ce face. --- ## Capcane de mediu ### BIOS „Power On After AC Loss" Dacă setarea e pe **Power On**, nodurile pornesc singure în secunda în care revine curentul — posibil eșalonat, posibil înainte să fii tu pregătit. Primul nod care pornește nu are quorum. Incidentul 2026-04-20 conține exact acest simptom („pvemini revine SINGUR — BIOS auto-power-on sau watchdog reset"). Verifică setarea înainte de intervenție sau fii lângă servere la revenirea curentului. ### UPS Dacă lucrarea implică și UPS-ul, vezi `../ups/README.md` și `../ups/docs/UPS-SHUTDOWN-README.md` — NUT are propria logică de shutdown orchestrat care poate intra peste procedura de aici. --- ## Stare de referință a clusterului (2026-08-29) Resurse HA configurate — 10 în total: | Serviciu | Nod | Grup | Comentariu | |----------|-----|------|------------| | ct:100 | pvemini | ha-prefer-pvemini | portainer | | ct:101 | pve1 | ha-prefer-pve1 | minecraft | | ct:103 | pvemini | ha-prefer-pvemini | dokploy | | ct:104 | pvemini | ha-prefer-pvemini | flowise | | ct:106 | pvemini | ha-prefer-pvemini | gitea | | ct:108 | pvemini | ha-prefer-pvemini | central-oracle | | ct:110 | pve1 | ha-prefer-pve1 | moltbot | | ct:171 | pvemini | ha-prefer-pvemini | claude-agent | | vm:109 | pveelite | ha-prefer-pveelite | oracle-dr-windows (`stopped`) | | vm:201 | pvemini | ha-prefer-pvemini | roacentral | Guest-uri **în afara** HA: CT 102, CT 301, VM 302, VM 303, **VM 304**, VM 310. `nofailback` este `1` doar pe `ha-prefer-pveelite`; celelalte două grupuri au `nofailback 0`, deci resursele se întorc automat pe nodul preferat când acesta revine. Rețea și storage de care depinde procedura, verificate pe 2026-08-29: | Ce | Valoare | |---|---| | `datacenter.cfg` | `ha: shutdown_policy=freeze` + `migration: network=10.10.10.0/24,type=insecure` | | insulă pve1 / pvemini / pveelite | `10.10.10.200` (USB) / `10.10.10.201` (`enp87s0`) / `10.10.10.202` (USB) | | NFS `backup-pvemini-nfs` | server `10.10.10.201`, montat pe pve1 și pveelite | | corosync | **două linkuri**: `LINK ID 0` pe `10.0.20.20x`, `LINK ID 1` pe `10.10.10.20x`, `config_version: 17` | | Wake-on-LAN | merge pe toate 3 (`ethtool ` → `Wake-on: g`); unealta: `../scripts/wake-cluster.ps1` | --- ## Referințe - [Switch 2.5G dedicat nodurilor — rețeaua `10.10.10.0/24`](switch-2.5g-dedicat-noduri.md) - [Strategia de failover și HA](../failover/README.md) - [Incident 2026-04-20 — cluster outage](../incidents/2026-04-20-cluster-outage.md) - [Incident 2026-08-27 — pveelite fără rețea 16h (USB LAN reset)](../incidents/2026-08-27-pveelite-down.md) - [Cluster README — SSH, storage, noduri](../README.md) - [UPS](../ups/README.md)