8 décembre 2022

Gestion d’un réseau complexe KVM et Openvswitch

Dans cet article, nous allons étudier la mise en place d’un réseau avec Openswitch. Ce réseau sera utilisé dans le cadre de la virtualisation de VMs avec l’aide de KVM.

Cet article s’intègre dans la série New Box 2022. Vous y trouverez le pourquoi du comment, les prérequis, paquets à installer, etc…

 

I – Explication

Voila un schéma réseau pour présenter succinctement ce que nous allons mettre en place :

NB : Pour le moment, je n’ai pas indiqué l’ensemble de l’architecture, le schéma sera complété au fur et a mesure du tuto.

Les carrés représentent les futurs VMs et les rectangles, des switchs.

On y trouve, de haut en bas :

  • Deux routeurs de « bordure » : Un master, un backup, avec une IP Flottante 66.66.66.66, IP publique. C’est notre interco avec le grand internet.
  • Ces routeurs ont un adressage privé en 10.10.1.0/24 et sont branchés sur un premier Switch appelé Vlan10.
  • Nous trouvons ensuite, également connectés à ce Switch, nos VMS FrontWeb. Ces serveurs sont accessibles de l’extérieur pour y héberger nos frontaux Web par le biais du routeur et de DNAT. De manière identique aux routeurs, le service FrontWeb est loadbalancé avec une IP flottante en 10.10.1.10.
  • Par la suite, dans cette couche, nous ajouterons d’autres VMs qui ont vocation à offrir un service sur Internet (mail, dns, etc…)
  • Ces VMs de front auront chacune une interface sur un réseau 10.20.1.0/24. Sur ce réseau, nous allons trouver également deux routeurs (Master-Slave) qui vont faire le transit entre les VMs des services publics (Serveur Web, Messagerie, DNS, VPN) et les VMs ‘Infra’ (Stockage, SQL, etc…)
  • Chacun de ces « pools », stockage, SQL, lDAP, sera isolé au niveau par le truchement de Switchs. Nous détaillerons tout cela plus tard…

Les plus pinailleurs des experts réseau me diront que j’aurais pu être plus économe en plage IP… Oui, je découpe large, tel un boucher « Y’en a un peu plus, je vous le mets avec ? »

On n’est pas la pour faire un TP réseau, on peut prendre le 10.0.0.0/8, alors roule pedro…

Pour les switchs, on est d’accord, on est sur du virtuel avec Openvswitch. Et on ne va pas faire un switch par sous réseau, mais utiliser les Vlans.

On aura donc, comme « switchs » :

  • un switch br0, destiné a l’interco avec le monde extérieur par le biais de l’interface physique eno1 du serveur
  • un switch brint, destiné à l’interconnexion entre les vms. Ce switch sera « découpé » en sous réseaux par l’utilisation de VLAN.

D’un point de vue hyperviseur, on a ce schéma :

Deux grands types de VMs :

  • Celles avec une connexion vers le réseau externe
  • Celles avec de simples lien en interne

Le lecteur curieux et surement un brin taquin me demandera : « Mais diantre, pourquoi deux switchs distincts ?  »

Nous sommes d’accord, il serait tout a fait possible de n’en utiliser qu’un seul, avec un vlan associé pour le lien externe, et hop… Mais je suis chez Online et chez Online, si on a une VM qui s’annonce sur le réseau mais qui n’est pas déclaré côté Online, on se mange un blocage de port et c’est direction le support (et du coup, interruption plus ou moins longue…)

Si je fais tout bien, ça ne doit pas arriver, mais on le sait, en informatique, le risque zéro n’existe pas, il se peut que je puisse me louper, du coup, je ne prend pas de risques, un switch virtuel dédié aux VMS qui doivent avoir un lien direct avec le réseau externe, un autre pour le reste et on minimise alors le risque de foirage…

 

II – Mise en place

A – OpenvSwitch

Au cas ou vous arriviez sur cette page par une recherche Google sans avoir vu l’article racine (Tuto Virtualisation V 2022 : Debian 11, KVM et Openvswitch), il faut au préalable installer Openvswitch sur l’hyperviseur :

# apt install openvswitch-switch

On va ajouter nos deux switchs br0 et brint :

# ovs-vsctl add-br br0
# ovs-vsctl add-br brint

On peut vérifier avec :

# ovs-vsctl show

 

B – Connexion Hyperviseur sur le switch br0

