Activité Service d'annuaire à haute disponibilité

Consigne

  1. Avant de commencer l’activité :
    • Lire la mise en situation, prendre connaissance des objectifs, du résultat attendu, et des ressources à disposition.
    • Lire une première fois en entier la section Mise en route.
  2. Effectuez le travail décrit dans la section Mise en route et effectuez les tâches demandées dans la section Tâches.

Mise en situation

Votre équipe est chargée de centraliser l’authentification des utilisateur·rice·s sur les serveurs Linux et les applications Web. Après une phase d’analyse, il a été décidé de mettre en place un système d’annuaire à haute disponibilité avec OpenLDAP. Actuellement, le système d’annuaire se compose de deux serveurs configurés pour une réplication en mode multiprovider, et une machine Linux utilise l’un des deux serveurs pour authentifier les utilisateur·rice·s du système. Votre tâche est de faire en sorte que si l’un des serveurs tombe en panne ou s’il doit faire l’objet d’opérations de maintenance, l’autre prenne automatiquement le relai.

Objectifs

À la fin de ce travail, en ayant accès au web, vous devez :

  1. Connaître la notion de haute disponibilité.
  2. Connaître la notion de grappe de serveurs (cluster).
  3. Connaître les notion de basculement (failover) et de répartition de charge (load balancing).
  4. Connaître les cas d’utilisation du basculement et de la répartition de charge.
  5. Connaître la notion d’adresse virtuelle
  6. Connaître l’existence du protocole VRRP et du logiciel Keepalived

Résultat attendu

  • Un rapport qui comprend :
    • Une marche à suivre permettant l’installation et la configuration de OpenLDAP.
    • Les réponses aux questions
  • Une machine virtuelle Linux (Ubuntu server 22.04) avec OpenLDAP configuré.

Ressources

Documents:

Matériel:

  • Un serveur Linux avec Ubuntu server 22.04 :
    • le nom complet est svr-m159-$NUM-ldap-02.lab.epai-ict.ch ($NUM est le numéro du réseau sur deux ou trois chiffres, en initialisant une variable d’environnement NUM, les commandes peuvent être exécutées telles quelles).
    • le nom d’utilisateur·rice est admin
    • les informations d’indentification se trouvent sur la fiche que vous avez reçu par courriel.

Mise en route

Grappe de serveurs

Une grappe de serveurs (cluster) est un groupe d’ordinateurs reliés en réseau et qui travaillent ensemble pour fournir un service et conçu de telle manière qu’elle apparaît sur le réseau comme un seul hôte. Une grappe de serveur est souvent mise en œuvre pour améliorer la disponibilité (availability) d’un service, pour améliorer l’évolutivité (scalability) d’un service en facilitant sa mise à l’échelle (scaling), ou les deux.

Avant de voir comment réaliser une grappe de serveur, arrêtons-nous un instant sur les notions de haute disponibilité et de mise à l’échelle.

Haute disponibilité

La haute disponibilité fait référence à la capacité d’un service à rester fonctionnel et accessible en continu, même si un serveur est arrêté à cause d’une défaillance matérielle ou logicielle, ou pour des tâches de maintenance. Il s’agit d’assurer un temps de fonctionnement maximal pour des services critiques (applications, bases de données, annuaires, etc.).

Dans un contrat de service, la disponibilité est généralement représentée par un pourcentage. Par exemple, une disponibilité de 90% autorise jusqu’à 36.5 jours d’interruption par an. Le pourcentage est souvent exprimé par un nombre de «neu». Une disponibilité de 90% se dit «un neuf», 99% se dit «deux neufs», 99.9% «trois neufs», et ainsi de suite. Une disponibilité de «cinq neufs» assure moins de 5.26 minutes d’interruption par an.

Pour atteindre la haute disponibilité, un système informatique est conçu avec des composants redondants: équipements réseau, disques (RAID), serveurs, etc., afin de garantir qu’aucun point de défaillance unique (single point of failure ou SPOF) ne puisse compromettre l’ensemble du système. La redondance des serveurs est souvent réalisée avec des grappes de serveur.

Mise à l’échelle

La mise à l’échelle (scaling) d’un service désigne l’augmentation de la capacité de traitement ce service. Elle peut être réalisée de deux manières :

  • La mise à l’échelle verticale (vertical scaling) consiste à augmenter la capacité de traitement d’un service en augmentant la puissance de l’ordinateur qui l’héberge par l’ajout de CPU, de mémoire, d’adaptateurs réseau, etc.
  • La mise à l’échelle horizontale (horizontal scaling) consiste à distribuer la charge de travail entre plusieurs ordinateurs. L’ajout d’ordinateurs permet d’augmenter la capacité de traitement.

