1. Présentation du projet

1-1. Le contexte théorique du projet

La majorité des applications sur Internet sont accessibles via le protocole HTTP. Ces applications sont hébergées sur des serveurs Web. Cependant avec l’augmentation du nombre d’utilisateurs de ces applications, le temps de réponse aux requêtes des clients devient assez important. Répondre efficacement aux requêtes des utilisateurs nécessite le déploiement de plusieurs serveurs Web sur plusieurs machines (un cluster de machines). Les machines du cluster peuvent avoir des caractéristiques différentes (CPU, RAM…). Au niveau de ce cluster, une machine centrale va recevoir les requêtes des utilisateurs et elle va les répartir sur l’ensemble des serveurs. La répartition doit prendre en considération les caractéristiques de chaque serveur afin d’avoir une répartition équilibrée (chaque serveur va avoir un nombre de requêtes à traiter selon ses caractéristiques).

1-2. La description du projet

L’opération de l’orientation des nouveaux bacheliers se déroule chaque année. Le nombre de bacheliers ne cesse d’augmenter chaque année, ce qui engendre un accès de plus en plus intense aux serveurs (notamment dans la période de l’annonce des résultats de l’orientation). Pour faire face à ce problème, les responsables ont mis en place un cluster de serveurs Web. Un logiciel est utilisé pour répartir les requêtes sur les différents serveurs. Chaque année, de nouveaux serveurs physiques sont acquis et actuellement le cluster est constitué d’un ensemble de serveurs ayant différentes caractéristiques. Le logiciel utilisé ne prend pas en compte l’équilibrage de charge, alors chaque serveur va avoir la même charge (nombre de requêtes) ce qui va créer un déséquilibre dans la répartition des requêtes. Pour exploiter efficacement les serveurs, ils pensent mettre en place un cluster de serveurs Web avec un équilibrage de charge, et donc ont lancé un appel d’offres pour l’acquisition d’une plate-forme logicielle pour gérer un cluster d’équilibrage de charge. Suite à cet appel d’offres, ils ont retenu deux offres, la première est basée sur LVS (Linux Virtual Server) et la deuxième sur Haproxy. Ils ont donc fait appel à vous pour les aider à choisir la meilleure offre.
On vous demande de répondre à cet appel d’offres en déployant les deux outils et en effectuant une série de tests de performance pour choisir le meilleur outil.


1-3. Objectifs du projet

  1. Déployer le cluster :

    • Donner la description détaillée des étapes du déploiement (installation et configuration) du cluster (déploiement de LVS et Haproxy).
    • Effectuer des tests fonctionnels (LVS et Haproxy).

  2. L’évaluation des performances du cluster et étude comparative :

    • Effectuer une série de tests de performance pour évaluer les performances du cluster (LVS et Haproxy).
    • Selon les résultats, faire une étude comparative entre LVS et HaProxy.


Quelques exigences techniques :

En plus de LVS et Haproxy, on vous demande de déployer les logiciels suivants :

  • Ganglia : un outil de supervision dédié au cluster. Ganglia va permettre de visualiser l’état du cluster (consommation des ressources au niveau de chaque nÅ“ud du cluster).
  • NTP : un serveur de temps pour synchroniser entre les nÅ“uds du cluster.
  • SSH : accès distant au cluster et communication entre les nÅ“uds du cluster.



Il est aussi exigé d’utiliser :

  • Apache comme serveur Web ;
  • CentOS comme distribution Linux ;
  • machines virtuelles pour la mise en place du cluster ;
  • VirtualBox pour la virtualisation.

Pour l’outil d’évaluation des performances, vous pouvez utiliser soit l’utilitaire ab (Apache benchmark) ou l’outil Apache-Jmeter. Serveurs Web sur plusieurs machines (un cluster de machines). Les machines du cluster peuvent avoir des caractéristiques différentes (CPU, RAM…). Au niveau de ce cluster, une machine centrale va recevoir les requêtes des utilisateurs et elle va les répartir sur l’ensemble des serveurs. La répartition doit prendre en considération les caractéristiques de chaque serveur afin d’avoir une répartition équilibrée (chaque serveur va avoir un nombre de requêtes à traiter selon ces caractéristiques).
Nous avons choisi d'utiliser Ganglia.

2. Déploiement du cluster – description technique

2-1. Introduction

Avant, le contenu Web était en majeure partie statique et donc très facile à délivrer rapidement aux clients, mais aujourd’hui, le contenu des pages Web est devenu principalement dynamique, permettant l’interaction entre l’utilisateur et les services offerts, et induisant une forte charge sur les serveurs Web tout en exigeant des réponses rapides, une haute performance ainsi qu’une disponibilité permanente des applications. Pour cela, les applications Web doivent être en mesure de fonctionner sur plusieurs serveurs Web de manière à exploiter pleinement leur performance et cela dans le but de supporter l’accroissement dynamique et soudain du nombre de clients et donc de requêtes, grâce à des mécanismes de scalabilité, répartition de charge et haute disponibilité. Dans le cas de notre projet, ceci se fera à travers la mise en place de deux principaux outils : LVS (Linux Virtual Server) et HAProxy (High Availability Proxy).

2-2. HAProxy

2-2-1. Description

HAProxy est une solution open source très flexible offrant des fonctionnalités de répartiteur de charge, reverse proxy HTTP et proxy TCP (c’est-à-dire qu’il fonctionne aussi bien sur la couche 4 que sur la couche 7 du modèle OSI) ainsi que des services de haute disponibilité (HA). Il est utilisé généralement dans le cas d’un fort trafic et c’est d’ailleurs l’une des raisons pour laquelle il est utilisé par plusieurs grands sites Web, notamment GitHub, Instagram, Twitter, Stack Overflow, Reddit, Tumblr, Yelp et tant d’autres.

