---
title: "Configuring Route Reflectors in Calico"
source: "https://www.tigera.io/blog/configuring-route-reflectors-in-calico/"
---

[Technical Blog](https://www.tigera.io/category/technical-blog/)

# Configuring Route Reflectors in Calico

By [Josh Rosso](https://www.tigera.io/blog/author/josh-rosso/) on Mar 22, 2019 • 5 min read

Calico is a popular CNI plugin for Kubernetes. It leverages Border Gateway Protocol (BGP) for communicating routes available on nodes. This method fosters a highly scalable networking model between our workloads.

## The Case for Route Reflection

Calico requires no additional routers or infrastructure to run. Like many CNI plugins, you can apply it using `kubectl`.

```
`kubectl apply -f http://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml kubectl apply -f http://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml`
```

Once started, Calico runs a node-to-node mesh. This means every node peers to every other node to broadcast routes. This is done from the `calico/node` pod that runs on every node (via a daemonset). Let’s assume a 5 node cluster, with an IP range of `10.30.0.13-10.30.0.17`.

![Calico node-to-node mesh: 5 Kubernetes nodes with calico/node pods, each connected to all others via colored lines](https://www.tigera.io/app/uploads/2019/03/routes.png)

Every colored line represents a peering connection we’d expect in this cluster. These connections can be surfaced by downloading [calicoctl](http://github.com/projectcalico/calicoctl/releases) and running `sudo calicoctl node status` on a node. The example below shows the output from `10.30.0.15` in our example.

```
`sudo calicoctl node status Calico process is running. IPv4 BGP status +--------------+-------------------+-------+----------+--------------------------------+ | PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO | +--------------+-------------------+-------+----------+--------------------------------+ | 10.30.0.17 | node-to-node mesh | up | 01:17:08 | Established | | 10.30.0.16 | node-to-node mesh | up | 01:17:07 | Established | | 10.30.0.14 | node-to-node mesh | up | 01:29:06 | Established | | 10.30.0.13 | node-to-node mesh | up | 01:29:06 | Established | +--------------+-------------------+-------+----------+--------------------------------+`
```

This default behavior prevents us from worrying about upstream routers and BGP-configuration complexity. However, once our cluster grows to hundreds of nodes, we may find this node-to-node mesh to be no longer scalable. Route reflectors provide a solution to this. Since Calico 3, `calico/node` can act as a reflector. Introducing 2 `calico/node` pods or containers as route reflectors would change the peering relationship to the following.

![Calico/node route reflectors reduce node-to-node mesh complexity in large Kubernetes clusters](https://www.tigera.io/app/uploads/2019/03/route-reflection.png)

Calico makes achieving the above easy. We have 3 options to choose from.

- Dedicate Kubernetes node(s) to be route reflectors.

- Run `calico/node` as a container on non-Kubernetes host(s).

- Run a different reflector, such as a dedicated [BIRD](http://bird.network.cz) binary, and setup Calico to peer with it.

Trade-offs must be weighed between the options. Since configuration of option 1 & 2 are nearly identical and option 1 doesn’t require additional hosts, we’ll choose option 1 for demonstrating how reflection is configured. To do this we’ll perform the following steps.

- Select and configure `Node` resources to act as reflectors.

- Setup `BGPPeering` configurations to talk to reflectors.

- Disable node-to-node mesh.

 

## Configuring Nodes

First, we need to select the Nodes in our cluster to act as route reflectors. You may choose to taint these nodes to ensure other workloads don’t run on them.

List nodes in the cluster.

```
`kubectl get no -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP qtwtv Ready <none> 4h49m v1.13.0 10.30.0.17 rxgks Ready <none> 4h49m v1.13.0 10.30.0.16 uqwst Ready <none> 4h49m v1.13.0 10.30.0.14 volwl Ready <none> 4h49m v1.13.0 10.30.0.15 zyisy Ready master 4h50m v1.13.0 10.30.0.13`
```

Let’s choose `zyisy` and `rxgks` as our reflector nodes.

Download `calicoctl` on the host.

```
`wget http://github.com/projectcalico/calicoctl/releases/download/v3.4.0/calicoctl-linux-amd64 chmod +x calicoctl-linux-amd64 sudo mv calicoctl-linux-amd64 /usr/local/bin/calicoctl`
```

Export the `Node` resource of our chosen nodes to the local file system.

```
`calicoctl get node zyisy --export -o yaml > zyisy.yaml calicoctl get node rxgks --export -o yaml > rxgks.yaml`
```

Edit each node to include a `spec.bgp.routeReflectorClusterID: 1.0.0.1` and a `metadata.labels.router-reflector: true` An updated version of node `zyisy` is below.

```
`apiVersion: projectcalico.org/v3 kind: Node metadata: name: zyisy labels: route-reflector: true spec: bgp: ipv4Address: 10.30.0.13/22 ipv4IPIPTunnelAddr: 192.168.0.1 routeReflectorClusterID: 1.0.0.1`
```

The `routeReflectorClusterID` represents the BGP router’s cluster id, this is **not** synonymous with a Kubernetes cluster identifier. Determining whether reflectors should share cluster ids may depend on your topology. You should read about reflector peering and the implications of shared / unique cluster ids to make an informed decision.

Replace the existing `Node` resources with the updated ones.

```
`calicoctl replace -f zyisy.yaml Successfully replaced 1 'Node' resource(s) calicoctl replace -f rxgks.yaml Successfully replaced 1 'Node' resource(s)`
```

 

```
`kind: BGPPeer apiVersion: projectcalico.org/v3 metadata: name: node-peer-to-rr spec: nodeSelector: !has(route-reflector) peerSelector: has(route-reflector)`
```

## Configure BGP Peering

The [BGPPeer](http://docs.projectcalico.org/v3.4/reference/calicoctl/resources/bgppeer) resource defines what nodes peer. This is also commonly used when peering Calico’s network with your data center fabric by configuring peering to Top of Rack (ToR) routers.

We can make use of the added label `route-reflector: true` to easily setup a dynamic detection of reflector nodes should peer with.

Add the following node peering connection to ensure `calico/node` instance peer with the reflector instances.

Add peering between the RouteReflectors themselves.

```
`kind: BGPPeer apiVersion: projectcalico.org/v3 metadata: name: rr-to-rr-peer spec: nodeSelector: has(route-reflector) peerSelector: has(route-reflector)`
```

 

## Disable node-to-node Mesh

Lastly, we must turn off node-to-node mesh ensuring nodes are only peering with the reflectors they’re configured to. This requires altering or adding a default `BGPConfiguration`.

Check for an existing config, if one exists, modify/replace the existing, otherwise follow steps to create a new one.

```
`calicoctl get bgpconfig default`
```

Create a `BGPConfiguration` with `nodeToNodeMeshEnabled: false` and an Autonomous System number (`asNumber`) of `63400`.

```
`apiVersion: projectcalico.org/v3 kind: BGPConfiguration metadata: name: default spec: logSeverityScreen: Info nodeToNodeMeshEnabled: false asNumber: 63400`
```

Your asNumber may vary based on other BGP configurations throughout your data center(s).

On a non-reflector node, re-run `node status`.

```
`sudo calicoctl node status Calico process is running. IPv4 BGP status +--------------+-----------+-------+----------+-------------+ | PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO | +--------------+-----------+-------+----------+-------------+ | 10.30.0.13 | global | up | 03:52:51 | Established | | 10.30.0.16 | global | up | 03:54:11 | Established | +--------------+-----------+-------+----------+-------------+ IPv6 BGP status No IPv6 peers found.`
```

We can now see `zyisy: 10.30.0.13` and `rxgks: 10.30.0.16` are the reflectors this node is peering with! From here, validate network connectivity between pods.

## Additional Thoughts and Considerations

I hope you found this post helpful in understanding the configuration of route reflectors with Calico! Below are some additional thoughts and considerations to leave you with.

- Remember that when reflector nodes fail or get removed, we must replace them.

- It’d be cool if we one day there existed an operator / controller that can handle the assignment of reflectors to nodes based on scaled and topology!

- You may need to consider a different `asNumber` than the one used here.

- `routeReflectorClusterID` between routeReflectors may vary.

This article originated from http://octetz.com/posts/rr-setup

[Josh Rosso](http://www.linkedin.com/in/joshrosso/) is a Tigera guest blogger. His work involves Kubernetes on architecture, engineering, and consulting.

————————————————-

[**Free Online Training**](https://www.tigera.io/events/)

Access Live and On-Demand Kubernetes Training

[**Calico Enterprise – Free Trial**](https://www.calicocloud.io/home)

Network Security, Monitoring, and Troubleshooting

for Microservices Running on Kubernetes

[How-To](https://www.tigera.io/tags/how-to/)[Open Source](https://www.tigera.io/tags/open-source/)[Project Calico](https://www.tigera.io/tags/project-calico/)

## Related posts

[![Save the Address, Save the Cloud: A Hands-on KubeVirt Live Migration Workshop](https://www.tigera.io/app/uploads/2026/07/Save-the-Address-Save-the-Cloud-A-Hands-on-KubeVirt-Live-Migration-Workshop.png)](https://www.tigera.io/blog/save-the-address-save-the-cloud-a-hands-on-kubevirt-live-migration-workshop/)

#### [Save the Address, Save the Cloud: A Hands-on KubeVirt Live Migration Workshop](https://www.tigera.io/blog/save-the-address-save-the-cloud-a-hands-on-kubevirt-live-migration-workshop/)

By [Reza Ramezanpour](https://www.tigera.io/blog/author/rezar/)
on Jul 9, 2026

In the previous post in this series, we covered why Virtual Machine (VM) Live Migration in Kubernetes is difficult: a VM’s IP is its identity, and the “new” VM on the destination node has to...

[Read more](https://www.tigera.io/blog/save-the-address-save-the-cloud-a-hands-on-kubevirt-live-migration-workshop/)

[![What’s new in Calico: Spring 2026 Release](https://www.tigera.io/app/uploads/2026/06/Whats-New-in-Calico-NEW-TEMPLATE-2026.png)](https://www.tigera.io/blog/whats-new-in-calico-spring-2026-release/)

[Company Blog](https://www.tigera.io/category/company-blog/)

#### [What’s new in Calico: Spring 2026 Release](https://www.tigera.io/blog/whats-new-in-calico-spring-2026-release/)

By [Veronika Smolik](https://www.tigera.io/blog/author/veronika-smolik/)
on Jun 2, 2026

Kubernetes has come a long way since its debut in 2014. It’s gone from running a couple of containerized microservices to orchestrating fleets of production workloads spanning everything from AI agents to full scale VMs...

[Read more](https://www.tigera.io/blog/whats-new-in-calico-spring-2026-release/)

[![Kubernetes Operational Maturity: Secure and Resilient Cluster Federation with Cluster Mesh](https://www.tigera.io/app/uploads/2026/05/Kubernetes-Operational-Maturity-Secure-and-Resilient-Cluster-Federation-with-Cluster-Mesh.png)](https://www.tigera.io/blog/kubernetes-operational-maturity-secure-and-resilient-cluster-federation-with-cluster-mesh/)

#### [Kubernetes Operational Maturity: Secure and Resilient Cluster Federation with Cluster Mesh](https://www.tigera.io/blog/kubernetes-operational-maturity-secure-and-resilient-cluster-federation-with-cluster-mesh/)

By [Veronika Smolik](https://www.tigera.io/blog/author/veronika-smolik/)
on May 25, 2026

Practically no one runs a single Kubernetes cluster in production these days. Maybe that’s how it started but data sovereignty requirements, acquisitions, AI initiatives and the need for edge servers, among other considerations, have pulled...

[Read more](https://www.tigera.io/blog/kubernetes-operational-maturity-secure-and-resilient-cluster-federation-with-cluster-mesh/)

<!-- plugin=object-cache-pro client=phpredis metric#hits=3234 metric#misses=33 metric#hit-ratio=99.0 metric#bytes=1576558 metric#prefetches=0 metric#store-reads=175 metric#store-writes=15 metric#store-hits=169 metric#store-misses=22 metric#sql-queries=32 metric#ms-total=556.89 metric#ms-cache=33.45 metric#ms-cache-avg=0.1770 metric#ms-cache-ratio=6.0 sample#redis-hits=4293471 sample#redis-misses=1668753 sample#redis-hit-ratio=72.0 sample#redis-ops-per-sec=55 sample#redis-evicted-keys=0 sample#redis-used-memory=84372144 sample#redis-used-memory-rss=84037632 sample#redis-memory-fragmentation-ratio=1.0 sample#redis-connected-clients=1 sample#redis-tracking-clients=0 sample#redis-rejected-connections=0 sample#redis-keys=27629 -->
