systemd, le « sujet » qui a fait couler beaucoup d’encre…
Dès son annonce, systemd à fait parler de lui que se soit en bien ou en mal. Certains étaient enthousiastes à la venue d’un nouveau système d’init, d’autres étaient réfractaire au changement, d’autres étaient partagés sur le fait que systemd faisait beaucoup trop de choses.
Pour ma part je n’avais pas spécialement d’opinion sur le sujet, j’attendais simplement de voir comment systemd allait s’intégrer aux distributions et plus particulièrement à Debian GNU/Linux. Depuis Debian GNU/Linux Stretch (9.x), l’intégration de systemd a été amplement améliorée même s’il est dommage que la version embarquée par défaut soit inférieure à 233 (heureusement que les backports sont là pour corriger cela).
Comme indiqué quelques lignes plus haut, systemd est capable de gérer plusieurs choses, entre autres:
- NTP via systemd-timesyncd
- Conteneur via systemd-nspawn
- Réseau via systemd-networkd
Nous allons nous attarder sur systemd-networkd afin de configurer entièrement notre réseau et de remplacer le « déprécier » /etc/network/interfaces*.
Objectif Lune (dédicace à Tintin o/)
Dans ce billet, nous avons pour objectif de configurer:
- Un bonding LACP (802.3ad) avec deux interfaces réseau
- Deux vlan configurés sur le bond
- Application des jumbo frames sur l’un des vlan
Configuration du module bonding
La première chose à effectuer avant d’aller plus loin et de définir le comportement du module bonding. Par défaut quand le module bonding est chargé, le noyau créé automatiquement une interface nommée bond0. Ce comportement pose problème à systemd… pour faire simple il se mélange les pinceaux en essayant de créer une interfaces bond0 qui existe déjà…
La configuration du module bonding est simple, il suffit d’ajouter le contenu suivant dans le fichier /etc/modprobe.d/bonding.conf (libre à vous d’en ajouter en fonction de vos besoins).
options bonding max_bonds=0
D’après la documentation officielle du module:
max_bonds
Specifies the number of bonding devices to create for this
instance of the bonding driver. E.g., if max_bonds is 3, and
the bonding driver is not already loaded, then bond0, bond1
and bond2 will be created. The default value is 1. Specifying
a value of 0 will load bonding, but will not create any devices.
À partir de la version 235, systemd se charge de configurer automatiquement le module bonding via un drop-in dans le répertoire /etc/modprobe.d/
Configuration de systemd-networkd
Le module bonding est désormais configuré (tu veux une médaille ?), systemd-networkd a maintenant besoin d’informations pour créer le réseau. Ces informations sont à fournir sous forme de fichiers, ces fichiers doivent se terminer avec des extensions particulières.
- .link: Utile pour configurer la MTU, l’adresse MAC, la bande passante, etc..
- .netdev: Permet de créer une interface virtuelle comme par exemple un bond, un bridge, un vlan, etc…
- .network: Permet d’assigner une configuration réseau à une interface physique ou virtuelle
L’ordre de lecture de ces fichiers s’effectue de manière lexicale. Il est important de noter que si aucun fichier .link existe, le fichier /lib/systemd/network/99-default.link sera automatiquement appliqué.
Les interfaces ens4 et ens5 sont membres de bond0, il est nécessaire de créer deux fichiers (un par interface physique) dans le répertoire /etc/systemd/network/.
# cat << EOF > /etc/systemd/network/20-bond0-ens4.network [Match] Name=ens4 [Network] Bond=bond0 EOF # cat << EOF > /etc/systemd/network/20-bond0-ens5.network [Match] Name=ens5 [Network] Bond=bond0 EOF
L’activation des jumbo frames s’effectue à l’aide des fichiers .link. Il est donc nécessaire de créer un fichier par interface ou l’on souhaite appliquer cette modification.
# cat << EOF > /etc/systemd/network/20-bond0-ens4.link [Match] OriginalName=ens4 [Link] MTUBytes=9000 EOF # cat << EOF > /etc/systemd/network/20-bond0-ens5.link [Match] OriginalName=ens5 [Link] MTUBytes=9000 EOF
Maintenant que nos interfaces sont prêtes à faire partie du bonding il ne reste plus qu’à créer notre bond0, ici nous allons créer une interface virtuelle (et oui, bond0 n’est pas physique).
# cat << EOF > /etc/systemd/network/20-bond0.netdev [NetDev] Name=bond0 Kind=bond [Bond] Mode=802.3ad MIIMonitorSec=1s LACPTransmitRate=fast UpDelaySec=2s DownDelaySec=8s EOF
Comme pour les interfaces physiques, il est nécessaire de changer la MTU pour bond0 auquel cas la taille de cette dernière sera celle par défaut à savoir 1500.
# cat << EOF > /etc/systemd/network/20-bond0.link [Match] OriginalName=bond0 [Link] MTUBytes=9000 EOF
Avant d’appliquer une configuration réseau à bond0, nous allons créer nos deux interfaces virtuelles de type vlan (bond0.10 et bond0.20). Encore une fois, nous allons devoir jouer avec les fichiers .link et .netdev (vous devriez commencer à comprendre le principe).
# cat << EOF > /etc/systemd/network/30-bond0-vlan10.link [Match] OriginalName=bond0.10 [Link] MTUBytes=1500 EOF # cat << EOF > /etc/systemd/network/30-bond0-vlan10.netdev [NetDev] Name=bond0.10 Kind=vlan [VLAN] Id=10 EOF # cat << EOF > /etc/systemd/network/30-bond0-vlan20.link [Match] OriginalName=bond0.20 [Link] MTUBytes=9000 EOF # cat << EOF > /etc/systemd/network/30-bond0-vlan20.netdev [NetDev] Name=bond0.20 Kind=vlan [VLAN] Id=20 EOF
ens4 et ens5 ont été ajoutées à bond0, ce dernier a été créé pour supporté LACP, les vlan 10 et 20 ont été taggés sur bond0 et les jumbo frame ont été activées sur toutes les interfaces excepté bond0.10.
La dernière étape consiste à appliquer une configuration réseau à nos interfaces virtuelles, dans un premier temps sur bond0.10 et bond0.20 et dans un second temps sur bond0 lui même.
# cat << EOF > /etc/systemd/network/30-bond0-vlan10.network [Match] Name=bond0.10 [Network] Address=10.10.0.10/24 EOF # cat << EOF > /etc/systemd/network/30-bond0-vlan20.network [Match] Name=bond0.20 [Network] Address=10.20.0.10/24 EOF # cat << EOF > /etc/systemd/network/30-bond0.network [Match] Name=bond0 [Network] BindCarrier=ens4 ens5 VLAN=bond0.10 VLAN=bond0.20 EOF
Le fichier 30-bond0.network indique que notre bond0 fait référence à nos deux interfaces avec vlan et que les interfaces ens4 et ens5 doivent être démarrées si elles sont inactives.
Nous arrivons au moment fatidique à savoir le démarrage/redémarrage du service systemd-networkd. Avant d’aller plus loin, assurez-vous d’avoir un accès iLO/iDrac/IPMI car si la configuration réseau n’est pas correcte vous n’aurez plus accès au serveur. 😳
# systemctl enable systemd-networkd # systemctl restart systemd-networkd
Si tout s’est bien passé, vous devriez toujours avoir la main sur le serveur o/o/ !!
Alors, ça fonctionne ?
La méthode pour débugger le réseau avec systemd-networkd est un poil différente, il est toujours possible d’utiliser les commandes fournies par iproute2 mais ces dernières risquent de ne pas être suffisantes pour systemd en lui même.
La commande networkctl permet d’avoir un aperçu rapide sur ce qui a été configuré.
# networkctl IDX LINK TYPE OPERATIONAL SETUP 1 lo loopback carrier unmanaged 2 ens3 ether routable configured 3 ens4 ether carrier configuring 4 ens5 ether carrier configuring 5 bond0 ether degraded configured 6 bond0.20 ether routable configured 7 bond0.10 ether routable configured 7 links listed.
Le retour de cette commande montre que l’interface bond0 est dans un état degraded, cela est tout à fait « normal » dans notre cas. La raison est que nous n’avons aucune adresse IP assignée sur cette interface.
À l’aide de la même commande, il est possible d’avoir de plus amples informations sur une interface spécifique.
# networkctl status bond0.10 ● 8: bond0.10 Link File: /etc/systemd/network/30-bond0-vlan10.link Network File: /etc/systemd/network/30-bond0-vlan10.network Type: ether State: routable (configured) Driver: 802.1Q VLAN Support HW Address: 4a:b3:ed:e1:d0:8c Address: 10.10.0.10 fe80::48b3:edff:fee1:d08c
Ici nous pouvons voir que les fichiers appliqués sur cette interface sont:
- /etc/systemd/network/30-bond1-vlan10.link
- /etc/systemd/network/30-bond1-vlan10.network
Il peut être aussi très utile de savoir ce qu’il s’est passé au niveau de systemd-networkd lors du démarrage du serveur, pour se faire journalctl est notre ami !
# journalctl --boot -u systemd-networkd
La commande dmesg permettra quant à elle de s’assurer que la MTU est correctement appliquée ou que les modules ont été correctement chargés.
[ 10.340774] 8021q: 802.1Q VLAN Support v1.8 [ 10.343750] e1000: ens5 changing MTU from 1500 to 9000 [ 10.399964] 8021q: adding VLAN 0 to HW filter on device ens5 [ 10.410635] bond0: Enslaving ens5 as an active interface with a down link [ 10.417307] e1000: ens4 changing MTU from 1500 to 9000 [ 10.493156] 8021q: adding VLAN 0 to HW filter on device ens4 [ 10.498667] bond0: Enslaving ens4 as an active interface with a down link [ 10.506141] 8021q: adding VLAN 0 to HW filter on device ens3 [ 12.417194] e1000: ens5 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX [ 12.430021] 8021q: adding VLAN 0 to HW filter on device bond0 [ 12.519335] e1000: ens4 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX [ 12.552724] bond0: link status definitely up for interface ens5, 1000 Mbps full duplex [ 12.552735] bond0: first active interface up! [ 12.552850] bond0: link status definitely up for interface ens4, 1000 Mbps full duplex
Au final il est assez simple de s’y retrouver après quelques recherches Google.
Petit bonus !!
Parce que je t’aime lecteur (si lecteur il y a), je joins un petit extra sur comment configurer une interface toute simple en DHCP avec une route statique et sa metric ainsi que des serveurs DNS personnalisés.
# cat << EOF > /etc/systemd/network/10-ens3.network [Match] Name=ens3 [Network] Description="DHCP example with static route and custom DNS" DHCP=ipv4 DNS=8.8.8.8 8.8.4.4 [Route] Destination=172.16.0.0/24 Metric=10 [DHCP] UseDNS=false EOF
L’option DNS de la section [Network] requiert le démarrage du service systemd-revolsed. Ce service se base sur le contenu du fichier /var/run/resolvconf/resolv.conf,/etc/resolv.conf est un lien symbolique vers ce fichier.
# systemctl enable systemd-resolved # systemctl restart systemd-resolved
Pensez bien à supprimer le contenu présent dans /etc/network/interfaces* et faites attention à cloud-init qui peut-être fourbe et recréer un fichier dans /etc/network/interfaces.d/ 😯
Conclusion
Nous y voilà, nous sommes passés à systemd-networkd (sans trop de douleur je l’espère). Cette transition nécessite quelques lectures afin de comprendre le fonctionnement et l’imbrication des services réseau de systemd.
Ci-dessus, j’ai rédigé une petite liste de pour et de contre (cette liste n’engage que moi).
Avantages:
- Configuration uniforme, que se soit sur Red Hat, CentOS, Arch, Ubuntu, Debian, Gentoo, etc…
- Projet très actif et en constante évolution
- Intégration d’udev à systemd ce qui permet beaucoup de personnalisation
- « Predictable Network Hostname » qui se base sur le slot ainsi que le module pour définir le nom
Désavantages:
- systemd-networkd ne gère pas encore toutes les fonctionnalités supportées par le système précédent
- « Production ready » depuis seulement la version 233
- Compliqué à prendre en main et peut faire peur au premier abord
Liens
- https://freedesktop.org/wiki/Software/systemd/
- http://lea-linux.org/documentations/Systemd
- https://www.freedesktop.org/software/systemd/man/systemd.link.html
- https://www.freedesktop.org/software/systemd/man/systemd.netdev.html
- https://www.freedesktop.org/software/systemd/man/systemd.network.html
Gaëtan Trellu (goldyfruit)
Derniers articles parGaëtan Trellu (goldyfruit) (voir tous)
- Qinling, let’s the journey begin! - 23 mai 2019
- systemd-networkd, l’âge de la maturité ? - 13 mars 2018
- Hyper-V, Nova, VxLAN et Open vSwitch, enfin une belle histoire ! - 31 décembre 2017
systemd-networkd, l’âge de la maturité ? par Gaëtan Trellu (goldyfruit) est sous Licence Creative Commons Internationale Attribution 4.0.