La mise à l’échelle horizontale à l’aide d’une grappe de serveur est particulièrement souple et s’applique bien à des charges de travail qui ne modifie pas l’état interne des serveurs. Cela comprend, notamment, des charges de travail telles que des serveurs HTTP, des serveurs SQL en lecture seule et des serveurs d’annuaire en lecture seule.

En revanche, ce mode de mise à l’échelle ne s’applique pas aux charges de travail qui modifient l’état interne des serveurs (mémoire vive ou stockage local). C’est le cas, par exemple, des serveurs SQL, des serveurs d’annuaire, et des pare-feu. En effet, pour maintenir la cohérence des données dans la grappe, chaque opération d’écriture sur l’un des serveurs doit être propagée à tous les autres à l’aide de protocoles de synchronisation ou de réplication. Par conséquent, chaque serveur de la grappe traite directement ou indirectement la totalité de la charge de travail. L’ajout d’un serveur ne permet donc pas d’augmenter de la capacité de traitement. De plus, si un même objet est modifié sur plusieurs serveurs, il peut y avoir des conflits susceptibles de provoquer une corruption de données. Pour éviter ces conflits et garantir la cohérence des données, il est crucial qu’à tout instant, les requêtes qui modifient l’état du système soient traitées par un seul et unique serveur.

Lorsque la mise à l’échelle horizontale à l’aide d’une grappe ne peut pas être mise en œuvre et que la mise à l’échelle verticale n’est pas une option, il est possible d’avoir recours à des techniques de partitionnement. Dans le domaine des bases de données, l’une de ces techniques est le sharding. L’objectif est de diviser une base de données en plusieurs fragments indépendants (shards) qui peuvent ensuite être distribués sur plusieurs serveurs. Toutefois, contrairement aux grappes de serveurs, ces techniques ne sont généralement pas transparentes pour les clients.

Répartiteur de charge

Pour la mise à l’échelle, une grappe de serveur est généralement réalisée à l’aide d’un répartiteur de charge (load balancer). Ce dernier est un dispositif de routage qui opère au niveau de la couche transport (TCP/UDP) ou de la couche application (p. ex. HTTP) et dont la fonction est de distribuer la charge de travail aux serveurs de la grappe. Il existe différentes stratégies plus ou moins sophistiquées pour répartir la charge, notamment:

  • Round-robin : Chaque serveur reçoit les requêtes à tour de rôle, éventuellement en tenant compte d’une pondération (weighted round-robin) si les serveurs n’ont pas tous la même capacité de traitement.
  • Least connections : Les requêtes sont envoyées vers le serveur qui a le moins de connexions ouvertes en cours.
  • Least response time : Les requêtes sont envoyées vers le serveur qui a la réponse la plus rapide à la dernière requête.
  • IP Hash : La répartition se fait en fonction de l’adresse IP du client. Cette stratégie permet de garantir que les requêtes d’un même client seront toujours envoyées vers le même serveur.

Un répartiteur de charge comprend généralement une fonctionnalité de surveillance (monitoring) de l’état de santé des serveurs. Lorsqu’un des serveurs montre des signes de défaillance, il est retiré de la grappe et n’est plus pris en compte par l’algorithme de répartition jusqu’à ce qu’il soit à nouveau opérationnel.

Il existe un grand nombre de solutions libres et propriétaire pour les répartiteurs de charge. Parmi les solutions libres, on peut mentionner : Keepalived (couche 4) et HAProxy (couche 4 et 7). Selon les besoins, un répartiteur de charge peut prendre la forme d’une machine virtuelle, d’un container, ou d’un équipement réseau. La principale caractéristique à prendre en compte est le débit effectif (throughput) du dispositif, c’est-à-dire le nombre de paquets ou de requêtes que le dispositif est capable de transférer aux serveurs de la grappe par unité de temps.

Protocole de redondance d’adresse et de basculement

Une grappe de haute disponibilité est réalisée à l’aide d’un protocole de redondance d’adresse et de basculement (failover) tel que VRRP (Virtual Router Redundancy Protocol) ou CARP (Common Address Redundancy Protocol) qui permettent à plusieurs hôtes de partager une même adresse IP appelée adresse IP virtuelle. Leur fonction est d’assurer que dans un groupe de serveurs, l’un d’entre eux est actif, et les autres passifs. Le serveur actif reçoit le trafic destiné à l’adresse IP virtuelle. S’il cesse de fonctionner, l’un des serveurs passifs devient le serveur actif (basculement).