Pour « connecter » ce switch a notre hyperviseur (en gros, l’intercaler entre le noyau et le port réseau physique), nous allons modifier le fichier interfaces /etc/network/interfaces de l’hyperviseur :

auto lo
iface lo inet loopback

auto br0
allow-ovs br0
allow-br0 eno1

iface br0 inet static
 address AAA.BBB.CCC.DDD
 netmask 255.255.255.0
 gateway IP.GATEWAY
 ovs_type OVSBridge
 ovs_ports eno1

iface eno1 inet manual
 ovs_bridge br0
 ovs_type OVSPort

Vous pensez à vérifier le nom de votre interface externe (qui sur la Dedibox en Debian11 est eno1).

Et on relance :

# service networking restart

Et si vous n’avez pas les doigts palmés, on doit toujours avoir la machine connectée au réseau. Sinon, on est bon pour un mode rescue 😉

Si on fait un :

# ip a

On voit que l’IP est désormais « attachée » à br0.

...
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master ovs-system state UP group default qlen 1000
  link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
  altname enp4s0f0
  inet6 xxx::xxx:xxxx:xxxx:xxxx/64 scope link
    valid_lft forever preferred_lft forever
3: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
  link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
  altname enp4s0f1
4: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
  link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
  link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
  inet YY.YY.YY.YY/24 brd YY.YY.YY.YY scope global br0
    valid_lft forever preferred_lft forever
  inet6 xxx::xxx:xxxx:xxxx:xxxx/64 scope link
    valid_lft forever preferred_lft forever
6: brint: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
  link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff

 

II – Definition network dans KVM

Maintenant, passons à la configuration du réseau côté KVM, d’une manière similaire à la gestion du stockage, à savoir, définition de pool, etc..

On liste ce qui est en place :

# virsh net-list --all

On supprime :

# virsh net-undefine default

En parallèle, on va se créer un petit répertoire pour stocker nos configurations, histoire de pas avoir des fichiers qui trainent partout :

# mkdir /root/conf_network && cd /root/conf_network

 

A – Switch br0

On va maintenant configurer KVM pour que le br0 soit pris en compte et utilisable par les VMs. Cela se fait en le définissant dans un fichier xml nommé, par exemple, front.xml :

<network>
    <name>ovs-front</name>
    <forward mode='bridge'/>
    <bridge name='br0'/>
    <virtualport type='openvswitch'/>
</network>

Il faut ensuite l’insérer et l’activer :

# virsh net-define front.xml
# virsh net-start ovs-front
# virsh net-autostart ovs-front

Et si on liste :

# virsh net-list --all

On le voit !

 

B – Switch brint

Dans un fichier nommé intern.xml :

<network>
<name>intern-vlans</name>
<forward mode='bridge'/>
<bridge name='brint'/>
<virtualport type='openvswitch'/>
<portgroup name='vlansadmin'>
<vlan trunk='yes'>
<tag id='99'/>
<tag id='250'/>
</vlan>
</portgroup>
<portgroup name='vlansext'>
<vlan trunk='yes'>
<tag id='10'/>
<tag id='20'/>
</vlan>
</portgroup>
<portgroup name='vlan10'>
<vlan>
<tag id='10'/>
</vlan>
</portgroup>
<portgroup name='vlan20'>
<vlan>
<tag id='20'/>
</vlan>
</portgroup>
<portgroup name='vlansint'>
<vlan trunk='yes'>
<tag id='100'/>
<tag id='101'/>
<tag id='102'/>
<tag id='103'/>
<tag id='104'/>
<tag id='105'/>
<tag id='106'/>
<tag id='107'/>
<tag id='108'/>
<tag id='109'/>
</vlan>
</portgroup>
<portgroup name='100'>
<vlan>
<tag id='100'/>
</vlan>
</portgroup>
<portgroup name='101'>
<vlan>
<tag id='101'/>
</vlan>
</portgroup>
<portgroup name='102'>
<vlan>
<tag id='102'/>
</vlan>
</portgroup>
<portgroup name='103'>
<vlan>
<tag id='103'/>
</vlan>
</portgroup>
<portgroup name='104'>
<vlan>
<tag id='104'/>
</vlan>
</portgroup>
<portgroup name='105'>
<vlan>
<tag id='105'/>
</vlan>
</portgroup>
<portgroup name='106'>
<vlan>
<tag id='106'/>
</vlan>
</portgroup>
<portgroup name='107'>
<vlan>
<tag id='107'/>
</vlan>
</portgroup>
<portgroup name='108'>
<vlan>
<tag id='108'/>
</vlan>
</portgroup>
<portgroup name='109'>
<vlan>
<tag id='109'/>
</vlan>
</portgroup>
</network>

