Cumulus – EVPN – VXLAN

Dans un précédent article, nous avons vu comment mettre en place du VXLAN statique, mais on comprend que cette solution peut atteindre ses limites dans une infrastructure plus large avec de nombreux Leafs, pouvant rendre complexe la liste des variables pour l’automatisation. La définition initiale de VXLAN (RFC 7348) n’incluait aucun plan de contrôle et reposait sur une approche « flood-and-learn  » pour l’apprentissage d’adresses MAC. EVPN (Ethernet Virtual Private Network), souvent appelé « controller-less VXLAN », est un plan de contrôle basé sur des normes pour VXLAN défini dans le RFC 7432 et dans le document « draft-ietf-bess-evpn-overlay » qui permet de créer et de déployer des VXLANs à plus grande échelle et apporte des fonctionnalités avancées. Il repose sur le protocole MP-BGP (Multi-Protocol BGP) pour échanger des informations et il est basé sur BGP-MPLS IP VPNs (RFC 4364). Il permet non seulement le pontage entre les systèmes d’extrémité pour un même segment de niveau 2, mais également le routage entre différents segments (sous-réseaux). Le plan de contrôle de routage (y compris EVPN) est inclus dans le package FRRouting (FRR) présent dans Cumulus Linux.

Cumulus Static VXLAN
Architecture de simulation

Tous les commutateurs sont remis dans leur configuration d’origine à l’aide de la commande net del all, et comme pour le VXLAN statique, la partie underlay est assurée par une approche « eBGP unumbered » dans laquelle une adresse loopback est définie sur chaque noeud, L’AS (Autonomous System) est configuré comme décrit sur le schéma de la simulation, des sessions sont établies vers les différents AS et les adresses locales sont annoncées aux voisins. Pour la partie overlay une différence apparait dans l’activation du plan de contrôle EVPN sur les interfaces infrastructures de tous les commutateurs, tous les VNIs sont automatiquement annoncés sur les Leafs et seules les origines des tunnels sont définies sur les Leafs.

Cumulus Linux est basé sur Debian et il serait tout à fait possible de l’administrer comme un serveur Linux, mais l’usage du module Ansible nclu apporte une facilité d’exploitation qui ne nécessite pas de se pencher sur les subtilités du fonctionnement interne au système d’exploitation pour un usage aussi simple que celui présenté ici.

[defaults]
inventory = ./hosts
host_key_checking = False
interpreter_python=auto
roles_path = roles.galaxy:roles
collections_paths = collections.galaxy:collections
[all:children]
fabric

[fabric:children]
spines
leafs

[fabric:vars]
ansible_user=cumulus

[spines]
spine1 ansible_host=192.168.105.15
spine2 ansible_host=192.168.105.16

[leafs]
leaf1 ansible_host=192.168.105.17
leaf2 ansible_host=192.168.105.18
---
# group_vars/spines.yml
as: 65100
---
# host_vars/spine1.yml
loopback: 172.16.100.3
---
# host_vars/spine2.yml
loopback: 172.16.100.4
---
# host_vars/leaf1.yml
loopback: 172.16.100.1
as: 65101
vxlans:
  - name: VNI-10
    id: 10
    local_ip: 172.16.100.1
    remote_ip: 172.16.100.2
    vlan: 10
    vlan_gw: 192.168.10.254
    interface: swp3
  - name: VNI-20
    id: 20
    local_ip: 172.16.100.1
    remote_ip: 172.16.100.2
    vlan: 20
    vlan_gw: 192.168.20.254
    interface: swp4
---
# host_vars/leaf2.yml
loopback: 172.16.100.2
as: 65102
vxlans:
  - name: VNI-10
    id: 10
    local_ip: 172.16.100.2
    remote_ip: 172.16.100.1
    vlan: 100
    vlan_gw: 192.168.10.254
    interface: swp3
  - name: VNI-20
    id: 20
    local_ip: 172.16.100.2
    remote_ip: 172.16.100.1
    vlan: 200
    vlan_gw: 192.168.20.254
    interface: swp4
---
- name: Create demo lab Cumulus
  hosts: all
  gather_facts: no
  roles:
    - role: underlay_ebgp
      tags: [ underlay ]
    - role: overlay_static
      tags: [ static ]
    - role: overlay_evpn
      tags: [ evpn ]
---
# roles/underlay_ebpg/tasks/main.yml
- name: Configure eBGP underlay
  community.network.nclu:
    commands:
      - add loopback lo ip address {{ loopback }}/32
      - add bgp autonomous-system {{ as }}
      - add bgp neighbor swp1 interface remote-as external
      - add bgp neighbor swp2 interface remote-as external
      - add bgp network {{ loopback }}/32
    atomic: true
  when: "'fabric' in group_names"
---
# roles/overlay_evpn/tasks/main.yml
- name: Configure EVPN
  community.network.nclu:
    commands:
      - add bgp evpn neighbor swp1-2 activate
    atomic: true
- name: Configure Leafs
  community.network.nclu:
    template: |
      add bgp evpn advertise-all-vni
      {% for vxlan in vxlans %}
      add interface {{ vxlan.interface }} bridge access {{ vxlan.vlan }}
      add vxlan {{ vxlan.name }} vxlan id {{ vxlan.id }}
      add vxlan {{ vxlan.name }} vxlan local-tunnelip {{ vxlan.local_ip }}
      add vxlan {{ vxlan.name }} bridge access {{ vxlan.vlan }}
      add vlan {{ vxlan.vlan }} ip address {{ vxlan.vlan_gw }}/24
      {% endfor %}
    atomic: true
  when: "'leafs' in group_names"
Cumulus Linux Ansible EVPN VXLAN
ansible-playbook site.yml –tags underlay,evpn

Une fois la configuration appliquée, la partie underlay est active comme pour les VXLANs statiques et on peut constater que les tunnels VXLANs se sont construits grâce au plan de contrôle EVPN.

Cumulus Linux EVPN VNI
Cumulus EVPN VNI

Le routage asymétrique a été implémenté et depuis l’un des serveurs, il est possible de joindre tous les autres au travers de la fabrique IP.

Cumulus Linux EVPN VXLAN ping
Utilisation de la fabrique avec EVPN-VXLAN

Le module Ansible nclu retourne, dans la variable msg, des informations sur le résultat des commandes qui sont passées au commutateur. Ce peut être l’occasion pour demander l’affichage des informations EVPN. Voici un playbook qui affiche les informations sur les VNIs.

---
- name: Test Cumulus Output
  hosts: leafs
  gather_facts: no
  tasks:
    - name: Get EVPN configuration
      community.network.nclu:
        commands:
          - show evpn vni json
      register: output
    - name: Display Remote VTEPs IP Address
      ansible.builtin.debug: msg="{{ output['msg']|from_json|community.general.json_query(jmesquery) }}"
      vars:
        jmesquery: "*.{VNI: vni, RemoteIP: remoteVteps[0]}"

Pour l’exécuter, json_query nécessite l’installation des éléments ci-dessous.

ansible-galaxy collection install community.general
pip install jmespath
Cumulus Linux Ansible nclu msg
Cumulus Ansible nclu msg

L’étape suivante consisterait à automatiser le contrôle de bon fonctionnement par des tests unitaires…