Overview
Until recently, if we want to do networking lab, we had option to play with GNS3 or EVE-NG with Virtual Machine for Network OS. But 2021 has seen the rise of Containerlab which gives us ability to play Lab As Code as you can define your own topology in a YAML file.
Arista cEOS is natively supported by the tool and gives you opportunity to build lab easily from any type of tool in charge of your design. Big thanks you to Nokia’s team for making this tool fully open-source and with support for all NOS.
In this article, we will see how to build a containerlab topology from an Arista Validated Design collection for ansible where you define your EVPN topology.
Yes, with AVD, you can easily build any type of EVPN/VXLAN fabric, but at some point it is nice to test configuration and building topology on the fly would make design easier.
Of course, you can also find some containerlab examples with Arista cEOS on github, but here we are going to talk about generating lab from Ansible.
AVD to design an EVPN fabric
This guide is not a detailed guide to setup Arista AVD collection. For this type of document, you should visit specific documentation for that. Here we will build a basic L3LS EVPN fabric based on 2 spines, 4 groups of 2 vteps and some L2 edge switches.
Install environment
Here we are talking about python for ansible and Golang for Containerlab. And obviously, you need a docker engine to bring up lab at the end.
1
2
3
4
5
6
# Download AVD requirements
$ curl -fsSL https://raw.githubusercontent.com/aristanetworks/ansible-avd/devel/ansible_collections/arista/avd/requirements.txt
$ pip3 install -r requirements.txt
# Install ansible
$ pip3 install ansible-core
Once ansible is installed, you can use galaxy to install AVD and avd_to_containerlab role:
1
2
$ ansible-galaxy collection install arista.avd
$ ansible-galaxy collection install titom73.avd_tools
Now we can install Containerlab:
1
$ bash -c "$(curl -sL https://get-clab.srlinux.dev)"
Since we are here, let’s download a cEOS version from Arista website. For that, you can use eos-download as explained in this post. And finally, install it on your Machine.
1
$ docker import cEOS-lab.tar.xz ceosimage:<your-ceos-version>
Now we are ready to go to the build phase.
Ansible configuration
Topology file is provided below and will be the key to build containerlab topology
- Spine topology:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
spine:
defaults:
platform: vEOS-LAB
bgp_as: 65001
loopback_ipv4_pool: 192.168.1.0/24
bgp_defaults: ''
mlag_peer_ipv4_pool: 172.31.253.0/31
mlag_peer_l3_ipv4_pool: 172.31.253.2/31
nodes:
ceos-spine1:
id: 1
mgmt_ip: 10.73.255.101/24
mac_address: '0c:1d:c0:1d:62:01'
ceos-spine2:
id: 2
mgmt_ip: 10.73.255.102/24
mac_address: '0c:1d:c0:1d:62:02'
- vTEP (aka L3LEAF) topology
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
l3leaf:
defaults:
loopback_ipv4_pool: 192.168.255.0/24
loopback_ipv4_offset: 2
vtep_loopback_ipv4_pool: 192.168.254.0/24
uplink_interfaces: ['Ethernet1', 'Ethernet2']
uplink_switches: ['ceos-spine1', 'ceos-spine2']
uplink_ipv4_pool: 172.31.255.0/24
evpn_route_servers: ['ceos-spine1', 'ceos-spine2']
mlag_peer_ipv4_pool: 172.31.253.0/31
mlag_peer_l3_ipv4_pool: 172.31.253.2/31
mlag_interfaces: ''
virtual_router_mac_address: 00:1c:73:00:dc:01
bgp_defaults: ''
spanning_tree_priority: 4096
spanning_tree_mode: mstp
node_groups:
ceos_leaf1:
bgp_as: 65101
filter:
tenants: [ 'Tenant_A', 'Tenant_B' ]
tags: [ 'POD01', 'DC1' ]
nodes:
ceos-leaf1a:
id: 11
mgmt_ip: 10.73.255.111/24
uplink_switch_interfaces: [Ethernet1, Ethernet1]
mac_address: '0c:1d:c0:1d:62:11'
ceos-leaf1b:
id: 12
mgmt_ip: 10.73.255.112/24
uplink_switch_interfaces: [Ethernet2, Ethernet2]
mac_address: '0c:1d:c0:1d:62:12'
# [ Output ommitted for readability]
# ...
- L2 Switch (aka L2LEAF) topology
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
edge:
defaults:
uplink_switches: ['ceos-leaf1a', 'ceos-leaf1b']
uplink_interfaces: ['Ethernet1', 'Ethernet2']
mlag_peer_ipv4_pool: 172.31.253.0/31
mlag_peer_l3_ipv4_pool: 172.31.253.2/31
node_groups:
ceos_edge_leaf1:
uplink_switches: [ ceos-leaf1a, ceos-leaf1b ]
filter:
tenants: [ 'Tenant_A', 'Tenant_B' ]
tags: [ 'POD01', 'DC1' ]
nodes:
ceos-agg01:
id: 21
mgmt_ip: 10.73.255.121/24
mac_address: '0c:1d:c0:1d:62:21'
uplink_switch_interfaces: [ Ethernet5, Ethernet5 ]
# [ Output ommitted for readability]
# ...
For a complete list of options, it is better to read the full documentation of AVD.
Also, full inventory is available on github. So you can just clone and play.
Playbook
After inventory has been created, we can create a playbook. This one will be fairly easy and will do 3 things:
- Transform abstracted topology into YAML EOS configuration file
- Generate EOS Cli configuration file
- Generate a containerlab topology loading AVD generated configuration files.
So here we go:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# playbook/build.yml
---
- name: Build Switch configuration
hosts: [all]
tags:
- avd
collections:
- arista.avd
tasks:
- name: generate intended variables
tags: [build]
import_role:
name: eos_designs
- name: generate device intended config and documentation
tags: [build]
import_role:
name: eos_cli_config_gen
- name: Build containerlab topology
hosts: [all]
connection: local
gather_facts: false
collections:
- arista.avd
- titom73.avd_tools
tasks:
- name: 'Build Containerlab Topology'
tags:
- containerlab
import_role:
name: inetsix.avd_tools.eos_designs_to_containerlab
vars:
mgmt_network_v4: 10.73.255.0/24
ceos_version: arista/ceos:4.27.1F
eapi_base: 8000
As you can see, eos_designs_to_containerlab
role needs some elements to generate a full configuration:
mgmt_network_v4
: Management network to configure on docker side. It must be the same as the one used in AVDeapi_base
: Base port for eAPI to expose eAPI service to the network outside of docker.ceos_version
: Which version of cEOS to use.
Make the magic happens
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ ansible-playbook playbooks/containerlab-build.yml -i containerlab/inventory.yml
[...]
===============================================================================
arista.avd.eos_cli_config_gen : Generate content of device documentation ---------- 4.61s
arista.avd.eos_cli_config_gen : Generate eos intended configuration --------------- 3.30s
arista.avd.eos_designs : Generate device configuration in structured format ------- 1.75s
arista.avd.eos_cli_config_gen : Generate TOC for device documentation ------------- 0.92s
arista.avd.eos_designs : Write device structured configuration to YAML file ------- 0.85s
arista.avd.eos_designs : Generate fabric documentation in Markdown Format. -------- 0.72s
arista.avd.eos_cli_config_gen : Create required output directories if not present - 0.61s
arista.avd.eos_designs : Set AVD facts -------------------------------------------- 0.58s
arista.avd.eos_cli_config_gen : Store checksum of existing device documentation --- 0.50s
arista.avd.eos_designs : Generate TOC for fabric documentation -------------------- 0.47s
arista.avd.eos_designs : Generate fabric topology in csv format. ------------------ 0.46s
inetsix.avd_tools.eos_designs_to_containerlab : Generate containerlab topology ---- 0.45s
arista.avd.eos_designs : Create required output directories if not present -------- 0.44s
arista.avd.eos_designs : Set AVD topology facts ----------------------------------- 0.28s
arista.avd.eos_designs : Store checksum of existing fabric documentation ---------- 0.26s
Playbook run took 0 days, 0 hours, 0 minutes, 17 seconds
So now you can look at files generated:
- EOS configuration files under
intended/configs
- Containerlab topology in
containerlab/containerlab.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
---
name: ceos_fabric
mgmt:
network: 'mgmt_ceos_fabric'
ipv4_subnet: 10.73.255.0/24
topology:
kinds:
ceos:
image: arista/ceos:4.27.1F
nodes:
ceos-agg01:
image: arista/ceos:4.27.1F
mgmt_ipv4: 10.73.255.121
kind: ceos
startup-config: <path>/intended/configs/ceos-agg01.cfg
ports:
- 8021:443/tcp
env:
TMODE: lacp
# [...]
links:
- endpoints: ["ceos-agg01:eth1", "ceos-leaf1a:eth5"]
# [...]
And you can start containerlab:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ sudo containerlab deploy --topo inventories/containerlab/containerlabs.yml
[sudo] password for tom:
INFO[0000] Parsing & checking topology file: containerlabs.yml
INFO[0000] Creating lab directory: /home/tom/arista-\
avd/avd-lab-validation/clab-ceos_fabric
INFO[0000] Creating docker network: Name='mgmt_ceos_fabric', \
IPv4Subnet='10.73.255.0/24', IPv6Subnet='', MTU='1500'
INFO[0000] config file '/home/tom/arista-avd/avd-lab-validation/\
clab-ceos_fabric/ceos-agg01/flash/startup-config' for node \
'ceos-agg01' already exists and will not be generated/reset
INFO[0000] Creating container: ceos-agg01
[...]
INFO[0004] Creating virtual wire: ceos-leaf3a:eth3 <--> ceos-leaf4a:eth3
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-leaf2a' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-bl01a' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-leaf3a' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-leaf4a' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-agg02' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-leaf1a' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-leaf2b' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-leaf1b' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-spine1' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-spine2' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-bl01b' node
INFO[0005] Running postdeploy actions for Arista cEOS 'ceos-agg01' node
Once it is over, you should see output below. It gives you some information such as kind
, version
and management 0
IP address.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
INFO[0143] 🎉 New containerlab version 0.23.0 is available! Release notes: https://containerlab.srlinux.dev/rn/0.23/
Run 'containerlab version upgrade' to upgrade or go check other installation options at https://containerlab.srlinux.dev/install/
+----+------------------------------+--------------+---------------------+------+---------+------------------+--------------+
| # | Name | Container ID | Image | Kind | State | IPv4 Address | IPv6 Address |
+----+------------------------------+--------------+---------------------+------+---------+------------------+--------------+
| 1 | clab-ceos_fabric-ceos-agg01 | 37973cf400d7 | arista/ceos:4.27.1F | ceos | running | 10.73.255.121/24 | N/A |
| 2 | clab-ceos_fabric-ceos-agg02 | cb37f8b37e0f | arista/ceos:4.27.1F | ceos | running | 10.73.255.122/24 | N/A |
| 3 | clab-ceos_fabric-ceos-bl01a | 9ba07822490b | arista/ceos:4.27.1F | ceos | running | 10.73.255.115/24 | N/A |
| 4 | clab-ceos_fabric-ceos-bl01b | 40eaf38dd58c | arista/ceos:4.27.1F | ceos | running | 10.73.255.116/24 | N/A |
| 5 | clab-ceos_fabric-ceos-leaf1a | f4ac53c2ae4d | arista/ceos:4.27.1F | ceos | running | 10.73.255.111/24 | N/A |
| 6 | clab-ceos_fabric-ceos-leaf1b | c03adbff83af | arista/ceos:4.27.1F | ceos | running | 10.73.255.112/24 | N/A |
| 7 | clab-ceos_fabric-ceos-leaf2a | b59260c441a0 | arista/ceos:4.27.1F | ceos | running | 10.73.255.113/24 | N/A |
| 8 | clab-ceos_fabric-ceos-leaf2b | 5514405b6429 | arista/ceos:4.27.1F | ceos | running | 10.73.255.114/24 | N/A |
| 9 | clab-ceos_fabric-ceos-leaf3a | 87e22287c2f2 | arista/ceos:4.27.1F | ceos | running | 10.73.255.117/24 | N/A |
| 10 | clab-ceos_fabric-ceos-leaf4a | 878b75601225 | arista/ceos:4.27.1F | ceos | running | 10.73.255.118/24 | N/A |
| 11 | clab-ceos_fabric-ceos-spine1 | 7d10d85458e0 | arista/ceos:4.27.1F | ceos | running | 10.73.255.101/24 | N/A |
| 12 | clab-ceos_fabric-ceos-spine2 | 7e0effa1ccd6 | arista/ceos:4.27.1F | ceos | running | 10.73.255.102/24 | N/A |
+----+------------------------------+--------------+---------------------+------+---------+------------------+--------------+
Also, you can look at docker directly. This one is interesting to ge eAPI port mapping:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
87e22287c2f2 arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8015->443/tcp, :::8015->443 tcp clab-ceos_fabric-ceos-leaf3a
f4ac53c2ae4d arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8011->443/tcp, :::8011->443/tcp clab-ceos_fabric-ceos-leaf1a
5514405b6429 arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8014->443/tcp, :::8014->443/tcp clab-ceos_fabric-ceos-leaf2b
40eaf38dd58c arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8018->443/tcp, :::8018->443/tcp clab-ceos_fabric-ceos-bl01b
b59260c441a0 arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8013->443/tcp, :::8013->443/tcp clab-ceos_fabric-ceos-leaf2a
cb37f8b37e0f arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8022->443/tcp, :::8022->443/tcp clab-ceos_fabric-ceos-agg02
c03adbff83af arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8012->443/tcp, :::8012->443/tcp clab-ceos_fabric-ceos-leaf1b
7d10d85458e0 arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8001->443/tcp, :::8001->443/tcp clab-ceos_fabric-ceos-spine1
878b75601225 arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8016->443/tcp, :::8016->443/tcp clab-ceos_fabric-ceos-leaf4a
7e0effa1ccd6 arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8002->443/tcp, :::8002->443/tcp clab-ceos_fabric-ceos-spine2
37973cf400d7 arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8021->443/tcp, :::8021->443/tcp clab-ceos_fabric-ceos-agg01
9ba07822490b arista/ceos:4.27.1F "/sbin/init systemd.…" 2 minutes ago Up 2 minutes 0.0.0.0:8017->443/tcp, :::8017->443/tcp clab-ceos_fabric-ceos-bl01a
And you can connect to your EOS cli directly from host with docker command:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
docker exec -it clab-ceos_fabric-ceos-spine1 Cli
ceos-spine1>
ceos-spine1>en
ceos-spine1#show lldp neighbors
Last table change time : 0:12:19 ago
Number of table inserts : 20
Number of table deletes : 1
Number of table drops : 0
Number of table age-outs : 1
Port Neighbor Device ID Neighbor Port ID TTL
---------- ------------------------ ---------------------- ---
Et1 ceos-leaf1a Ethernet1 120
Et2 ceos-leaf1b Ethernet1 120
Et3 ceos-leaf2a Ethernet1 120
Et4 ceos-leaf2b Ethernet1 120
Et5 ceos-bl01a Ethernet1 120
Et6 ceos-bl01b Ethernet1 120
Et7 ceos-leaf3a Ethernet1 120
Et8 ceos-leaf4a Ethernet1 120
ceos-spine1#show bgp evpn summary
BGP summary information for VRF default
Router identifier 192.168.1.1, local AS number 65001
Neighbor Status Codes: m - Under maintenance
Description Neighbor V AS MsgRcvd MsgSent InQ OutQ Up/Down State PfxRcd PfxAcc
ceos-leaf1a 192.168.255.13 4 65101 46 42 0 0 00:13:01 Estab 10 10
ceos-leaf1b 192.168.255.14 4 65101 46 42 0 0 00:13:01 Estab 10 10
ceos-leaf2a 192.168.255.15 4 65102 51 41 0 0 00:13:07 Estab 10 10
ceos-leaf2b 192.168.255.16 4 65102 52 42 0 0 00:13:08 Estab 10 10
ceos-leaf3a 192.168.255.17 4 65103 52 44 0 0 00:13:16 Estab 5 5
ceos-leaf4a 192.168.255.18 4 65104 53 48 0 0 00:13:28 Estab 5 5
ceos-bl01a 192.168.255.19 4 65105 52 48 0 0 00:13:18 Estab 4 4
ceos-bl01b 192.168.255.20 4 65105 54 48 0 0 00:13:18 Estab 4 4
If you change your AVD parameter, your lab will be fully rebuild and will be ready for testing. You just have to destroy active topology before running again the playbook.
Resources
- Containerlab / User Guide
- Containerlab examples
- Arista EOS AVD Topology examples
- Arista AVD ansible Collection: Documentation / Repository
- Collection to map AVD with Containerlab
- User journey & experiences with Containerlab by @Julio