2-2-2. Fonctionnalités

  • Répartition de charge à l’aide de plus de neuf algorithmes d’ordonnancement. Ceci permet de router les requêtes émanant de différents clients vers les serveurs de backend de manière à ce que la charge soit équilibrée au mieux et en évitant toute surcharge sur les serveurs pour permettre un service de qualité rapide et performant. Ceci se fait selon deux modes : le mode TCP et le mode HTTP.
  • Proxy TCP permettant de relayer le trafic entre le client et le serveur en rattachant la connexion ouverte avec le client au serveur pour faire passer le trafic, il joue donc le rôle d’intermédiaire entre les deux.
  • Proxy inverse HTTP, appelé aussi passerelle ou gateway, dans ce cas HAProxy joue le rôle d’un serveur proxy ouvrant deux connexions différentes avec le client et le serveur et fait passer les requêtes entre les deux bouts. L’avantage majeur de ce dernier est de « cacher » des informations sur les serveurs backends.
  • Offre des mécanismes assurant la haute disponibilité afin de garantir la continuité de service et ceci à travers l’utilisation automatique de serveurs répliqués en cas de panne par exemple.
  • Offre un stack SSL avec énormément de fonctionnalités et joue le rôle de terminaison SSL, il décharge donc les serveurs Web de tout ce qui est traitement lié au cryptage/décryptage SSL/TLS.
  • Optimisation des ressources et minimisation du temps de réponse.
  • Optimise le trafic et protège les serveurs en évitant de transmettre toute requête invalide aux serveurs.
  • Il offre la possibilité de continuer à fonctionner normalement même en cas de panne des serveurs backend.
  • Permet de faire du monitoring concernant les serveurs et HAProxy lui-même.
  • Offre la possibilité de choisir un serveur bien précis pour lui transmettre la requête et ce, en se basant sur n’importe quel élément figurant dans la requête reçue. Ceci est particulièrement utile pour gérer les sessions des utilisateurs pour qu’un utilisateur soit toujours envoyé vers le même serveur.
  • Il offre des services de health checks permettant de vérifier le bon fonctionnement des serveurs backend ainsi que l’élimination de serveurs défaillants. Ceci se fait à travers un certain nombre de fonctionnalités de vérification offertes par HAProxy.
  • Offre un certain nombre de métriques pouvant être utilisées afin de déterminer les performances et l’état de l’architecture en évaluant certains critères frontend (c’est-à-dire entre HAProxy et les clients) et backend (entre HAProxy et les serveurs), par exemple, il est possible de connaître le nombre de requêtes par seconde, nombre de sessions créées par seconde, nombre d’erreurs HTTP côté client et côté serveur, nombre de tentatives de connexion, etc. Ceci a principalement pour but d’analyser le trafic et prendre des décisions en cas de problème pour améliorer le rendement et les performances.
  • Offre la possibilité d’avoir des connexions chiffrées des deux côtés (client et serveur) avec SSL/TLS.
  • Assure un certain niveau de sécurité en offrant une protection contre les attaques DDoS par exemple en gardant les statistiques de connexions, adresses IP, URL, cookies, etc. pour ensuite appliquer les actions appropriées comme le blocage.

2-2-3. Répartition de charge avec HAProxy

HAProxy offre des fonctionnalités de répartition de charge (load balancing) assez complètes, dans le sens où elles permettent de réaliser plusieurs configurations personnalisées et adaptées aux besoins de ses utilisateurs. Il existe deux modes de load balancing offerts par HAProxy : le mode TCP et le mode HTTP.

2-2-3-1. Mode de load balancing : TCP

Les décisions de répartition de charge se font sur la base de toute la connexion. Dans ce cas, l’entête de la requête HTTP n’est pas évalué.

2-2-3-2. Mode de load balancing : HTTP

Les décisions de répartition de charge se font uniquement sur la base de la requête (chaque requête séparément). Cette méthode permet par exemple de choisir le backend selon l’URL de la requête.

2-2-4. Fonctionnement

HAProxy considéré comme deux half-proxy, est composé de deux parties essentielles, la partie frontend qui est directement en contact avec le côté client et reste en écoute de ce dernier et la partie backend, du côté des serveurs. Quand une requête est reçue par le frontend de HAProxy à partir d’un client, celui-ci applique alors les règles définies à ce niveau telles que le blocage de requêtes, modification des entêtes ou tout simplement l’interception de ces dernières pour établir des statistiques. Les requêtes sont ensuite envoyées vers le côté backend de HAProxy, qui est relié directement aux serveurs Web où la stratégie de load balancing est appliquée et que se termine par l’envoi de la requête vers le serveur choisi. Après le traitement de la requête par le serveur, sa réponse est transmise à HAProxy qui peut effectuer quelques traitements dessus ou l’envoyer directement au client via le frontend. Bien évidemment, HAProxy peut être vu comme full-proxy, c’est-à-dire l’union du frontend et du backend.

Image non disponible

2-2-5. Algorithmes d’ordonnancement

Plus de neuf algorithmes d’ordonnancement sont offerts par HAProxy, nous citons les plus fréquents d’usage :

  1. Round robin : c’est le plus communément utilisé, son principe consiste à distribuer les requêtes sur les différents serveurs un à un en rebouclant. Le RR standard fonctionne de façon « automatique » en adressant chaque serveur à tour de rôle à la chaîne, mais il existe une variante du RR à laquelle on peut ajouter des pondérations dans le cas de serveurs hétérogènes afin de bénéficier au maximum des performances de chaque nœud du cluster.
  2. Least connection : il consiste à déterminer le serveur qui a été le plus anciennement utilisé et avec le plus petit nombre de connexions actives afin de lui transmettre la requête.
  3. Source : se base sur l’adresse IP source du client hachée pour déterminer le serveur auquel envoyer la requête. De ce fait, un client retombera toujours sur le même serveur qui pourrait être une solution quant à la persistance de sessions (mais assez limitée).
  4. URI : le serveur sélectionné dépend directement de l’URI de la requête HTTP. Dans ce cas, on calcule le haché de l’URI (deux cas possibles : la partie gauche de l’URI uniquement (avant le point d’interrogation, c’est-à-dire avant le passage de paramètres) ou alors l’URI entière si elle contient tous les paramètres). Cet haché nous permettra de définir le serveur vers lequel envoyer notre requête. Cet algorithme est généralement utilisé dans le cas de proxy de cache dans le but de maximiser le nombre de « hits » (accès au cache et obtention de la donnée avec succès).
  5. HDR : se base sur un champ spécifique de l’entête HTTP afin de déterminer le serveur destination.

