LoadBalancer
A LoadBalancerClass configures how Lace assigns and advertises external VIPs for LoadBalancer Services. A Service opts in by setting spec.loadBalancerClass to lace-cni.io/<metadata.name>; the class then decides which address pool the VIP comes from and how it is advertised to the outside network.
Only class names carrying the lace-cni.io/ prefix are handled by Lace. A Service whose loadBalancerClass has the prefix but matches no class is reported as an error rather than silently left to another implementation.
apiVersion: lace-cni.io/v1alpha1kind: LoadBalancerClassmetadata: name: publicspec: mode: l2 ipv4Pools: - cidr: 198.51.100.0/24 - start: 203.0.113.10 end: 203.0.113.20 ipv6Pools: - cidr: 2001:db8:f00d::/64A Service selects the class above with loadBalancerClass: lace-cni.io/public.
Each class carries an ipv4Pools and/or ipv6Pools list; at least one must be non-empty. Each entry is either a cidr block or an inclusive start–end range. Entries are tried in order, falling through to the next when one is exhausted.
A Service gets one VIP per address family it is configured for, each allocated from the matching family’s pools. The families a Service can have are its own IP-family configuration, further constrained to the families the class actually provides a pool for.
Advertisements
Section titled “Advertisements”spec.mode selects how an allocated VIP is advertised to the surrounding network. Only l2 is implemented; l3 is reserved for a future BGP-based advertisement.
In L2 mode each allocated VIP is tracked by an L2Advertisement — one per VIP — which records the VIP, the owning Service, and the elected node. The VIP is attracted to a single node that answers for it on the local segment:
- Exactly one node is elected to advertise each VIP. The L2Advertisement doubles as the election lock: the winning node claims it and heartbeats its liveness, and a stale claim is taken over by another reachable node.
- The elected node answers ARP (IPv4) and NDP (IPv6) for the VIP, and on acquisition sends a gratuitous ARP / unsolicited Neighbor Advertisement so switches and peers re-point the VIP to it immediately.
- Only a node that can actually reach the VIP’s subnet is a candidate; a node with no route to the VIP never claims it.
The election only decides where external traffic enters the cluster. Routing the VIP onward to the Service’s endpoints is not tied to the elected node: every node programs the VIP into its data plane and load-balances it across the Service’s endpoints wherever they run. So the entry node forwards to a backing pod on any node, and a takeover changes only the ingress point, not reachability.
Requesting a specific VIP
Section titled “Requesting a specific VIP”A Service can ask for specific addresses with the loadbalancer.lace-cni.io/loadBalancerIPs annotation: a comma-separated list of at most one IPv4 and one IPv6 address. Each must fall within the class’s pools, and is claimed exactly if free.
apiVersion: v1kind: Servicemetadata: name: web annotations: loadbalancer.lace-cni.io/loadBalancerIPs: "198.51.100.7,2001:db8:f00d::7"spec: type: LoadBalancer loadBalancerClass: lace-cni.io/public # ...A requested address that is already taken or outside every pool is reported as an error on the Service instead of being silently replaced.