Académique Documents
Professionnel Documents
Culture Documents
Article publié dans le hors série spécial Haute Disponibilité du GNU/Linux Magazine France,
numéro 18 (Février/Mars 2004).
Introduction
Comment améliorer la disponibilité d'un serveur Linux sur le réseau ?
En sécurisant les différents éléments matériels composant le serveur si l'on considère que c'est le plus
souvent la panne de l'un de ces composants qui va conduire brutalement à l'arrêt de la machine
(jusqu'au remplacement de l'élément défectueux) et dans une moindre mesure un problème logiciel
qui peut alors être plus facilement résolu (on redémarre le logiciel en cause voire directement la
machine dans les cas les plus bloquants).
Sécuriser peut signifier choisir un composant offrant une durée de vie suffisante (exprimé en MTBF,
« Mean Time Between Failures », soit le temps moyen écoulé entre deux pannes) par rapport au
besoin exprimé.
Une autre approche, moins optimiste, considère qu'un composant est faillible par nature et qu'il
convient donc de prévoir la panne : Disposer de composants de secours qui viendront immédiatement
(et automatiquement) prendre la relève d'un composant défaillant est une réponse adaptée à ce délicat
problème.
La mémoire de masse (par exemple les disques durs avec une solution RAID), le ventilateur (pour
éviter les cas de surchauffe) ou encore l'alimentation sont des éléments qui peuvent facilement être
dupliqués sans trop de difficultés.
Mais peu de gens savent qu'il est aussi très simple de sécuriser les interfaces Ethernet en utilisant une
fonctionnalité du noyau Linux appelée « Channel Bonding ».
Cette technique consiste à surveiller l'état de la couche réseau pour pallier à la panne d'un contrôleur
ou à la déconnexion d'un câble : On regroupe de façon logicielle (et transparente pour l'utilisateur)
plusieurs contrôleurs réseaux en une seule et même interface Ethernet virtuelle afin de disposer de
plusieurs chemins physiques pour recevoir ou transmettre un même flux de données ; On multiplie les
chemins pour garantir la continuité du service.
Le support de cette fonctionnalité sous Linux se fait à travers le driver bonding dont la version
actuellement présente dans le noyau 2.4 (et 2.6) est directement dérivée du travail effectué par Donald
Becker, le gourou des drivers réseaux sous Linux. Une documentation en ligne est directement
disponible dans les sources du noyau sous [1] (à lire et à relire car c'est quasiment la seule source
d'informations disponible).
Le Channel Bonding utilisé sous Linux est l'équivalent du Trunking de SUN, du Port Trunking de D-
LINK ou encore de l'EtherChannel de CISCO. Tous ces systèmes ou équipements sont conformant à
la norme IEEE 802.3ad.
Pour être précis, il faut différencier l'agrégation dynamique de l'agrégation statique dans la norme
802.3ad :
• L'agrégation de liens statique (souvent appelée « trunking ») impose de configurer manuellement
et individuellement chaque système ou équipement. Plusieurs algorithmes sont proposées par la
norme pour garantir le bon acheminement des données ;
• A l'inverse, l'agrégation dynamique 802.3ad se base sur un échange dynamique d'informations
pour faciliter la création de groupes d'agrégation. Le protocole LACP (Link Agrégation Control
Protocol) est utilisé à cette intention : La méthode d'agrégation est choisie statiquement par
l'administrateur ou bien dynamiquement par LACP (l'administrateur peut aussi imposer des
contraintes d'agrégation puis laisser faire le protocole).
De fait, il n'existe pas un seul mais bien plusieurs algorithmes implémentés par le driver bonding :
• Active-backup (Sauvegarde active) : Seule une des interfaces est réellement utilisée. En cas de
panne, l'interface active suivante prend la relève ;
• Broadcast (Diffusion) : Les données sont envoyées à toutes les interfaces actives ;
• Balance-rr (Équilibrage de charge) : Les données sont transmises séquentiellement de la
première interface active à la dernière (de façon continue et cyclique) pour augmenter le nombre de
paquets envoyés et donc améliorer la bande passante ;
• Balance-xor (Mode XOR) : Permet d'utiliser toujours la même interface active pour les paquets
IP envoyés à une même adresse physique sur le réseau (adresse MAC) et améliore donc les
performances en parallélisant les transferts ;
Les algorithmes suivants sont disponibles depuis la version 2.4.22 du noyau (dont l'agrégation
dynamique 802.3ad) :
• balance-tlb (Équilibrage de charge auto-adaptatif en émission) : Le trafic en sortie est adapté à la
charge de chaque interface active. Par contre, chaque interface reçoit en entrée les flux qu'il initie :
Si cette dernière ne peut plus recevoir les données (passage en mode inactif), une autre interface
active récupère son adresse physique et donc ses données ;
• balance-alb (Équilibrage de charge auto-adaptatif en émission et en réception) : Tout comme le
mode balance-tlb, le trafic en sortie est adapté à la charge des interfaces actives. La différence se
situe dans la capacité de ce mode à équilibrer la charge en entrée en interceptant les requêtes ARP
et en les redistribuant pour diriger le flux vers l'interface la moins chargée ;
• 802.3ad (Agrégation dynamique des liens) : Permet de créer des groupes de liens qui partagent le
même paramétrage. L'intérêt est de disposer d'un mode qui ne nécessite pas forcément de
configuration manuelle : Les liens se découvrent mutuellement et sont agrégés automatiquement.
Tous ces modes offrent la même résistance aux pannes : En cas de problème sur une interface, cette
dernière est automatiquement retirée de la liste des interfaces actives sans que la continuité du service
ne soit perturbée.
Certains de ces modes imposent que le système ou l'équipement (switch ou hub) qui se trouve en face
supporte cette technologie :
• Dans le cas de deux machines sous Linux, il n'y a bien évidemment pas de problèmes ;
• Dans le cas d'un équipement réseau, cela dépend du mode que l'on souhaite utiliser :
• Si vous voulez utiliser les modes active-backup, balance-tlb ou balance-alb, vous n'êtes pas
contraint par le choix d'un équipement spécifique (préférez toutefois le switch au hub sauf dans
le cas du mode active-backup) ;
• Pour les autres modes, il faut que les équipements (obligatoirement de type switchs
paramétrables) supportent l'agrégation de liens conformément à la norme IEEE 802.3ad. Les
modes broadcast, balance-rr et balance-xor ont besoin d'un switch qui accepte le trunking
(plus courant sur le marché) alors que le mode 802.3ad nécessite un modèle supportant
l'agrégation dynamique. Hors de question d'utiliser un équipement conventionnel : Celui ci
serait notamment rendu inefficace par le fait que la même adresse physique (adresse MAC)
apparaîtrait sur plusieurs ports simultanément.
Le mode active-backup nous intéresse tout particulièrement car il va nous permettre de mettre en
oeuvre une solution reposant sur un équipement réseau standard (indifféremment de type hub ou
switch). Deux câbles ou plus sont connectés sur l'équipement : Un seul lien est actif et peut rendre
immédiatement la main à une interface de secours si un problème apparaît. Une fonctionnalité
intéressante permet de privilégier une interface par rapport à une autre : Si vous disposez de deux
interfaces, l'une en 100 Mb/s et l'autre en 10 Mb/s, il semble judicieux d'utiliser en priorité l'interface
la plus puissante. Une bonne solution pour recycler vos cartes réseaux obsolètes.
Les modes balance-tlb et balance-alb sont à privilégier si vous disposez d'un switch standard et que
vous souhaitez améliorer en même temps les performances.
Surveillance du lien réseau
Comment le driver bonding sait qu'un câble a été débranché ? La plupart des cartes Ethernet récentes
contiennent des registres que l'on peut adresser sous Linux et qui permettent d'interroger l'état du lien
ou de changer le type de négociation de la carte.
Trois méthodes sont disponibles :
• La consultation des registres MII [2] par l'utilisation de l'ioctl SIOCGMIIPHY ;
• L'utilisation de l'ioctl SIOCETHTOOL (registres ETHTOOL) ;
• Depuis la version 2.4.22, la primitive netif_carrier_ok() du noyau.
Bien évidemment, si une interface ne supporte pas l'une de ces trois méthodes, la déconnexion de son
câble Ethernet ne sera pas détectée (une fonctionnalité absolument inutile si l'on souhaite uniquement
améliorer la bande passante du réseau).
Les outils mii-tool et ethtool permettent d'interroger les registres ETHTOOL et MII et donnent
quelques indications pour savoir si vos cartes sont adaptées pour la haute disponibilité :
# mii-tool eth0
eth0 : negotiated 100baseTx-FD flow-control, link ok
# ethtool eth0
Link detected: yes
Quelle que soit la distribution, la commande mii-tool est issue du paquet net-tools alors que ethtool
possède son propre paquet du même nom (voir [3]).
Si vous ne disposez pas d'interfaces supportant l'une de ces différentes techniques, il existe une
dernière méthode qui consiste à envoyer régulièrement des requêtes ARP sur certaines adresses IP
présentes sur votre réseau afin de valider la disponibilité du trafic (une requête ARP, acronyme de
« Address Resolution Protocol », permet de récupérer l'adresse physique d'une adresse IP passée en
paramètre).
Ce mode est intéressant à plus d'un titre car autorisant la détection d'une panne bien au delà de la
surveillance des registres présents sur la carte. En effet, si l'équipement réseau sur lequel est branché
une de vos interfaces devait être coupé du réseau, la surveillance de ces registres ne vous sera
d'aucune utilité (le lien sera toujours marqué actif). Seule la méthode mettant en oeuvre une
surveillance ARP donnera de bon résultats.
Il n'est par contre pas possible de cumuler la surveillance de vos cartes réseaux avec la surveillance
basée sur ARP : Il vous faudra donc choisir.
Commande ifenslave
La commande ifenslave va nous permettre de construire l'interface bond en agrégeant plusieurs
devices réseaux passés en paramètre (dans la suite de cet article, on utilisera le terme bond pour
désigner l'ensemble des interfaces physiques appartenant à une interface virtuelle de type Channel
Bonding). Il est peu courant que cette commande soit disponible directement dans un paquet de votre
distribution (en dehors, à ma connaissance, de la distribution Redhat dans le paquet iputils) : Le plus
simple va être de la compiler à partir de ses sources : Ceci est même préférable pour disposer d'un
version compatible avec la version courante du driver bonding.
Les noyaux de version 2.4.12 et supérieurs mettent en effet à disposition une version adaptée
directement dans le répertoire /usr/src/linux/Documentation/network.
Suivez les instructions suivantes sous root pour compiler et installer la commande (en considérant que
les sources du noyau ainsi que les outils de compilation GNU sont installés) :
# cd /usr/src/linux/Documentation/network
# gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o
ifenslave
# mv ifenslave /sbin
Dans le cas du paramètre miimon, il est préférable de ne pas descendre en dessous de 10 ms : Une
valeur plus petite perturberait la fluidité de votre système (sur architecture x86, la fréquence
d'interruption de l'horloge du noyau 2.4 fonctionne sur une fréquence de 100 Hz et donc utilise des
tranches de temps de 10 ms). La valeur minimale conseillée est de 100 ms
Le paramètre downdelay est utile dans le cas d'une connexion avec un switch paramétrable
(supportant le trunking) dont la prise en compte d'un problème sur un port est moins rapide que celle
du driver bonding sous Linux. Ce paramètre permet de décaler le moment où le contrôleur est marqué
comme inactif dans le bond.
Certains switchs présentent leurs ports actifs avant que la connexion réseau ne soit réellement
opérationnelle (dans le cas d'un reboot, par exemple). Le paramètre updelay permet de prendre en
compte cette particularité. Par contre, si toutes les interfaces sont marquées en échec, le driver
bonding utilisera immédiatement la première interface active sans tenir compte de ce paramètre.
Passons à la pratique
Il est essentiel de disposer du driver bonding compilé en module pour pouvoir lui passer des
paramètres, ce qui est le cas dans la majorité des distributions.
Vous ne possédez qu'une seule interface ? Pas de panique, les exemples suivants fonctionnent aussi
avec une seule interface (même si cela ne sert pas à grand chose).
Si l'on veut que le bond soit activé directement au démarrage de la machine, la première chose à faire
est d'ajouter la ligne suivante dans le fichier /etc/modules.conf :
alias bond0 bonding
Cette ligne va permettre d'associer le device Ethernet bond0 avec le driver bonding. On peut bien
entendu ajouter plusieurs devices de type bond sur un même système en incrémentant le numéro du
device comme avec une interface Ethernet standard.
On ajoute ensuite la liste des paramètres que l'on va passer en option lors de l'appel du driver (on
s'assure de bien charger le driver des cartes réseaux avant celle du Channel Bonding) :
probeall bond0 eth0 eth1 ... eth[x] bonding
options bond0 mode=active-backup miimon=100
La possibilité de configurer le mode directement à partir de son libellé (active-backup) plutôt que de
son numéro (1) n'est disponible qu'à partir du noyau 2.4.21.
Pour de simples tests, il est possible de passer les paramètres directement en ligne de commande
comme dans l'exemple suivant :
# modprobe bonding mode=active-backup miimon=100
Il reste à activer l'interface dans la phase de démarrage de votre système : Certaines distributions
(comme la Redhat et ses dérivés) sont capables de directement prendre en charge cette étape dans
leurs fichiers de configuration. Je vous renvoie au manuel d'utilisation de la distribution Redhat pour
ceux que cela intéresse.
Une solution plus générique consiste à créer un script que nous allons placer dans le répertoire /
etc/init.d si l'on suit les recommandations du Linux Standard Base (LSB) :
#!/bin/bash
#
# Bonding configuration
#
# /etc/init.d/bonding
#
### BEGIN INIT INFO
# Provides: bonding
# Required-Start: $network
# Required-Stop:
# Default-Start: 3 5
# Default-Stop:
# Description: Configurer le Channel Bonding
### END INIT INFO
BOND_ADDR="192.168.4.1/24"
LISTE_ETH="eth0 eth1"
#ETH_ADDR="XX:XX:XX:XX:XX:XX"
case "$1" in
start)
ip link set dev bond0 down
if [ "$ETHER_ADDR" != "" ] ; then
ip link set dev bond0 addr ${ETHER_ADDR}
fi
ip addr add ${BOND_ADDR} brd + dev bond0
ip link set dev bond0 up
ifenslave bond0 ${LISTE_ETH}
;;
stop)
ip link set dev bond0 down
;;
*)
echo "Usage: $0 [start|stop]"
exit 1
esac
Nous voulons appeler notre script juste après le chargement de la couche réseau dans les runlevels 3
et 5 (l'option -d permet de désactiver le démarrage du script) :
# chkconfig -s bonding 35
Si l'on observe les caractéristiques de l'interface bond0 (ip link show bond0), on s'aperçoit que
l'adresse physique et celles de toutes les interfaces esclaves partagent la même valeur. Il s'agit en
réalité de l'adresse physique de la première interface réseau ajoutée dans le bond, eth0 dans notre cas.
On peut souhaiter configurer soi-même cette adresse physique en ajoutant la ligne suivante au tout
début de la section start :
ip link set dev bond0 addr XX:XX:XX:XX:XX:XX
Pour recouvrir la configuration initiale des adresses MAC de chaque carte réseau, il faut arrêter les
interfaces réseaux, supprimer puis recharger les drivers.
Comment connaître la configuration ou surveiller l'état de notre bond ? Le plus simple est de consulter
le fichier virtuel /proc/net/bond[x]/info (ou [x] correspond au numéro de votre bond). Cela peut
notamment permettre de connaître le nombre de fois qu'une interface a été désactivée depuis le
démarrage du serveur.
Par exemple, dans le cas de notre interface bond0 :
# cat /proc/net/bond0/info
Bonding Mode: active-backup
Currently Active Slave: eth0
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0
N'hésitez pas à consulter le démon syslog (/var/log/messages) pour suivre les changements dans
votre bond et tracer les éventuels dysfonctionnements. Par exemple, dans le cas de perte d'une
interface :
...
bond0 : link status definitely down for interface eth0, disabling it and making
interface eth1 the active one
...
Dans cet autre exemple, nous disposons d'un serveur sous Linux avec deux interfaces Ethernet et d'un
équipement réseau : Si l'équipement est standard, utilisez obligatoirement le mode active-backup,
balance-tlb ou balance-alb ; Sinon vous êtes libre de choisir le mode de votre choix.
Conclusion
Après avoir lu cet article, vous vous demandez peut être si il est encore possible d'améliorer la
disponibilité du serveur sur le réseau après avoir sécurisé tous les composants possibles et en
particulier les interfaces Ethernet ? On peut répondre par l'affirmative car si la perte d'une interface
n'est pas synonyme dans ce cas d'arrêt immédiat de la machine, il faudra songer à remplacer l'élément
défectueux assez vite : Soit vous pouvez prévoir un arrêt de maintenance (changement du composant
défectueux à froid), soit vous êtes contraint à la haute disponibilité de vos services et un arrêt du
serveur est absolument à proscrire.
Dans ce dernier cas, une seule solution : Le changement à chaud du composant. Vous devez utiliser
pour cela obligatoirement des composants CompactPCI (si votre serveur supporte ce type d'interface).
Le regroupement PCIMG (PCI Industrial Manufacturers Group) a mis en place une ensemble de
standards autour des composants CompactPCI pour faciliter la maintenance à chaud. Toute la chaîne
logicielle ou matérielle doit pouvoir supporter cette norme : Pour ceux que cela intéresse, je vous
conseille de vous dirigez vers le site officiel du support CompactPCI sous Linux [4] (PCIMGR
standard 2.12) et vers un article très intéressant qui a été publié sur le site linuxdevices.com [5].
Pour conclure, n'hésitez pas à faire un petit tour sur le site [6] traitant du Channel Bonding sous Linux
si vous souhaitez suivre l'évolution de ce driver assez méconnu mais qui mériterait d'être plus souvent
utilisé et déployé (à quand une configuration en standard dans toutes les distributions ?).
Lionel Tricon
Bookmarks
[1] Documentation officielle : /usr/src/linux/Documentation/networking/bonding.txt
[2] Outils de diagnostics réseaux (registres MII) : http://www.scyld.com/diag/
[3] Ethtool : http://www/.sourceforge.net/projects/gkernel
[4] PCIMG Hot-Swap site : http://www.sourceforge.net/projects/pcimg212-hs
[5] Support du CompactPCI : http://www.linuxdevices.com/articles/AT8382728818.html
[6] Driver Channel Bonding sous Linux : http://www.sourceforge.net/projects/bonding