Remarque : les algorithmes de round robin, least connection et les algorithmes à hachage permettent de faire une pondération dynamique des serveurs, ce qui nous offre la possibilité de changer le poids d’un serveur.

2-2-6. Persistance des sessions

HAProxy offre diverses méthodes pour assurer la persistance des sessions appelée aussi « Stickiness », celle-ci peut être basée sur divers paramètres tels que l’adresse IP source, l’URL, cookies, sessions, etc., afin de déterminer le bon serveur et assurer que le client retombe toujours sur ce dernier et qu’il ne soit pas déconnecté à chaque envoi de requête, car il ne tombe pas sur le serveur contenant les informations concernant sa session. Les informations de mapping entre client/serveur sont gardées dans une table au niveau de HAProxy appelée stickiness table, elle contient comme entrée le client et le serveur contentant les informations de ce client.

2-2-7. Haute disponibilité

Les algorithmes d’équilibrage de charge naïfs augmentent le risque d’indisponibilité des serveurs, car ils augmentent la probabilité qu’un client tombe sur un serveur indisponible, il est donc très important de garantir la disponibilité des serveurs à tout moment aux clients et éviter l’arrêt de service. Afin de garantir cela, HAProxy offre des mécanismes permettant la mise en place de la haute disponibilité. HAProxy permet d’effectuer des tests périodiques sur l’état des serveurs afin de vérifier leur bon fonctionnement à travers ce que l’on appelle les health checks, ainsi une requête est délivrée à un serveur que s’il est pleinement opérationnel. Il permet aussi de supprimer un nœud (serveur) sans affecter le fonctionnement de l’architecture globale, sans oublier le fait qu’il utilise automatiquement les serveurs backup quand une panne est détectée, ce qui permet d’avoir un service continu malgré l’arrêt d’un serveur. Par défaut, les charges sont réparties équitablement sur le reste des serveurs quand l’un d’eux tombe en panne.

2-3. LVS

2-3-1. Description

LVS est un projet gratuit et open source lancé par Wensong Zhang en mai 1998, sous licence GNU General Public License (GPL), version 2.

La mission de ce projet était de construire un serveur de haute performance pour Linux utilisant la technologie du clustering.

Il est principalement composé de IPVS : un logiciel d’équilibrage de charge IP implanté dans le noyau Linux.

Le code de LVS est fusionné dans les versions 2.4.x et plus récentes du noyau Linux 1.

2-3-2. Load Balancing

2-3-2-1. Layer 4 Load Balancing (IPVS)

L’équilibrage de charge au niveau de la couche 4 est implémenté à travers IPVS, celui-ci dirige les requêtes aux serveurs du cluster en utilisant l’une des trois techniques de load balancing IP ci-dessous :

  • Direct Routing :le load balancer et les serveurs du cluster partagent une même adresse virtuelle. Les requêtes des utilisateurs sont envoyées vers le load balancer qui examine l’adresse et le port de destination et vérifie s’ils correspondent bien à un des services du cluster. Un algorithme d’ordonnancement décide ensuite du serveur vers lequel la requête est envoyée. Une fois traitée, le serveur envoie une réponse directement au client sans passer par le load balancer (d’où le nom « routage direct »). À noter que les serveurs et le load balancer doivent être dans le même réseau local.

Image non disponible

  • IP Tunneling : cette technique suit le même principe que le « Direct Routing », sauf que le load balancer et les serveurs peuvent ne pas appartenir au même réseau local. Un tunnel est alors créé entre eux et les paquets reçus par le load balancer sont encapsulés dans des entêtes IP et envoyés vers les serveurs.

Image non disponible

  • NAT : lorsque le load balancer reçoit les requêtes des utilisateurs, il choisit un serveur grâce à un algorithme d’ordonnancement et l’adresse et le port de destination sont translatés vers ceux du serveur choisi. Une fois la requête traitée, la réponse est renvoyée vers le load balancer qui va remplacer l’adresse et le port source par ceux du load balancer (plus précisément ceux du service virtuel) pour finalement l’envoyer à l’utilisateur.

Image non disponible

2-3-2-2. Layer 7 Load Balancing (KTCPVS)

Le système KTCPVS redirige les requêtes aux différents serveurs en se basant sur le contenu de ces dernières. Les différents composants sont reliés à travers des LAN/WAN.

Image non disponible

2-3-3. Algorithmes d’ordonnancement

LVS supporte un grand nombre d’algorithmes, ils sont listés ci-dessous :

  1. Round robin : les serveurs sont choisis à tour de rôle de manière cyclique.
  2. Weighted round robin : les serveurs sont choisis à tour de rôle, mais relativement à leur poids, c’est-à-dire que les serveurs ayant les poids les plus forts seront désignés en premier et recevront plus de requêtes par rapport à ceux ayant des poids plus faibles.
  3. Least connection : le serveur ayant le moins de connexions (donc le moins chargé) est choisi.
  4. Weighted least connection : le serveur ayant le moins de connexions relativement à son poids est choisi, c’est-à-dire que celui qui minimise le rapport Ci/Wi est désigné (Avec Ci le nombre de connexions du serveur i et Wi son poids).
  5. Destination hashing : l’adresse IP destination est hachée et le choix du serveur se fera selon cette valeur.
  6. Source hashing : l’adresse IP source est hachée et le choix du serveur se fera selon cette valeur.
  7. Locality-based least connection : un groupe d’utilisateurs est affecté à chaque serveur (il est choisi en utilisant l’algorithme du weighted least connection), et si celui-ci n’est pas surchargé, il recevra les requêtes des clients qui lui sont attachés. Dans le cas contraire, le serveur qui a un nombre de connexions inférieur à la moitié de son poids est désigné.
  8. Locality-Based least connection with replication : cet algorithme suit le même principe que celui du locality-based least connection, sauf que les groupes d’utilisateurs sont affectés non pas à un seul serveur, mais à un ensemble de serveurs, et dans cet ensemble, un serveur est désigné en utilisant l’algorithme du weighted least connection.
  9. Shortest expected delay : le serveur ayant le délai le plus court (estimé selon une formule basée sur le nombre de connexions et le poids) est choisi.
  10. Never queue : s’il y a un serveur idle (au repos), il sera choisi, sinon, l’algorithme du shortest expected delay sera utilisé.

