Skip to content

feat: per-peer / per-instance routeLiveness (cascade over cluster default) - #5

Merged
mxhob1 merged 3 commits into
noden/mainfrom
feat/per-peer-route-liveness
Jun 6, 2026
Merged

mxhob1 merged 3 commits into
noden/mainfrom
feat/per-peer-route-liveness

Conversation

@mxhob1

@mxhob1 mxhob1 commented Jun 6, 2026

Copy link
Copy Markdown
Member

Follow-up to #4. Makes liveness gating selectable at three levels with a cascade — peer > instance > cluster-default — so it can be enabled surgically instead of fleet-wide.

CRD

  • Wireguard.spec.routeLiveness (instance default) and WireguardPeer.spec.routeLiveness (per-peer), enum disabled|passive|active, optional. CRDs regenerated.

Agent

  • Effective mode per peer = first explicitly-set of {peer, instance} else the cluster default (WG_ROUTE_LIVENESS env). Empty = inherit; an explicit disabled overrides downward (e.g. a fallback gateway forced always-on under an active instance).
  • The controller now tracks every peer passively, probes only effective-active peers, and IsLive branches per mode (disabled→always-live/ungated, passive→stall, active→stall+probe). Only gated peers drive transition→wg.Sync.
  • The watcher always runs (per-peer/instance can enable even when the cluster default is disabled); when everything resolves to disabled it's a cheap no-op read loop → routes static → byte-identical to current behavior.

Tests

Cascade resolution, per-peer mode resolution + ungated fallback, gated-only transitions, active probe/​revive. go build/vet/golangci-lint-full green; non-envtest unit packages pass (controller envtest + e2e in CI).

🤖 Generated with Claude Code

mxhob1 added 3 commits June 6, 2026 21:06
…Peer (per-peer) — enum disabled|passive|active
…r default); controller branches IsLive per mode, probes only active peers, gates only gated peers
…o KRO can render ""=inherit; agent validates
@mxhob1
mxhob1 merged commit ba5f12d into noden/main Jun 6, 2026
5 checks passed
mxhob1 added a commit that referenced this pull request Jun 6, 2026
Routes declared on a WireguardPeer (spec.routes/routesV6) are installed
unconditionally today. This adds an agent-side liveness gate so a peer's
routes are withdrawn from both AllowedIPs and the kernel route table when the
peer goes unreachable, and re-attached when it recovers — letting cluster→
tunnel traffic fail over to a broader, still-live peer (longest-prefix).

Modes (cascade: per-peer spec.routeLiveness > per-instance spec.routeLiveness
> cluster default WG_ROUTE_LIVENESS env):
  - disabled — routes always installed (current static behaviour; default)
  - passive  — withdraw when inbound goes silent (ReceiveBytes/handshake stall
               over a per-peer N*keepalive window)
  - active   — passive + a /32 UDP handshake probe; down after N unanswered,
               revived on progress

Gated peers start dead until confirmed reachable, so a broader live peer wins
the longest-prefix match during the initial bring-up window rather than
blackholing through a peer that hasn't completed a handshake yet.

Design notes:
  - The /32 peer address is always kept in AllowedIPs; only spec.routes are
    gated, so the control channel to the peer never drops.
  - New env knobs are delivered via the agent deployment template (operator env
    passthrough), not the CRD: WG_ROUTE_LIVENESS, WG_ROUTE_FAILURE_COUNT,
    WG_ROUTE_CHECK_INTERVAL, WG_ROUTE_PROBE_INTERVAL. Unset ⇒ disabled ⇒
    byte-identical to current behaviour.
  - The controller reconciles these WG_ROUTE_* env vars onto existing agent
    Deployments (by name), so a Deployment created before the setting was
    applied (or before it changed) picks it up instead of staying inert; no
    churn once they match.
  - spec.routeLiveness is a plain optional string (not apiserver-enum) so a
    renderer can always emit ""=inherit; the agent validates (unknown ⇒
    inherit, fail-safe).
  - Adds a wireguard_peer_routes_active gauge + transition logging.

Squashed from internal PRs #4 (core), #5 (per-peer/instance cascade), #6
(start-dead) and #7 (reconcile env on existing Deployments). Depends on the
peer Routes/RoutesV6 feature.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant