Nach v1.2.102 (VIP nicht mehr statisch gebunden) wandert die Public-VIP .100 erstmals wirklich per keepalived zwischen den Node-MACs. Der Hosting-Upstream lernte die neue MAC aber nicht zuverlässig → .100 nach Schwenk von außen unerreichbar (vorher maskiert, weil .100 statisch dauerhaft auf utm-1 lag). Zwei Mechanismen ergänzt: 1) keepalived.conf.tpl global_defs: vrrp_garp_master_repeat 5 + vrrp_garp_master_refresh 60 (+ vrrp_garp_interval/gna 0, aus Legacy-Template verloren gegangen) → forciertes GARP beim Wechsel + periodische Auffrischung, damit die VIP-MAC am Switch nicht altert. 2) keepalived-master.sh: neuer Master pingt den Default-Gateway aus jeder Public-IP/VIP an (ping -I <vip>) → Upstream sieht Traffic VON der VIP und lernt die MAC sofort. Manche Hoster relearnen nur so, nicht via GARP. Test: keepalived_test.go prüft GARP-Direktiven im Render. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
42 lines
2.4 KiB
Bash
42 lines
2.4 KiB
Bash
#!/bin/bash
|
|
# Keepalived notify_master: dieser Node hat die VIP übernommen.
|
|
#
|
|
# KEIN Auto-Promote — Split-Brain-Schutz durch manuelle Promotion.
|
|
# Admin muss "edgeguard-ctl promote" ausführen wenn PG-Failover gewünscht.
|
|
|
|
logger -t keepalived -p daemon.warning \
|
|
"MASTER: VIP übernommen — PG-Rolle ist noch '$(cat /var/lib/edgeguard/pg_role 2>/dev/null || echo standby)'. Für PG-Failover: edgeguard-ctl promote"
|
|
|
|
# ── Upstream-ARP/Routing für die Failover-VIP(s) aktualisieren ──
|
|
# Manche Hoster lernen die neue MAC einer Failover-IP NICHT zuverlässig über
|
|
# Gratuitous-ARP, sondern erst, wenn sie Traffic VON der IP sehen. Ohne das ist
|
|
# die VIP nach einem Schwenk von außen unerreichbar. Wir pingen daher den
|
|
# Default-Gateway aus jeder Public-IP (inkl. VIP) an (source via -I), damit der
|
|
# Upstream die MAC sofort umlernt. Hintergrund-Pings, damit notify nicht blockt.
|
|
WAN_DEV="$(ip -4 route show default 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}')"
|
|
WAN_GW="$(ip -4 route show default 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="via"){print $(i+1); exit}}')"
|
|
if [ -n "$WAN_DEV" ] && [ -n "$WAN_GW" ]; then
|
|
for vip in $(ip -4 -o addr show dev "$WAN_DEV" scope global 2>/dev/null | awk '{print $4}' | cut -d/ -f1); do
|
|
ping -I "$vip" -c 3 -W 1 "$WAN_GW" >/dev/null 2>&1 &
|
|
done
|
|
logger -t keepalived -p daemon.info "MASTER: Upstream-ARP via Ping aus VIP(s) auf $WAN_GW ($WAN_DEV) angestoßen"
|
|
fi
|
|
|
|
# Dienste reloaden/starten damit sie die neu aktiven VIPs binden.
|
|
# Squid + Unbound + HAProxy binden beim Start an spezifische IPs — war der Dienst
|
|
# während des BACKUP-Zustands gecrasht oder gestoppt, muss er gestartet werden.
|
|
for svc in squid.service unbound.service haproxy.service; do
|
|
if systemctl is-active --quiet "$svc"; then
|
|
systemctl reload "$svc" 2>/dev/null || systemctl restart "$svc" 2>/dev/null || true
|
|
else
|
|
systemctl start "$svc" 2>/dev/null || true
|
|
fi
|
|
done
|
|
logger -t keepalived -p daemon.info "MASTER: squid/unbound/haproxy reload-or-start nach VIP-Übernahme"
|
|
|
|
# Alert an die API schicken (best-effort, ignoriert Fehler)
|
|
curl -sf --max-time 3 -X POST \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"level":"warning","message":"Keepalived MASTER: VIP übernommen. Wenn PG-Failover gewünscht: edgeguard-ctl promote ausführen.","source":"keepalived"}' \
|
|
http://127.0.0.1:9443/api/v1/internal/alert > /dev/null 2>&1 || true
|