Le principe de fonctionnement est toujours le même:

  • Le serveur actif envoie périodiquement une annonce pour indiquer aux autres qu’il est opérationnel.
  • Au démarrage, un serveur est toujours passif et à l’écoute des annonces du serveur actif.
  • Si un serveur passif ne reçoit pas d’annonce durant une période de temps généralement configurable, il lance la procédure d’élection d’un nouveau serveur actif.

Contrairement aux répartiteurs de charge, le nombre de solutions de protocole de redondance d’adresse est plutôt limité. Sous Linux, la solution la plus courante est le protocole VRRP avec Keepalived, et ucarp est une implémentation du protocole CARP.

En pratique, les deux types de grappes sont souvent combinés. Un répartiteur de charge est souvent une grappe à haute disponibilité composée de deux ou trois répartiteurs de charge identiques.

Tâche

Installation et configuration de Keepalived

La première chose à faire d’installer Keepalived. Pour cela, connectez-vous au premier serveur et installez le paquet keepalived avec le gestionnaire de paquet (apt -y install keepalived), puis recommencer avec le second serveur.

Pour configurer Keepalived, nous avons besoin de l’adresse IP de chacun des deux serveurs et de l’adresse IP virtuelle. Pour cela, utilisez la commande dig pour obtenir les adresses correspondant aux noms d’hôtes des serveurs (svr-m159-$NUM-ldap-01.lab.epai-ict.ch et svr-m159-$NUM-ldap-02.lab.epai-ict.ch) ainsi que l’adresse virtuelle qui correspond au nom d’hôte svr-m159-$NUM-ldap.lab.epai-ict.ch (voir figure 1).

1
2
3
dig svr-m159-$NUM-ldap-01.lab.epai-ict.ch +short
dig svr-m159-$NUM-ldap-02.lab.epai-ict.ch +short
dig svr-m159-$NUM-ldap.lab.epai-ict.ch +short
Fig. 1 – Déterminer les adresses IP du premier et du second serveur et l'adresse IP virtuelle