2-3-4. Persistance

Il arrive parfois que deux connexions d’un même client se doivent d’être attribuées au même serveur pour des raisons fonctionnelles ou de performance. Par exemple, FTP qui nécessite l’établissement d’une connexion entre le port 21 du serveur et le port du client ainsi que l’envoi des données à travers le port 22. Le protocole SSL est également un exemple puisqu’un ID de session est généré pour l’utilisateur, il serait donc intéressant de le garder pour des connexions futures.

LVS implémente cette fonctionnalité en utilisant des « templates » de connexion. Lorsque l’utilisateur accède pour la première fois au serveur, un template est créé entre cet utilisateur et le serveur qui a été choisi avec des informations sur les ports utilisés, et pour chaque connexion, une entrée est générée dans une table de hachage au niveau du load balancer. Le template peut expirer dans un délai configurable, cependant, tant que toutes les connexions correspondant au template ne se terminent pas, il n’expirera pas.

3. Implémentation

3-1. Mise en place de la plateforme – topologie

Image non disponible

 

Image non disponible

3-2. Mise en place des serveurs Web

3-2-1. Installation de Apache

Il suffit d’exécuter la commande suivante :

 
Sélectionnez
sudo yum -y install httpd


Pour démarrer le service :

 
Sélectionnez
service httpd start

3-2-2. Installation de MySQL

Il suffit d’exécuter la commande suivante :

 
Sélectionnez
sudo yum -y install mysql-server mysql-client

Pour démarrer le service :

 
Sélectionnez
service mysqld start

3-2-3. Installation de SSH

Il suffit d’exécuter la commande suivante :

 
Sélectionnez
sudo yum -y install openssh

Pour démarrer le service :

 
Sélectionnez
service sshd start

3-3. Mise en place de HAProxy

Dans cette partie, nous allons détailler l’installation du logiciel HaProxy version 1.7.8.

3-3-1. Installation

Tout d’abord, avant l’installation de HAProxy, il est nécessaire d’installer quelques prérequis pour pouvoir télécharger et compiler le programme :

 
Sélectionnez
sudo yum install wget
sudo yum install gcc pcre-static pcre-devel -y

Ensuite, on télécharge la version 1.7.8 de HAProxy avec la commande suivante :

 
Sélectionnez
wget https://www.haproxy.org/download/1.7/src/haproxy-1.7.8.tar.gz -O ~/haproxy.tar.gz



On compile le logiciel en utilisant les commandes suivantes :

 
Sélectionnez
tar xzvf ~/haproxy.tar.gz -C ~ 
cd ~/haproxy-1.7.8
make TARGET=linux2628
sudo make install


On vérifie que l’installation a bien eu lieu :

 
Sélectionnez
haproxy -v


On a :

 
Sélectionnez
HAProxy version 1.7.8 2017/07/07

3-3-2. Configuration

Pour la configuration de HAProxy, tout d’abord il est nécessaire de créer les répertoires suivants pour les fichiers de configuration et de statistiques :

 
Sélectionnez
sudo mkdir -p /etc/haproxy
sudo mkdir -p /var/lib/haproxy
sudo touch /var/lib/haproxy/stats

On ajoute un lien symbolique du binaire d’HAProxy dans le répertoire /usr/sbin pour pouvoir le lancer en tant qu’utilisateur normal (Non root) :

 
Sélectionnez
sudo ln -s /usr/local/sbin/haproxy /usr/sbin/haproxy

On ajoute HAProxy en tant que service système :

 
Sélectionnez
sudo cp ~/haproxy-1.7.8/examples/haproxy.init /etc/init.d/haproxy
sudo chmod 755 /etc/init.d/haproxy
sudo systemctl daemon-reload

On modifie le fichier de configuration /etc/haproxy/haproxy.cfg avec la configuration suivante :

 
Sélectionnez
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats timeout 30s
user haproxy
group haproxy
daemon

defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000

frontend http_front
bind *:80
stats uri /haproxy?stats
default_backend http_back

backend http_back
balance roundrobin
server webserver1 192.168.1.11:80 check weight 45
server webserver2 192.168.1.12:80 check weight 20
server webserver3 192.168.1.13:80 check weight 35


Dans l’exemple ci-dessus, l’algorithme d’ordonnancement est le round robin et les poids des serveurs Web sont respectivement : 45 %, 20 % et 35 %.

3-4. Mise en place de LVS

Dans cette partie, nous allons détailler l’installation du logiciel LVS version 1.26.

3-4-1. Installation

Avant d’installer LVS, il est nécessaire d’installer les packages suivants pour pouvoir télécharger et compiler le source de LVS :

 
Sélectionnez
sudo yum -y install wget gcc pcre-static pcre-devel libnl* popt*


Ensuite, nous allons récupérer la version 1.26 de LVS destinée au noyau 2.6 de Linux comme suit :

 
Sélectionnez
wget http://www.linuxvirtualserver.org/software/kernel-2.6/ipvsadm-1.26.tar.gz

Il suffit maintenant de décompresser et de compiler LVS en utilisant les commandes suivantes :

 
Sélectionnez
tar -xvf ipvsadm-1.26.tar.gz
cd ipvsadm-1.26
sudo make install


Enfin, il faut activer le IP forwarding afin de pouvoir faire transiter les paquets d’une interface à une autre, pour cela, nous allons modifier le fichier /etc/sysctl.conf comme suit :

 
Sélectionnez
net.ipv4.ip_forward = 1

Il ne nous reste plus qu’à redémarrer le service et faire en sorte qu’il soit automatiquement activé à l’allumage de la machine :

 
Sélectionnez
service ipvsadm restart
chkconfig ipvsadm on

3-4-2. Configuration

Après avoir installé LVS sur le load balancer, nous passons maintenant à sa configuration en suivant les étapes ci-dessous :
On vide la table ipvsadm en exécutant la commande suivante :

 
Sélectionnez
# ipvsadm -C


