BGP mode isn't just about CRD configuration — it's about network design. This episode covers configuring multiple peers, using routerID, planning the advertised subnets, placing IP pools, and coordinating with firewalls so peering is secure and stable.

BGP mode in episode 6 stopped at a single simple peer. In the real world, a cluster with just one router is rare. Peering & network design determines whether your BGP mode will be stable and easy to maintain — or a source of headaches down the road. Episode 13 covers network design comprehensively: multiple peers, routerID, advertised subnets, pool placement, and firewalls.
Good design means adding a Service only adds an IP to a pool — without touching routers at all. Bad design means every new Service requires coordination with the network team. The goal of this episode: build the right design mindset from the start.
Production clusters usually have more than one router or L3 switch for redundancy. MetalLB can peer with many routers at once — each peer is a separate BGPPeer resource:
apiVersion: metallb.io/v1beta1
kind: BGPPeer
metadata:
name: core-a
namespace: metallb-system
spec:
myASN: 64500
peerASN: 64512
peerAddress: 192.168.1.1
---
apiVersion: metallb.io/v1beta1
kind: BGPPeer
metadata:
name: core-b
namespace: metallb-system
spec:
myASN: 64500
peerASN: 64512
peerAddress: 192.168.1.2With these two peers, the routes MetalLB advertises reach the network through two paths. If one router dies, the peering session to it drops, but the routes remain available through the other router.
Check that both sessions establish:
kubectl get bgppeer
kubectl describe bgppeer core-akubectl get bgppeer lists all peers in one view. Each one's status can be seen via kubectl describe bgppeer core-a — look for a condition indicating the BGP session is Established.
BGP identifies sessions by a router ID. If not configured, MetalLB uses an IP address from one of the node's interfaces — which can change and cause confusion. Setting an explicit routerID keeps each node's identity stable and predictable:
apiVersion: metallb.io/v1beta1
kind: BGPPeer
metadata:
name: core-b
namespace: metallb-system
spec:
myASN: 64500
peerASN: 64512
peerAddress: 192.168.1.2
routerID: 192.168.0.10routerID: 192.168.0.10 gives the node a fixed identity in the routers' eyes. Make sure the routerID is unique across the whole cluster and network — colliding routerIDs can cause unstable BGP sessions.
One of the biggest design decisions: which subnet is used for Service IPs, and whether those IPs are advertised to the entire network or only certain segments. General recommendations:
Remember aggregationLength from episode 8: with aggregation, a subnet like 192.168.20.0/24 is advertised as a single route rather than per-IP. This shrinks the router's routing table and simplifies the network team's policy.
kubectl get bgpadvertisement -o widekubectl get bgpadvertisement -o wide shows the advertisements along with their aggregation options. Before changing the design, always consult the network team about the subnets being advertised — a leaked route can affect the entire network.
If the cluster spans several network segments, create a separate pool per segment. For example, segment 10.0.10.0/24 for internal and 10.0.20.0/24 for public:
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
name: segmen-internal
namespace: metallb-system
spec:
addresses:
- 10.0.10.200-10.0.10.240
---
apiVersion: metallb.io/v1beta2
kind: IPAddressPool
metadata:
name: segmen-publik
namespace: metallb-system
spec:
addresses:
- 10.0.20.200-10.0.20.240With this separation, internal and public Services can be announced to different segments — for example via nodeSelectors and interfaces from episode 8. This structure is far easier to maintain than one giant pool covering everything.
Pool placement must reflect the physical topology: IPs announced over Layer 2 must be in a subnet reachable via ARP; IPs advertised over BGP must fall within a block the router is allowed to accept. Violating these rules is the most common source of "IP unreachable" problems.
BGP uses TCP port 179. BGP peering requires direct communication between every node and the peer router on this port. Check the firewall between them:
nc -zv 192.168.1.1 179nc -zv 192.168.1.1 179 tests whether port 179 on the peer router is reachable from the node. If not, the firewall is blocking peering — one of the hidden reasons why BGP sessions never establish.
kubectl get bgppeer
kubectl logs -n metallb-system -l component=speaker --tail=30 | grep -i bgpkubectl logs -n metallb-system -l component=speaker --tail=30 | grep -i bgp shows peering-related log lines — a quick way to see whether a session established or is stuck in Connect status. This is the first diagnostic step we'll reuse in episode 19.
Episode 13 completes peering and network design: multiple peers for redundancy, a stable routerID, planning advertised subnets, placing pools per segment, and firewall coordination for the BGP port.
Key takeaways:
BGPPeer per router so redundant paths are available.routerID keeps node identity stable in the routers' eyes.kubectl get bgppeer and speaker logs are a quick peering status check.In the next episode, episode 14, we'll discuss security & access control — RBAC permissions for the controller and speaker, hardening the namespace, restricting access to management and health check ports, and protecting MetalLB configuration from unauthorized changes.