feat: Redesign gateway CRDs around DSR/Maglev datapath - #17
Merged
Conversation
Full-NAT (DNAT+SNAT) makes the gateway node that picked a backend also rewrite and forward every reply, so it stays a stateful bottleneck: one node owns the connections it accepted, and the API had to track which node that was (PrimaryNode, EgressAddress/EgressSID) instead of just the LB's health. Direct Server Return removes the gateway from the reply path entirely — the backend answers the client directly. The schema changes below follow from that: - NetworkGatewayStatus: drop SRv6Address/EgressAddress/EgressSID. A DSR gateway node rewrites nothing and has no SNAT/masquerade address of its own to publish; the type is now a per-node marker + health object. - NetworkRuleStatus: drop PrimaryNode. Every NetworkGateway serves every accepted rule identically (anycast, via consistent hashing on the flow 5-tuple) — no single node owns backend selection anymore. - NetworkEgressPolicyStatus: drop AssignedGatewayNode. Tenant egress (backend -> internet) is a different traffic pattern from ingress and moves to its own sharded, stateful NAT66 tier (NAT66Shard, below) with its own placement ring, instead of pinning a tenant to one gateway node. - New ServiceVIPBinding CRD: the backend-node half of DSR — binds the VIP to a dummy interface for a veth/container backend, or registers a transparent tap-boundary address substitution for a VM backend, so the backend can answer on the VIP directly. - New NAT66Shard CRD: marks a node as a member of the sharded egress NAT66 tier and publishes a dedicated per-shard public address/uSID, so a reply is routed to the owning shard by ordinary unicast routing with no cross-shard hashing on the return path. - BGPVRFInstanceSpec: add optional NPTv6 (ULAPrefix/PublicPrefix), a stateless RFC 6296 mapping keyed by VRFID rather than by address, so two VRFs can share an identical ULAPrefix without collision. Breaking change, no back-compat shim — the dropped fields have no meaning under the new datapath. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
scotwells
approved these changes
Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The gateway CRDs described a Full-NAT (DNAT+SNAT) load balancer, where the node that picked a backend also had to rewrite and forward every reply — a stateful bottleneck the API tracked via fields like
PrimaryNodeandEgressAddress. This redesigns them around a Maglev-style consistent-hash L4 load balancer running in DSR (Direct Server Return) mode: gateway nodes forward without rewriting, and backends answer clients directly.Breaking changes
NetworkGatewayStatus,NetworkRuleStatus, andNetworkEgressPolicyStatusdrop fields tied to the old NAT model (no meaning under DSR, no back-compat shim). Egress moves to a new sharded NAT66 tier instead of pinning a tenant to one gateway node. Two new CRDs,ServiceVIPBindingandNAT66Shard, cover the backend-side DSR binding and the sharded egress tier respectively.BGPVRFInstancegains an optional NPTv6 mapping.Test plan