On modifie ensuite le fichier de configuration de LVS /etc/sysconfig/ipvsadm, afin d’y spécifier le load balancer ainsi que les trois serveurs Web que nous avons initialement mis en place. Nous avons choisi comme algorithme WRR (Weighted Round Robin) qui nous permet de définir des poids pour chaque serveur (65 %, 15 % et 20 % pour les serveurs Web 1, 2 et 3 respectivement) afin de lui transmettre le taux de requêtes qu’il peut supporter selon ses performances. Voici le contenu du fichier de configuration de LVS :

 
Sélectionnez
-A -t 192.168.43.9:80 -s wrr
-a -t 192.168.43.9:80 -r 192.168.1.11:80 -m -w 65
-a -t 192.168.43.9:80 -r 192.168.1.12:80 -m -w 15
-a -t 192.168.43.9:80 -r 192.168.1.13:80 -m -w 20

Afin que les modifications soient prises en compte, on redémarre le service ipvsadm de la manière suivante :

 
Sélectionnez
# service ipvsadm restart


On vérifie ensuite, que la configuration a bien été prise en charge, en affichant la table ipvsadm comme suit :

 
Sélectionnez
# ipvsadm -l

Afin de permettre la communication entre les serveurs Web et le load balancer LVS, on doit définir l’interface interne (côté serveur) de LVS comme étant la passerelle par défaut de ces derniers.

4. Déploiement de NTP

4-1. Introduction

La notion de temps est critique pour les systèmes informatiques. C'est la seule référence qu'un réseau a pour savoir quand les applications et les processus doivent être ou ont été faits. La solution pour assurer la synchronisation du réseau est assez simple et relativement peu coûteuse : un serveur de temps NTP.

Dans cette partie, nous allons énumérer les étapes de déploiement de NTP (Network Time Protocol) permettant d’assurer une synchronisation temporelle entre tous les nœuds. On passera ensuite aux étapes de déploiement de Ganglia pour monitorer notre cluster et enfin, on parlera des étapes de mise en place de SSH sur les serveurs Web pour effectuer des échanges sécurisés en cas de nécessité.

4-2. Déploiement de NTP

Dans cette première partie, nous allons citer les étapes suivies afin de configurer NTP sur les répartiteurs de charge dans un premier temps et sur les serveurs Web dans un second temps.

4-2-1. Configuration du serveur NTP

  • Installer NTP : ceci se fait via la commande suivante :

     
    Sélectionnez
    # yum install ntp
  • Choisir le Pool de serveurs de temps mondiaux avec lesquels notre serveur doit se synchroniser sur www.pool.ntp.org, plus précisément sur : www.pool.ntp.org/zone/dz

     
    Sélectionnez
    server 0.africa.pool.ntp.org
    server 1.africa.pool.ntp.org
    server 2.africa.pool.ntp.org
    server 3.africa.pool.ntp.org
  • Configurer notre serveur NTP en éditant le fichier de configuration de NTP : /etc/ntp.conf comme suit :

    • Ajouter le pool de serveurs mondiaux correspondant à notre région (Algérie) pour que notre serveur se synchronise avec ces derniers.
    • Ajouter la directive fudge 127.127.1.10 stratum 10 constitue un serveur fictif en guise d'IP fallback, au cas où la source de temps extérieure deviendrait momentanément indisponible. En cas d'indisponibilité du serveur distant, NTP continuera à tourner en se basant sur ce fonctionnement-là.
    • Autoriser les clients de notre réseau à envoyer des requêtes de synchronisation à notre serveur en ajoutant la ligne suivante :
 
Sélectionnez
restrict 192.168.1.0 netmask 255.255.255.0 nomodify notrap

Image non disponible

  • Activer le service NTP comme suit :

     
    Sélectionnez
    # chkcong ntpd on 
    # service ntpd start
  • Pour vérifier que NTP est bien activé sur le serveur :

     
    Sélectionnez
    service ntpd status
  • Vérifier la synchronisation de notre serveur avec les serveurs mondiaux de notre région : ntpq -p et date -R pour afficher la date courante du système.

Image non disponible

Remarque 1 : la synchronisation se fait de manière automatique chaque 64 s par défaut, mais si toutefois on veut une synchronisation instantanée, il est possible d'envoyer une requête manuellement au pool de serveurs comme suit :

 
Sélectionnez
ntpdate -q 0.africa.pool.ntp 1.africa.pool.ntp.org

4-2-2. Configuration des clients NTP

  • Installer NTP : de la même manière que sur le serveur NTP.
  • Ajouter les load balancers comme serveur NTP dans le fichier de configuration /etc/ntp.conf des serveurs Web pour que ces derniers les considèrent comme leurs masters et se synchronisent avec eux comme suit :

    Image non disponible

  • Activer le service ntpd sur les serveurs Web de la même manière que sur les répartiteurs de charge.

  • Vérifier le bon fonctionnement de la synchronisation de la même manière que sur les serveurs NTP.

5. Déploiement de Ganglia

La mise en place du suivi temps réel de notre Cluster avec Ganglia se fait en suivant les étapes ci-dessous :

5-1. Configuration du nœud maître

