From 7b6409b631540e8d01791a642758bf4a79b6415d Mon Sep 17 00:00:00 2001 From: Debian Date: Sun, 7 Jun 2026 18:09:17 +0200 Subject: [PATCH] =?UTF-8?q?fix(cluster):=20VIPs=20nie=20statisch=20binden?= =?UTF-8?q?=20=E2=80=94=20Duplicate-IP-Kernbug=20=E2=80=94=20v1.2.102?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ergänzt v1.2.101: der ip-addresses-Apply (internal/services/ipaddresses/ apply.go) band ALLE aktiven Adressen statisch — inkl. is_vip. RenderSecondary (das eth0 ausschließt) ist toter Code, wird nie aufgerufen. Folge: die VIP (89.163.205.100 + VLAN-Gateways 10.0.x.1) lag auf dem Node statisch gebunden, UNABHÄNGIG von keepalived. Sobald keepalived die VIP per Failover auf den Peer legte, lag sie auf BEIDEN Nodes → Duplicate-IP/ARP- Konflikt → UniFi-Tunnel/LAN bricht (erklärt „utm-1 stoppen → sofort stabil": der Konflikt verschwindet, nicht VRRP-Failover). Fix: Render-Query schließt is_vip hart aus (AND ia.is_vip = false) → VIPs gehören ausschließlich keepalived (nur der VRRP-Master trägt sie). Gilt für beide Render-Pfade. Co-Authored-By: Claude Opus 4.8 (1M context) --- VERSION | 2 +- internal/services/ipaddresses/apply.go | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index b54183a..ff710f5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.101 \ No newline at end of file +1.2.102 \ No newline at end of file diff --git a/internal/services/ipaddresses/apply.go b/internal/services/ipaddresses/apply.go index e5400c2..2a28ebc 100644 --- a/internal/services/ipaddresses/apply.go +++ b/internal/services/ipaddresses/apply.go @@ -40,11 +40,17 @@ func (g *Generator) render(ctx context.Context, excludeEthernet bool) error { prefix int } + // is_vip-Adressen werden NIE statisch gebunden — sie gehören + // ausschließlich keepalived (nur der VRRP-Master trägt die VIP). Würde + // der Apply sie statisch binden, läge die VIP nach einem Failover auf + // BEIDEN Nodes (statisch hier + keepalived drüben) → Duplicate-IP/ARP- + // Konflikt → Tunnel/LAN bricht. Deshalb hart ausschließen. q := ` SELECT ni.name, ia.address, ia.prefix FROM ip_addresses ia JOIN network_interfaces ni ON ni.id = ia.interface_id - WHERE ia.active = true` + WHERE ia.active = true + AND ia.is_vip = false` if excludeEthernet { q += ` AND ni.type != 'ethernet'`