La configuration demande une petite explication.

Au niveau des Vlans, j’ai ceci :

– 99 : utilisé pour les communications hyperviseur <-> VMs
– 250 : utilisé pour la supervision

Ces deux VLANs étant systématiquement utilisés et disponibles sur l’ensemble des VMs, ils sont regroupés au sein d’un trunk nommé vlansadmin, déclaré ainsi dans le fichier :

<portgroup name='vlansadmin'>
<vlan trunk='yes'>
<tag id='99'/>
<tag id='250'/>
</vlan>
</portgroup>

Ensuite, j’ai les VLANs 10 et 20, utilisés dans les intercos routeurs externes <-> front et front <->routeurs internes.
Je peux avoir des machines avec uniquement le VLAN 10, d’autres avec uniquement le VLAN 20 et pour terminer certaines avec les deux.
Je déclare alors ainsi :

<portgroup name='vlansext'>
<vlan trunk='yes'>
<tag id='10'/>
<tag id='20'/>
</vlan>
</portgroup>
<portgroup name='vlan10'>
<vlan>
<tag id='10'/>
</vlan>
</portgroup>
<portgroup name='vlan20'>
<vlan>
<tag id='20'/>
</vlan>
</portgroup>

avec un trunk nommé vlansext qui regroupe les deux VLANs.

Et pour terminer, les VLANs utilisés par les pools de services, web, stockage, etc.. Numérotés de 100 à 109 avec en supplément un trunk vlansint (regroupant l’ensemble des VLANS 100,101,102….109), utilisé entre le switch et les routeurs internes. Ce qui donne cela :

<portgroup name='vlansint'>
<vlan trunk='yes'>
<tag id='100'/>
...
<tag id='109'/>
</vlan>
</portgroup>
<portgroup name='100'>
<vlan>
<tag id='100'/>
</vlan>
</portgroup>
...
<portgroup name='109'>
<vlan>
<tag id='109'/>
</vlan>
</portgroup>
</network>

Et de la même manière que pour br0, pour utiliser tout ceci dans nos futurs VMs :

# virsh net-define intern.xml
# virsh net-autostart intern-vlans
# virsh net-start intern-vlans

On peut vérifier :

# virsh net-list --all

A y est, c’est prêt ! Il ne reste plus qu’un petit réglage…

 

C – Hyperviseur sur le VLAN 99

Comme je l’ai expliqué, le VLAN 99 sert à l’interconnexion entre l’hyperviseur et les VMs. On va donc connecter notre hyperviseur sur ce switch brint.

A savoir, quand on créé un switch à l’aide d’Openvswitch, un port de type particulier est créé automatiquement :

Bridge brint
  Port brint
    Interface brint
      type: internal
...

Port indiqué de type internal. On a le même également pour br0.

Sur ce port brint (côté Debian), on va associer une IP :

# ip addr add 10.99.1.250 dev brint
# ip link set brint up
# ip route add 10.99.1.0/24 dev brint

On affecte l’IP 10.99.1.250, on monte le lien et on ajoute la route vers 10.99.1.0/24 via ce nouveau port.

Ensuite, il ne reste plus qu’à indiquer le VLAN à utiliser sur le port. Et cela se fait ainsi :

# ovs-vsctl set port brint tag=99

On peut vérifier au niveau Openvswitch :

# ovs-vsctl show

Qui nous indique :

Bridge brint
  Port brint
    tag: 99
    Interface brint
      type: internal
Bridge br0
  Port eno1
    Interface eno1
  Port br0
    Interface br0
      type: internal

Et histoire de maintenir la persistance au boot :

# nano /srv/boot.sh

Avec dedans :

#!/bin/bash
ip addr add 10.99.1.250 dev brint
ip link set brint up
ip route add 10.99.1.0/24 dev brint
ovs-vsctl set port brint tag=99

puis

# chmod +x boot.sh

Ensuite, on va créer le service qui va appeler le script :

# nano /etc/systemd/system/hypervisor-boot.service

Avec dedans :

[Unit]
Description=HyperVisor Boot
After=default.target

[Service]
ExecStart=/srv/boot.sh

[Install]
WantedBy=default.target

Et pour finir, on active avec :

# systemctl enable hypervisor-boot.service

 

Voila mis en place la couche réseau de notre future architecture.

Je vous propose donc de revenir à l’article initial et de poursuivre la feuille de route.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *