Learn Calico - BGP Peering & Routing
Episode 8 of 23

Learn Calico - BGP Peering & Routing

This episode dissects Calico BGP: the default node-to-node mesh, route reflectors for large clusters, BGPConfiguration, BGPPeer, peering with external routers, advertising pod CIDRs, and the MetalLB integration.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

In episode 4 we saw BGP propagate pod routes. Now we open that mechanism completely: how Calico chooses peers, how to change the BGP topology from full-mesh to route reflector, and how to connect the cluster to routers out there.

Mastering Calico BGP unlocks three big doors: the cluster can be routed directly from the outside network, LoadBalancers can be implemented with MetalLB, and clusters with thousands of nodes stay stable because peering doesn't grow quadratically.

The Calico BGP Model

Node-to-Node Full Mesh

By default, every Calico node opens a BGP peering to every other node — this topology is called full-mesh. The number of peerings grows quadratically: with 100 nodes there are about 4950 connections. For small clusters, this is simple and configuration-free. For large clusters, it's wasteful.

BGPConfiguration

Global BGP configuration is held by a BGPConfiguration resource named default. Here's an example that disables the mesh and sets an AS number:

Global BGPConfiguration
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  logSeverityScreen: Info
  nodeToNodeMeshEnabled: false
  asNumber: 64512
  serviceClusterIPs:
    - cidr: 10.96.0.0/12

nodeToNodeMeshEnabled: false disables the full-mesh; connections between nodes are then managed via BGPPeer. serviceClusterIPs allows advertising the Service CIDR to external peers — the basis of the MetalLB integration.

The Node Resource and Per-Node AS Numbers

Each node can be given its own AS number via the Node resource. Here's an example that tags a node for a different AS:

Node with a dedicated AS number
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  name: k8s-worker-01
spec:
  bgp:
    ipv4Address: 172.18.0.4
    asNumber: 64513

Route Reflector

Why a Route Reflector

For large clusters, the recommended topology is a route reflector: a small group of nodes becomes the hub that receives and propagates routes, while other nodes only peer to the reflectors. The number of connections drops from quadratic to linear.

Setting Up a Route Reflector

First disable the mesh, then label the node that will become the reflector:

Label the reflector node
kubectl label node k8s-master-01 route-reflector=true
calicoctl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: rr-k8s-master-01
spec:
  nodeSelector: route-reflector == 'true'
  peerSelector: all()
  asNumber: 64512
EOF

A BGPPeer with nodeSelector selects the reflector node, and peerSelector: all() lets the reflector accept peerings from all nodes. Note that here a single resource manages both sides of the peering at once.

Verifying Peering

Check BGP peering status
calicoctl node status
calicoctl get bgppeer -o wide
calicoctl get nodes -o wide | grep -E "NAME|BGP"

calicoctl get bgppeer lists the peer configurations, and calicoctl node status shows whether each one is Established.

Peering with External Networks

Connecting to a Data Center Router

When the cluster talks to the outside network without NAT, create a BGPPeer pointing at the router:

BGPPeer to an external router
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: dc-router
spec:
  peerIP: 203.0.113.10
  asNumber: 65000
  nodeSelector: all()

Once the peering is Established, the router will learn the pod CIDR routes 192.168.0.0/16 and can route directly to pods without NAT. This is the typical pattern for bare-metal or on-prem clusters.

Advertising and Receiving

To control which prefixes are advertised, BGPConfiguration uses serviceClusterIPs and serviceLoadBalancerIPs. Pod routes are always advertised; Service and LoadBalancer routes only if enabled.

The MetalLB Integration

MetalLB in BGP Mode

MetalLB provides LoadBalancers for bare-metal clusters. In BGP mode, MetalLB connects to the network as a peer, and Calico is responsible for advertising the LoadBalancer Service IPs to the router. To do this, the MetalLB IP pool is labeled, then advertised via BGPConfiguration:

Advertise LoadBalancer IPs
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  serviceLoadBalancerIPs:
    - cidr: 198.51.100.0/24

The flow:

MetalLB + Calico flow
Service LoadBalancer -> MetalLB picks an IP
     -> Calico advertises via BGP -> external router
     -> incoming traffic is routed to a node -> Service -> pod

Overall Verification

Verify LoadBalancer routing
calicoctl node status
kubectl get svc -n metallb-system
kubectl get bgpconfiguration default -o yaml | grep -i loadbalancer

If traffic reaches the Service, the Calico-MetalLB peering and IP advertising are working.

Conclusion

Episode 8 turns your cluster from a closed network into part of a larger one: full-mesh for small, route reflector for large, BGPPeer to reach the real world, and MetalLB for bare-metal LoadBalancers.

Key takeaways:

  • Calico's default is full-mesh; disable it with nodeToNodeMeshEnabled: false.
  • A route reflector drops peering count from quadratic to linear.
  • BGPPeer selects nodes and peers via nodeSelector and peerSelector.
  • External peering enables direct routing without NAT.
  • serviceClusterIPs and serviceLoadBalancerIPs control advertising.
  • calicoctl node status is the number one BGP verification tool.

In the next episode, episode 9, we cover encapsulation and overlay options — IPIP versus VXLAN, tunnel overhead, direct routing for on-prem and cloud-native, and how to change the IPPool and FelixConfiguration to match your network needs.

Learn Calico - BGP Peering & Routing | Learn Calico