Vos machines ont été préconfigurées et contiennent déjà un fichier de configuration pour Keepalived. Ce fichier est /etc/keepalived/keepalived.conf. Le contenu du fichier pour le premier et second serveur devrait correspondre à la figure 2. Assurez-vous que c’est bien le cas et que les différentes adresses IP correspondent à celles que vous avez obtenues avec la commande dig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vrrp_instance VI_1 {
    state MASTER
    interface ens192
    virtual_router_id 1<numéro de la machine>
    priority 101
    advert_int 1
    unicast_src_ip <adresse IP du premier serveur>
    unicast_peer {
        <adresse IP du second serveur>
    }
    authentication {
        auth_type PASS
        auth_pass 11<numéro de la machine>
    }
    virtual_ipaddress {
        <adresse IP virtuelle>
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vrrp_instance VI_1 {
    state BACKUP
    interface ens192
    virtual_router_id 1<numéro de la machine>
    priority 100
    advert_int 1
    unicast_src_ip <adresse IP du second serveur>
    unicast_peer {
        <adresse IP du premier serveur>
    }
    authentication {
        auth_type PASS
        auth_pass 11<numéro de la machine>
    }
    virtual_ipaddress {
         <adresse IP virtuelle>
    }
}
Fig. 2 – Fichier de configuration /etc/keepalived/keepalived.conf du premier et du second serveur

Lorsque vous avez vérifié que la configuration est correcte, démarrez le service keepalived sur les deux serveurs, puis assurez-vous que les deux services sont actifs. Pour cela, lancez les commandes suivantes sur chacun des deux serveurs.

1
2
sudo systemctl restart keepalived
sudo systemctl status keepalived
Fig. 3 – Démarrer et vérifier l'état du service Keepalived

Questions

  1. Sur le premier serveur (svr-m159-$NUM-ldap-01.lab.epai-ict.ch), affichez la ou les adresses IP de l’interface ens192 avec la commande ip -4 -br a s ens192. Relevez la ou les adresses. Que constatez-vous?
  2. Sur le second serveur (svr-m159-$NUM-ldap-02.lab.epai-ict.ch), lancez la même commande et relevez la ou les adresses de l’interface ens192. Que constatez-vous?
  3. Sur le premier serveur (svr-m159-$NUM-ldap-01.lab.epai-ict.ch), arrêtez le service Keealived avec la commande sudo systemctl stop keepalived et affichez le statut du service pour vous assurer qu’il est bien arrêté. Afficher une nouvelle fois la ou les adresses IP de l’interface `ens192. Que constatez-vous?
  4. Lancez la commande ping svr-m159-$NUM-ldap.lab.epai-ict.ch. Est-ce qu’un hôte répond? Si oui, quel est cet hôte? Peut-il s’agir du premier serveur (svr-m159-$NUM-ldap-01.lab.epai-ict.ch)?
  5. Sur le premier serveur (svr-m159-$NUM-ldap-01.lab.epai-ict.ch), redémarrez le service keepalived et afficher encore une fois la ou les adresses IP de l’interface ens192. Que constatez-vous?
  6. Analysez le fichier de configuration et expliquez brièvement tous les champs.

Activer la surveillance du serveur OpenLDAP

Vous devriez maintenant avoir une grappe de haute disponibilité opérationnelle. Le nom d’hôte de la grappe est svr-m159-$NUM-ldap.lab.epai-ict.ch. Le premier est serveur actif et tant qu’il envoie périodiquement une notification pour indiquer qu’il est opérationnel, le second est passif. Si le premier serveur n’envoie plus de notification, le second serveur prend le relai et devient le serveur actif.

Toutefois, la manière dont nous avons configuré Keepalived ne permet pas de déterminer si le serveur OpenLDAP (le daemon slapd) est bien en cours d’exécution et opérationnel. Le serveur est actif tant que le daemon keepalived est actif.

Keepalived permet d’exécuter périodiquement un script qui permet de vérifier la bonne santé du service fournit par la grappe de haute disponibilité, ici le serveur LDAP. Si le service est opérationnel, le script doit renvoyer le code d’erreur 0. N’importe quel autre code d’erreur indique que le service n’est plus opérationnel. Le code de la figure 4 montre un exemple de script qui vérifie que le processus slapd est en cours d’exécution et que le serveur LDAP fonctionne.

Sur le premier serveur (svr-m159-$NUM-ldap-01.lab.epai-ict.ch), copiez le code le code de la figure 4 dans un fichier et enregistrez-le sous le nom check-server-health.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#! /bin/bash

# Vérifie que le processus slapd est en cours d'exécution
slapdProc=$(/bin/pidof slapd)

if [ -z "$slapdProc" ]; then  
    echo "slapd is not running." >&2
    exit 1
fi

# Vérifie que OpenLDAP répond 
/usr/bin/ldapsearch -x -H ldap://localhost -b '' -s base -l 3 > /dev/null 2>&1
ldapsearchRes=$?

if [ "$ldapsearchRes" -gt 0 ]; then
    echo "slapd is not responding." >&2
    exit 1
fi

# Tout est ok
echo "ok"
exit 0
Fig. 4 – Script de vérification de l'état de santé du serveur OpenLDAP (/usr/local/bin/check-server-health)

Mofifiez les permissions du script check-server-health et copiez le fichier dans le répertoire /usr/local/bin avec les commandes ci-après.

1
2
chmod 770 ./check-server-health
sudo cp ./check-server-health /usr/local/bin/check-server-health
Fig. 5 – Ajuster les permissions du script et copiez le fichier dans /usr/local/bin

Véfifiez que le script fonctionne en l’exécutant avec la commande sudo check-server-health. Si le daemon slapd est actif, le script doit écrire ok dans la sortie standard. Essayez d’arrêter le daemon slap et exécutez le script une nouvelle fois. Cette fois, vous devriez voir le message “slapd is not running.”.

Si tout fonctionne correctement, modifiez la configuration de Keepalived pour qu’elle ressemble à celle de la figure 6 et redémarrez le service keepalived.

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
vrrp_script check_server_health {
  script "/usr/local/bin/check-server-health"
  interval 2
  fall 2
  rise 2
}
vrrp_instance VI_1 {
    state MASTER
    interface ens192
    virtual_router_id 1<numéro de la machine>
    priority 101
    advert_int 1
    unicast_src_ip <adresse IP du premier serveur>
    unicast_peer {
        <adresse IP du second serveur>
    }
    authentication {
        auth_type PASS
        auth_pass 11<numéro de la machine>
    }
    virtual_ipaddress {
        <adresse IP virtuelle>
    }
    track_script {
        check_server_health
    }
}
Fig. 6 – Configuration de la surveillance de l'état de santé du serveur

Si votre configuration est correcte, en arrêtant le service slapd sur le premier serveur, le second serveur devrait devenir actif.

Questions

  1. Expliquez ce que fait le script de la figure 4.
  2. Expliquez les modifications apportées à la configuration.
  3. (optionel) Modifiez la configuration du serveur svr-m159-$NUM.lab.epai-ict.ch pour utiliser la grappe à haute disponibilité (svr-m159-$NUM-ldap.lab.epai-ict.ch) au lieu du serveur svr-m159-$NUM-ldap-01.lab.epai-ict.ch.