Dans notre cas, les nœuds maîtres sont les deux load balancers qui récupéreront les données envoyées par les serveurs Web pour les synthétiser sous forme de graphes et statistiques et auxquels on pourra accéder via l’interface Web offerte par Ganglia et naviguer entre les différents nœuds de notre cluster pour en évaluer les performances, analyser les résultats obtenus, détecter un dysfonctionnement si toutefois il y en a un, etc. La mise en place de Ganglia sur nos deux load balancers se fait de la manière suivante :

  • Installer Ganglia et ses prérequis :

     
    Sélectionnez
    # yum update && yum install epel-release
    # yum install ganglia rrdtool ganglia-gmetad ganglia-gmond ganglia-web
  • Configuration de l’authentification à l’interface Web de Ganglia : pour cela, nous avons utilisé l’authentification de base offerte par Apache. Tout d’abord, on commence par créer un utilisateur avec comme nom d’utilisateur « ganglia » et un mot de passe choisi, ces informations seront stockées dans un fichier de configuration d’Apache /etc/httpd/auth.basic. Voici la commande permettant de créer cet utilisateur :

     
    Sélectionnez
    # htpasswd -c /etc/httpd/auth.basic ganglia
  • Puis on tapera deux fois le mot de passe. On peut vérifier le contenu du fichier d’authentification d’Apache comme suit :

     
    Sélectionnez
    cat /etc/httpd/auth.basic
  • Il faut maintenant modifier le contenu du fichier de configuration /etc/httpd/conf.d/ganglia.conf pour indiquer essentiellement le nom d’utilisateur et le fichier contenant le mot de passe, comme suit :

     
    Sélectionnez
    Alias /ganglia /usr/share/ganglia
    <Location /ganglia>
    AuthType basic
    AuthName "Ganglia web UI"
    AuthBasicProvider #le
    AuthUserFile "/etc/httpd/auth.basic"
    Require user ganglia
    </Location>
  • Configuration des sources de données de Ganglia : pour cela, nous indiquer le nom de notre Grid, qui sera dans ce cas « Cluster » ainsi que le nom de notre Cluster pour que ce dernier puisse être identifié de façon unique, ici ce sera « Servers ». Puis, nous préciserons notre nÅ“ud maître en indiquant son interface accessible de l’extérieur, ici ce sera l’adresse externe de notre load balancer, dans notre cas ce sera 192.168.43.9 pour LVS et 192.168.43.10 pour HAProxy. Enfin, nous indiquerons nos nÅ“uds source de données qui sont nos différents serveurs Web. Cette configuration se fait au niveau du fichier /etc/ganglia/gmetad.conf :

    Image non disponible

  • Configuration du Cluster et des flux d’échanges entre les différents nÅ“uds : pour cela, nous éditons le fichier /etc/ganglia/gmond.conf comme suit : on définit tout d’abord notre Cluster. On configure ensuite l’envoi et la réception via UDP en spécifiant le port d’écoute ici ce sera le port UDP 8649 sur le localhost (où se trouve Ganglia), voici le contenu devant figurer dans le fichier de configuration :

    Image non disponible

  • Autoriser les scripts PHP exécutés par Apache à se connecter au réseau grâce à la commande suivante :

     
    Sélectionnez
    # setsebool -P httpd _can_network_connect 1
  • Changer le port d’écoute d’Apache pour qu’il écoute le port 8080 par exemple au lieu de 80 en remplaçant Listen 80 par Listen 8080 dans /etc/httpd/conf/httpd.conf, car HAProxy et/ou LVS écoutent déjà le port 80.

  • Activer les services gmond, gmetad et apache sur le load balancer :
 
Sélectionnez
# systemctl restart httpd gmetad gmond
# systemctl enable httpd gmetad httpd

5-2. Configuration des nœuds source de données (Serveurs Web)

  • Installer Ganglia gmod sur les serveurs Web. Ceci permettra aux serveurs de transmettre leurs informations au nÅ“ud maître :

     
    Sélectionnez
    # yum update && yum install epel-release
    # yum install ganglia rrdtool ganglia-gmond
  • Configuration de gmond : cela se fait en éditant le fichier de configuration /etc/ganglia/gmond.conf de sorte que la partie Cluster soit identique à celle configurée sur le nÅ“ud maître, les seuls changements se font au niveau de la configuration des échanges UDP, voici le contenu du fichier de configuration après modification :

    Image non disponible

  • Activer le service gmond :
 
Sélectionnez
# service gmond start

6. Déploiement de SSH

  • Installer SSH sur les serveurs Web :

     
    Sélectionnez
    # yum install openssh
  • Activer le service SSH sur les serveurs Web :
 
Sélectionnez
# service sshd start

7. Étude comparative

7-1. Introduction

Dans cette première partie de la troisième phase du projet, nous allons effectuer un ensemble de tests afin d’évaluer la qualité du cluster mis en place selon la nature de l’application à laquelle il est dédié. Puis nous évaluerons chacune des deux solutions de répartition de charge proposée, HAProxy et LVS, et nous effectuerons une étude comparative qui nous permettra de choisir la solution la plus adaptée dans notre cas, celle qui offre le plus de performance et qui répond le mieux aux attentes. Ce document sera structuré de la manière suivante : nous décrirons en premier lieu l’ensemble des tests à effectuer puis nous passerons à l’analyse et interprétation des résultats qui nous permettront d’effectuer une étude comparative entre les deux solutions de LB pour enfin conclure avec le choix de la solution la plus performante.

7-2. Description des tests à effectuer

7-2-1. Tester l’application développée

Effectuer un ensemble de tests afin de vérifier le bon fonctionnement de l’application simulant l’opération BAC en déroulant les cas d’utilisation les plus importants de cette application et montrer que celle-ci répond totalement aux besoins exprimés : authentification avec nom d’utilisateur et mot de passe, redirection vers la page des résultats puis déconnexion de l’utilisateur.

7-2-2. Tester la répartition de charge et évaluer les performances

Trois algorithmes de répartition de charge seront testés sur chacun des serveurs LB : HAProxy et LVS puis, les résultats obtenus avec chaque algorithme seront analysés afin de choisir celui qui est le plus adapté selon les ressources consommées, les performances atteintes, les caractéristiques de notre application, etc. On conclura les tests avec une interprétation des résultats sur lesquels sera basée notre étude algorithmique pour chaque solution de manière indépendante. Enfin, une comparaison entre les résultats obtenus avec l’algorithme retenu sur chaque LB et comparer ensuite les deux solutions obtenues : répartition de charge avec LVS et HAProxy.

