fix(ui): Standby-Node zeigt keinen "alle Backends down"-Fehlalarm mehr — v1.3.8

Der Dashboard-Down-Backends-Alarm liest die LIVE-HAProxy-Stats des lokalen
Nodes. Auf dem keepalived-BACKUP-Node erreicht die lokale HAProxy die Backend-
Subnetze nicht (VLAN-Gateway-VIPs liegen beim Master) → alle Backends L4-down.
v1.3.7 stoppte nur den alert_events-Spam (scheduler), nicht die Anzeige.

Jetzt: ist der Node BACKUP (vip_status.vrrp_state), wird der rote "N Backends
down"-Alarm durch einen ruhigen Info-Hinweis ersetzt ("Standby-Node — Backend-
Health lokal nicht aussagekräftig, Master bedient den Traffic"). Auf MASTER/
UNKNOWN bleibt der echte Alarm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-07-31 17:44:23 +02:00
parent 8e4759ccc6
commit 4856779db8
4 changed files with 20 additions and 2 deletions

View File

@@ -1 +1 @@
1.3.7 1.3.8

View File

@@ -454,6 +454,8 @@
"summaryCritical": "{{critical}} kritisch" "summaryCritical": "{{critical}} kritisch"
}, },
"downBackendsAlert": "{{count}} Backend(s) komplett ausgefallen — kein Server UP", "downBackendsAlert": "{{count}} Backend(s) komplett ausgefallen — kein Server UP",
"backupNodeBackends": "Standby-Node — Backend-Health lokal nicht aussagekräftig",
"backupNodeBackendsDesc": "Dieser Node ist gerade keepalived-BACKUP und hält die VLAN-Gateway-VIPs nicht, kann die Backend-Subnetze also nicht erreichen — die lokalen Health-Checks laufen deshalb alle auf Timeout. Kein Ausfall: der Master-Node bedient den Traffic. Nach einem Failover (VIP übernimmt dieser Node) werden die Backends hier UP.",
"maintenanceAlert": "{{count}} Domain(s) im Wartungs-Modus", "maintenanceAlert": "{{count}} Domain(s) im Wartungs-Modus",
"onboardingTitle": "Willkommen bei EdgeGuard", "onboardingTitle": "Willkommen bei EdgeGuard",
"onboardingIntro": "Frische Box — hier die nächsten Schritte um Customer-Traffic zu routen:", "onboardingIntro": "Frische Box — hier die nächsten Schritte um Customer-Traffic zu routen:",

View File

@@ -454,6 +454,8 @@
"summaryCritical": "{{critical}} critical" "summaryCritical": "{{critical}} critical"
}, },
"downBackendsAlert": "{{count}} backend(s) completely down — no server UP", "downBackendsAlert": "{{count}} backend(s) completely down — no server UP",
"backupNodeBackends": "Standby node — local backend health is not meaningful",
"backupNodeBackendsDesc": "This node is currently the keepalived BACKUP and does not hold the VLAN gateway VIPs, so it cannot reach the backend subnets — local health checks all time out. This is not an outage: the master node serves the traffic. After a failover (this node takes over the VIP), the backends will show UP here.",
"maintenanceAlert": "{{count}} domain(s) in maintenance mode", "maintenanceAlert": "{{count}} domain(s) in maintenance mode",
"onboardingTitle": "Welcome to EdgeGuard", "onboardingTitle": "Welcome to EdgeGuard",
"onboardingIntro": "Fresh box — here are the next steps to route customer traffic:", "onboardingIntro": "Fresh box — here are the next steps to route customer traffic:",

View File

@@ -303,6 +303,13 @@ export default function DashboardPage() {
return down return down
})() })()
// Auf dem keepalived-BACKUP-Node erreicht die lokale HAProxy die Backend-
// Subnetze nicht (die VLAN-Gateway-VIPs liegen beim Master) → sie sieht
// ALLE Backends als down. Das ist strukturell erwartet, kein Ausfall:
// der Master bedient den Traffic. Deshalb den roten Down-Alarm auf dem
// Standby durch einen ruhigen Hinweis ersetzen.
const isBackup = vipStatus.data?.vrrp_state === 'BACKUP'
const alerts = recentAlerts.data ?? [] const alerts = recentAlerts.data ?? []
const nCritical = alerts.filter(e => e.severity === 'critical' || e.severity === 'error').length const nCritical = alerts.filter(e => e.severity === 'critical' || e.severity === 'error').length
const nWarning = alerts.filter(e => e.severity === 'warning').length const nWarning = alerts.filter(e => e.severity === 'warning').length
@@ -366,13 +373,20 @@ export default function DashboardPage() {
)} )}
{/* ─ Operational alerts ─────────────────────────────── */} {/* ─ Operational alerts ─────────────────────────────── */}
{downBackends.length > 0 && ( {downBackends.length > 0 && !isBackup && (
<Alert <Alert
type="error" showIcon className="mb-12" type="error" showIcon className="mb-12"
message={t('dashboard.downBackendsAlert', { count: downBackends.length })} message={t('dashboard.downBackendsAlert', { count: downBackends.length })}
description={<Space wrap size={4}>{downBackends.map(n => <Link key={n} to="/backends">{n}</Link>)}</Space>} description={<Space wrap size={4}>{downBackends.map(n => <Link key={n} to="/backends">{n}</Link>)}</Space>}
/> />
)} )}
{downBackends.length > 0 && isBackup && (
<Alert
type="info" showIcon className="mb-12"
message={t('dashboard.backupNodeBackends')}
description={t('dashboard.backupNodeBackendsDesc')}
/>
)}
{maintenanceDomains.length > 0 && ( {maintenanceDomains.length > 0 && (
<Alert <Alert
type="warning" showIcon className="mb-12" type="warning" showIcon className="mb-12"