ArunNetworkingPro
🏗️

A mini data center on one PC

A data center that fits in your laptop. We live in the future.

Big data centers use a simple, powerful shape: every leaf switch connects to every spine switch, with BGP choosing between all the paths at once. With Containerlab and the free FRRouting software, you can build one on a single Linux machine in minutes.

AdvancedA few weekendsRouting
spine1spine2leaf1leaf2every leaf ↔every spine2 paths!

🧰 What you need

Let's build it

1

Install Containerlab

bash -c "$(curl -sL https://get.containerlab.dev)"
2

Make a project folder

mkdir minidc && cd minidc
3

Tell FRR which routing daemons to run

Save as daemons:

bgpd=yes
vtysh_enable=yes
zebra_options="  -A 127.0.0.1 -s 90000000"
bgpd_options="   -A 127.0.0.1"
4

Describe the topology

Save as minidc.clab.yml: two spines, two leaves, every leaf cabled to every spine.

name: minidc
topology:
  defaults:
    kind: linux
    image: quay.io/frrouting/frr:10.2.1
  nodes:
    spine1: {binds: [spine1.conf:/etc/frr/frr.conf, daemons:/etc/frr/daemons]}
    spine2: {binds: [spine2.conf:/etc/frr/frr.conf, daemons:/etc/frr/daemons]}
    leaf1:  {binds: [leaf1.conf:/etc/frr/frr.conf, daemons:/etc/frr/daemons]}
    leaf2:  {binds: [leaf2.conf:/etc/frr/frr.conf, daemons:/etc/frr/daemons]}
  links:
    - endpoints: ["spine1:eth1", "leaf1:eth1"]
    - endpoints: ["spine1:eth2", "leaf2:eth1"]
    - endpoints: ["spine2:eth1", "leaf1:eth2"]
    - endpoints: ["spine2:eth2", "leaf2:eth2"]
5

Configure the spines

Save as spine1.conf. For spine2.conf, change the hostname to spine2 and 10.0.0.1 to 10.0.0.2 in both places.

frr defaults datacenter
hostname spine1
interface lo
 ip address 10.0.0.1/32
router bgp 65000
 bgp router-id 10.0.0.1
 neighbor FABRIC peer-group
 neighbor FABRIC remote-as external
 neighbor eth1 interface peer-group FABRIC
 neighbor eth2 interface peer-group FABRIC
 address-family ipv4 unicast
  redistribute connected
 exit-address-family
6

Configure the leaves

Save as leaf1.conf. For leaf2.conf, use hostname leaf2, AS 65102 and 10.1.1.2 in both places.

frr defaults datacenter
hostname leaf1
interface lo
 ip address 10.1.1.1/32
router bgp 65101
 bgp router-id 10.1.1.1
 neighbor FABRIC peer-group
 neighbor FABRIC remote-as external
 neighbor eth1 interface peer-group FABRIC
 neighbor eth2 interface peer-group FABRIC
 address-family ipv4 unicast
  redistribute connected
 exit-address-family
7

Bring the data center to life

sudo containerlab deploy -t minidc.clab.yml
8

Look at the fabric

sudo docker exec clab-minidc-leaf1 vtysh -c "show bgp summary"

Both spines show as neighbours with prefixes received.

✅ How you know it worked

Ping leaf2's loopback from leaf1's loopback, then look at the route:

sudo docker exec clab-minidc-leaf1 ping -c3 -I 10.1.1.1 10.1.1.2
sudo docker exec clab-minidc-leaf1 ip route show 10.1.1.2

The ping works, and the route to 10.1.1.2 has two next hops, one through each spine. Both paths are used at once: that's ECMP.

💥 Break it on purpose

Pull a "cable" on leaf1:

sudo docker exec clab-minidc-leaf1 ip link set eth1 down

Check the route again: one next hop left, and the ping still works through the other spine. Bring it back with ip link set eth1 up. When you're done, sudo containerlab destroy -t minidc.clab.yml cleans it all away.

🧠 What's really going on

In spine-and-leaf, every leaf is exactly two hops from every other leaf, and adding capacity just means adding another spine. Each switch runs BGP with its neighbours. The neighbor eth1 interface lines use "BGP unnumbered": the links need no IP addresses at all, because BGP finds its neighbour on the cable automatically. Every leaf learns every other leaf's routes through every spine and uses all of those paths at once. (Those odd fe80:: next hops in the route are the link addresses BGP unnumbered uses in place of IPs on each cable.)

← Back to all network labs · Stuck? Email me