Les tests se dérouleront de la manière suivante :

  • Tester en premiers lieux l’algorithme Round Robin sur les deux serveurs : utiliser les résultats obtenus avec RR comme référence (ce dernier étant l’algorithme trivial ou « traditionnel » de répartition de charge faisant en sorte de distribuer les requêtes de façon équitable sur l’ensemble des serveurs, peu importe leur hétérogénéité). Ceci nous permettra de trancher entre les deux autres algorithmes proposés pour chacune des deux solutions : LVS et HAProxy.
  • Tester deux algorithmes choisis sur LVS : les algorithmes choisis sont le Weighted Least-Connection et le Shortest Expected Delay. Le premier a été proposé, car il prend en considération les performances des serveurs grâce aux poids attribués à chaque serveur ce qui nous permettra de répartir les requêtes sur les serveurs selon leur capacité. De plus, ce dernier se trouve être dynamique, c’est-à-dire qu’il ajuste la répartition de charge en temps réel selon l’état actuel du cluster en calculant le nombre de connexions sur chaque serveur puis selon son poids, décide de la manière de répartir les requêtes, le serveur ayant le plus petit rapport nombre de connexions actives sur son poids sera sélectionné. Pour le deuxième algorithme, le choix s’est porté sur celui-ci, car il est dynamique, basé sur les poids assignés aux serveurs ainsi que le délai de réponse calculé selon le rapport (nombre de connexions + 1) / poids du serveur en prenant en considération la nouvelle connexion.
  • Tester deux algorithmes choisis sur HAProxy : les algorithmes choisis pour HAProxy sont Weighted Round Robin et Weighted Least Connections. Le premier fonctionne exactement comme RR sauf qu’il prend les poids attribués aux serveurs en considération, c’est-à-dire qu’il essayera au mieux de répartir la charge de manière équitable sur les différents serveurs selon leur capacité et performance. Le taux de requêtes envoyées à chaque serveur sera donc différent, mais l’efficacité du cluster sera meilleure, car on exploitera au mieux les performances des nÅ“uds. Pour le deuxième algorithme, la justification est exactement la même que pour LVS.
  • À chaque fois, afficher les résultats obtenus sous forme de graphes, courbes, etc. Analyser et interpréter les résultats obtenus pour effectuer le choix de l’algorithme le plus adapté : faire varier le nombre de requêtes simultanées (10 000, 20 000, 30 000, 40 000, 50 000) et utiliser les graphes et statistiques générés par Ganglia afin de récupérer la consommation des ressources (CPU et RAM essentiellement), le nombre de requêtes reçues et le nombre de requêtes traitées, le temps d’exécution des requêtes (temps total, temps moyen, etc.). Utiliser Apache Jmeter pour les tests de performance.
  • Comparer les résultats obtenus avec LVS et les résultats obtenus avec HAProxy.

Remarque : les algorithmes choisis sur chaque LB ont la propriété d’être dynamiques étant donné la nature de notre application, plusieurs utilisateurs à travers le territoire national seront connectés en même temps et enverront un nombre important de requêtes, les serveurs se retrouveront vite saturés si on se contentait seulement de leur attribuer des poids, ces derniers étant des valeurs généralement expérimentales et non exactes, il faut donc un moyen d’adaptation ou réadaptation en temps réel afin de garantir une répartition de charge de qualité.

7-2-3. Health checkup des serveurs Backend

  • Essayer avec un simple algorithme de répartition de charge, RR à priori, qu’effectivement le health checkup fonctionne sur le load balancer HAProxy, et que ce dernier vérifie que les serveurs répondent et que si ce n’est pas le cas, ils transfèreront la requête vers un serveur qui répond.
  • Tester de la même manière le fonctionnement de Keepalive sous LVS.
  • Expliquer ce qui se passe avec l’algorithme de load balancing choisi pour HAProxy : faire un test avec un nombre réduit de requêtes permettant d’anticiper les serveurs devant être choisis et essayer d’éteindre l’un des serveurs et vérifier qu’effectivement, la requête est envoyée au prochain serveur qui répond au critère de l’algorithme choisi.
  • Faire de même avec l’algorithme choisi pour LVS.

7-2-4. Tester la persistance de session

Étant donné la nature de notre application (application PHP), la persistance de session est primordiale. Un client qui se connecte une première fois sur le site pour voir ses résultats sera dirigé vers un serveur donné selon la stratégie de répartition de charge, mais si jamais sa session est perdue (il est par exemple redirigé vers un autre serveur à l’envoi d’une autre requête), l’utilisateur se retrouvera déconnecté et sa session perdue. Une simple actualisation de la page causera cela, il faut donc faire en sorte que les requêtes de cet utilisateur soient toutes envoyées et traitées par le même serveur que celui de sa première connexion et ce, pendant une durée fixée par l’administrateur (Timeout). Pour cela, nous avons utilisé les Sticky Sessions au niveau de HAProxy et la LVS persistence sur LVS. Pour vérifier le bon fonctionnement, nous simulerons l’envoi de plusieurs requêtes à partir de différents clients (différentes sessions) puis nous essayerons d’actualiser par exemple pour voir que chaque utilisateur reste connecté tant que le timeout fixé n’a pas expiré, nous visualiserons ensuite la correspondance entre les serveurs et les utilisateurs.

7-3. Interprétation des résultats obtenus

Dans ce qui suit, nous allons interpréter les résultats des tests effectués sur LVS et HAProxy pour les trois algorithmes choisis. À noter que les poids des serveurs sont les suivants :

  • Serveur 1 : 10
  • Serveur 2 : 10
  • Serveur 3 : 10
  • Serveur 4 : 20
  • Serveur 5 : 30
  • Serveur 6 : 20

7-3-1. LVS

7-3-1-1. Round Robin

Image non disponible

Comme nous pouvons le voir sur le graphe ci-dessus, les requêtes sont distribuées uniformément (et de manière cyclique conformément à l’algorithme Round Robin) sur les différents serveurs.

7-3-1-2. Shortest Expected Delay

Image non disponible

La figure montre que les requêtes ont toutes été dirigées vers le serveur 5, car il a le poids le plus fort et donc c’est celui qui est susceptible de répondre le plus rapidement (en d’autres termes celui qui est susceptible d’avoir le délai le plus court), ceci même en considérant le nombre de connexions actives, car l’envoi et la réception des requêtes se font en un temps réduit.

7-3-1-3. Weighted Least Connection

Image non disponible

On remarque que les serveurs 1, 2 et 3 ont reçu le même nombre de requêtes, de même pour les serveurs 4 et 6 alors que le serveur 5 a reçu un nombre plus élevé de requêtes et ceci est dû au nombre de connexions actives en prenant en considération les poids (attribués relativement aux performances des différents serveurs).

7-3-1-4. Comparaison

Nous constatons que dans le cas de LVS, l’algorithme « Weighted Least Connection » semble être le meilleur, et ceci est visible à travers les graphes ci-dessous.

Image non disponible

Image non disponible

 

Image non disponible

