From 9c6808cb8918239513f5b01351c8731b2a833955 Mon Sep 17 00:00:00 2001 From: Peter Sprygada Date: Sun, 2 Aug 2026 20:03:44 -0400 Subject: [PATCH 1/2] feat: add operational hardening defaults to fabric-router DaemonSet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds livenessProbe (pidof zebra/bgpd), resource requests/limits, a preStop hook for graceful FRR shutdown, and rollingUpdate strategy — all standard, environment-agnostic defaults for an FRR DaemonSet so every consumer (prod, staging, containerlab) gets them without needing a per-environment patch. Co-Authored-By: Claude Sonnet 5 --- config/fabric/daemonset.yaml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/config/fabric/daemonset.yaml b/config/fabric/daemonset.yaml index 35c6e84..82a44ea 100644 --- a/config/fabric/daemonset.yaml +++ b/config/fabric/daemonset.yaml @@ -9,6 +9,10 @@ spec: selector: matchLabels: app.kubernetes.io/name: fabric-router + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 template: metadata: labels: @@ -75,12 +79,32 @@ spec: containers: - name: frr image: ghcr.io/datum-cloud/fabric-router:latest + lifecycle: + preStop: + exec: + command: + - /usr/lib/frr/frrinit.sh + - stop securityContext: capabilities: add: - NET_ADMIN - NET_RAW - SYS_ADMIN + livenessProbe: + exec: + command: + - sh + - -c + - pidof zebra bgpd + initialDelaySeconds: 10 + periodSeconds: 30 + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + memory: 256Mi volumeMounts: - name: frr-etc mountPath: /etc/frr From 9861ef14d3742f4f234e0a8083626d487d10ffa1 Mon Sep 17 00:00:00 2001 From: Peter Sprygada Date: Sun, 2 Aug 2026 20:17:55 -0400 Subject: [PATCH 2/2] fix: harden fabric-router probes and add priorityClass/dnsPolicy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Research against Calico/MetalLB/Cilium's production FRR/BGP DaemonSets surfaced several gaps versus real-world practice: - pidof zebra bgpd only proves the processes are resident, not that they're responsive, and passes as long as any one of the named processes is alive. Replace with per-daemon vtysh checks (`vtysh -d -c "show version"`) — verified via FRR source that `vtysh -c "show daemons"` silently omits unreachable daemons from its exit code, so it wouldn't have caught a dead bgpd either. - Add a startupProbe so a slow config load (peer groups, route-maps, prefix-lists) doesn't get killed by liveness before it's up. - Add priorityClassName: system-node-critical, matching calico-node and cilium-agent, so the speaker isn't evicted under node pressure. - Add dnsPolicy: ClusterFirstWithHostNet, required alongside hostNetwork: true and missing before now. - Bump cpu request 50m -> 100m to absorb BFD/convergence bursts. terminationGracePeriodSeconds is intentionally left untouched: calico-node and MetalLB's speaker both ship low values (0s and 2s) rather than stretching it to match BGP hold-timers, relying on BFD for fast peer-side failure detection instead of a k8s-side graceful drain. Co-Authored-By: Claude Sonnet 5 --- config/fabric/daemonset.yaml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/config/fabric/daemonset.yaml b/config/fabric/daemonset.yaml index 82a44ea..2b23175 100644 --- a/config/fabric/daemonset.yaml +++ b/config/fabric/daemonset.yaml @@ -19,6 +19,8 @@ spec: app.kubernetes.io/name: fabric-router spec: hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + priorityClassName: system-node-critical # FRR here establishes the underlay eBGP session to the physical fabric # and brings up the node's lo address, both of which galactic-router # depends on before it can start — so this must tolerate NotReady the @@ -91,17 +93,27 @@ spec: - NET_ADMIN - NET_RAW - SYS_ADMIN + startupProbe: + exec: + command: + - sh + - -c + - vtysh -d zebra -c "show version" && vtysh -d bgpd -c "show version" + periodSeconds: 5 + failureThreshold: 30 livenessProbe: exec: command: - sh - -c - - pidof zebra bgpd + - vtysh -d zebra -c "show version" && vtysh -d bgpd -c "show version" initialDelaySeconds: 10 periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 5 resources: requests: - cpu: 50m + cpu: 100m memory: 64Mi limits: memory: 256Mi