Loadbalancing Active Active
Active-Active Load Balancing with GoBGP, Keepalived, and IPVSADM
Unlike traditional active-passive setups where standby nodes sit idle, an active-active load balancing architecture uses all available load balancing nodes simultaneously. Traffic is horizontally scaled and distributed across all active nodes using Equal-Cost Multi-Path (ECMP) routing over BGP.
By combining GoBGP (for dynamic route advertisement), Keepalived (for local node health checking), and IPVSADM (for Layer 4 kernel-level packet forwarding), you can build a resilient, high-throughput active-active load balancing tier.
Active-Active Architecture Overview
In an ECMP-based active-active design, multiple independent load balancer nodes advertise the exact same Virtual IP (VIP) address to upstream Top-of-Rack (ToR) routers via BGP.
- Upstream Routers: Use ECMP to hash and distribute incoming connections evenly across all load balancing nodes advertising the VIP.
- Load Balancer Nodes: Simultaneously receive a portion of total incoming traffic and route it to backend real servers using LVS/IPVSADM.
- Failure Handling: If a load balancer node fails or its backend services go down, its GoBGP daemon stops advertising the VIP route. Upstream routers immediately remove the node from the ECMP pool without causing global downtime.
Component Roles
- IPVSADM / LVS (Linux Virtual Server): Operates inside the Linux kernel to perform Layer 4 (TCP/UDP) load balancing at near wire-speed.
- Keepalived: Performs continuous health checks against backend real servers and updates local IPVS configuration tables.
- GoBGP: A modern, high-performance BGP daemon written in Go. It interfaces with Keepalived/custom health scripts to dynamically advertise or withdraw the VIP route to upstream network switches.
Configure IPVSADM with Keepalived
Keepalived manages the IPVS kernel table and verifies that backend real servers are healthy.
Keepalived Configuration (/etc/keepalived/keepalived.conf)
global_defs {
router_id LB_NODE_01
}
# Define the local VIP on a dummy or loopback interface
# (Do NOT bind via VRRP; BGP will handle the routing)
virtual_server 192.168.100.1 80 {
delay_loop 3
lb_algo rr
lb_kind NAT
protocol TCP
real_server 10.0.1.11 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
retry 3
delay_before_retry 2
}
}
real_server 10.0.1.12 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
retry 3
delay_before_retry 2
}
}
}
Configure GoBGP for Route Advertisement
GoBGP connects to upstream routers (ToR switches) via BGP peering and advertises the /32 VIP host route.
GoBGP Configuration (/etc/gobgp/gobgpd.conf)
[global.config]
as = 65001
router-id = "10.0.0.1"
[[neighbors]]
[neighbors.config]
neighbor-address = "10.0.0.254" # Upstream Router IP
peer-as = 65000
[[neighbors.afi-safis]]
[neighbors.afi-safis.config]
afi-safi-name = "ipv4-unicast"
# Start GoBGP daemon
gobgpd -f /etc/gobgp/gobgpd.conf &
# Add VIP route advertisement
gobgp global rib add 192.168.100.1/32
Integrate Health Checks with Route Withdrawals
If all backend services behind an active-active node fail, the node must withdraw its VIP advertisement so the upstream router stops sending it ECMP traffic.
Create a health monitoring script (/usr/local/bin/bgp_healthcheck.sh):
#!/bin/bash
# /usr/local/bin/bgp_healthcheck.sh
VIP="192.168.100.1/32"
# Check if IPVS has active real servers
ACTIVE_SERVERS=$(ipvsadm -Ln | grep -c "Masq")
if [ "$ACTIVE_SERVERS" -gt 0 ]; then
# Ensure route is advertised
gobgp global rib | grep -q "192.168.100.1"
if [ $? -ne 0 ]; then
gobgp global rib add $VIP
fi
else
# Withdraw route if no backend real servers are healthy
gobgp global rib | grep -q "192.168.100.1"
if [ $? -eq 0 ]; then
gobgp global rib del $VIP
fi
fi
Verification & Failover Execution
Verify BGP Peering & ECMP
On your upstream switch, check that both load balancer nodes are actively peering and advertising the VIP:
Verify Kernel IPVS Rules
Run ipvsadm on each load balancer node:
Simulate node failure
Keepalived and VRRP
Keepalived was built around VRRP (Virtual Router Redundancy Protocol). In VRRP, Keepalived dynamically assigns or drops a Virtual IP (VIP) directly on the network interface.
In an Active-Active BGP (ECMP) setup, you do not use VRRP because all nodes must hold the VIP simultaneously on a dummy interface. Instead, route management is handed off to GoBGP. Because Keepalived isn't controlling the network interface or communicating directly with GoBGP, it has no native mechanism to tell GoBGP: "Hey, all my backends are dead, stop telling the network switch to send me traffic!"
The script acts as the bridge between Keepalived's application awareness and GoBGP's network awareness. It ensures that a node only advertises itself as a valid network path when it actually has healthy backend servers ready to process requests.