En effet, comme nous pouvons le voir, la latence due à l’ordonnancement des requêtes entrantes est la plus courte pour le WLC, de même pour le nombre de requêtes traitées par seconde. Ceci peut être expliqué par le fait que cet algorithme se base sur deux facteurs qui influent grandement sur les métriques représentées sur le graphe : le poids étant un facteur assez représentatif des performances du serveur, et le nombre de connexions actives étant un paramètre important puisque les utilisateurs affectés à un serveur peuvent être connectés plus longtemps sur celui-ci que les utilisateurs affectés à un autre serveur.

7-3-2. HaProxy

7-3-2-1. Round Robin

Image non disponible

Comme nous pouvons le voir sur le graphe ci-dessus, les requêtes sont distribuées uniformément (et de manière cyclique conformément à l’algorithme Round Robin) sur les différents serveurs.

7-3-2-2. Weighted Round Robin

Image non disponible

Les requêtes sont distribuées de manière cyclique sur les différents serveurs en prenant uniquement en considération les poids affectés. Ainsi, le serveur ayant le poids le plus élevé (Serveur 5 avec le poids 30) a reçu le plus de requêtes, suivi par les serveurs 4 et 6 qui ont un poids de 20 chacun, ensuite les serveurs 1, 2 et 3 qui ont un poids de 10 chacun.

7-3-2-3. Weighted Least Connection

Image non disponible

On remarque que les serveurs 1, 2 et 3 ont reçu le même nombre de requêtes, de même pour les serveurs 4 et 6 alors que le serveur 5 a reçu un nombre plus élevé de requêtes et ceci est dû au nombre de connexions actives en prenant en considération les poids (attribués relativement aux performances des différents serveurs).

7-3-2-4. Comparaison

Comme pour LVS, nous constatons que le meilleur algorithme pour HAProxy est le « Weighted Least Connection ».

Image non disponible

 

Image non disponible

 

Image non disponible

En effet, la latence et le nombre de requêtes par seconde sont plus faibles pour le WLC comparé aux autres algorithmes. Quant à la consommation CPU, la différence est négligeable. La justification est la même : les deux facteurs sur lesquels se base WLC (poids et nombre de connexions actives) influent grandement sur les métriques que l’on a considérées dans notre cas.

7-4. Comparaison entre HAProxy et LVS

La finalité du projet est de comparer entre les deux solutions de Load Balancing que sont LVS et HAProxy dans le contexte de notre application, puis de choisir celle qui répond le mieux aux critères de performance et de haute disponibilité nécessaires à l’opération Bac. Ce choix est fondé non seulement sur les résultats des différents tests effectués sur le cluster, mais aussi sur les points forts et les points faibles de LVS et HAProxy que nous avons pu identifier tout au long du projet. Il convient donc de les citer dans ce qui suit.

7-4-1. LVS

7-4-1-1. Points forts
  • Implantation de LVS sur le noyau, ce qui entraîne un temps de réponse minimal.
  • Nécessite une faible consommation CPU étant donné qu’il se contente de router les paquets sans examiner leur contenu.
  • Installé par défaut sur Linux.
7-4-1-2. Points faibles
  • Absence de health check : nécessité d’installer et de configurer Keepalived.
  • Nécessité de configurer le load balancer comme étant la passerelle par défaut des serveurs backend.
  • Dans le cas de LVS NAT, le load balancer peut constituer un goulot d’étranglement si le nombre de serveurs backend dépasse 20.
  • La mise à jour de LVS peut entraîner la mise à jour du kernel de Linux.

7-4-2. HAProxy

7-4-2-1. Points forts
  • Possibilité de faire un health check au niveau TCP et au niveau applicatif.
  • Diversité des méthodes pour implémenter la persistance : algorithmes d’ordonnancement (Hachage de l’adresse source par exemple), concaténation de l’ID du serveur avec le cookie d’une application (Le session ID d’une application PHP…), insertion d’un autre cookie, etc.
  • Possibilité d’utiliser des ACL.
  • Flexibilité en termes de configuration.
  • Affichage des statistiques sur une interface Web.
  • Fonctionnalité de reverse proxy HTTP.
7-4-2-2. Points faibles
  • Consommation CPU assez élevée (relativement à LVS).
  • Nécessite des dépendances pour l’installation.

7-5. Choix de la meilleure solution

En nous appuyant sur les résultats des tests ainsi que sur les caractéristiques des deux logiciels de load balancing, nous pouvons conclure que la solution la plus adéquate pour l’opération Bac est HAProxy.

Image non disponible

En effet, de par le fait qu’il soit entièrement dédié au trafic HTTP, nous avons constaté qu’il offrait une plus faible latence (et donc un temps de réponse plus faible) comparé à LVS. Ce dernier, bien qu’il ait l’avantage d’être implanté sur le noyau de Linux, dans notre cas cela ne représente pas un point fort puisque les serveurs sont sur des VM, donc il y a une couche additionnelle de virtualisation qui fait qu’on ne peut profiter pleinement de LVS.

Par ailleurs, si l’on considère l’aspect consommation CPU, l’application ne nécessite pas une grande puissance de calcul, donc même si HAProxy demande plus de ressources CPU que LVS, la consommation ne dépasse pas les 20 % ce qui est acceptable.

D’autre part, HAProxy est très flexible et propose un large éventail de fonctionnalités, il permet en outre d’offrir un certain niveau de sécurité grâce au reverse proxying et aux ACL. Il offre également des outils de validation HTTP (permettant de vérifier si les requêtes sont conformes aux standards HTTP) et une protection au niveau applicatif contre les attaques DDoS. Cet aspect, bien que nous ne l’ayons pas détaillé dans le projet, constitue un réel avantage.

  • Par conséquent, dans notre contexte, nous pouvons dire que HAProxy est la solution la plus adaptée.

8. Conclusion

Ce projet a été réalisé par Amina, Manel Aghiles, Mehdi, Mohamed, et moi-même.

8-1. Bibliographie

[1] HAProxy Starter Guide : http://cbonte.github.io/haproxy-dconv/1.9/intro.html.

[2] LVS Documentation : http://www.linuxvirtualserver.org/Documents.html.

[3] LVS Wiki : http://kb.linuxvirtualserver.org/wiki/.

[4] How to install and configure HAProxy on CentOS 6, février 2015 :

https://idroot.net/tutorials/install-configure-haproxy-centos-6/.