[TP] HAProxy et Docker : construire un cluster load balancé de haute disponibilité


Mise en place d'une infrastructure complète avec répartition de charge et monitoring.

Ce que vous allez apprendre dans ce TP :
  • Lancer l'infrastructure multi-conteneurs
  • Localiser et éditer le fichier principal
  • Démarrer une instance HAProxy 3.4 avec une configuration de base
  • Analyser les logs
  • Comprendre les sections de configuration
  • Comprendre l'importance de la modularité
  • Apprendre à gérer l'inclusion de dossiers de configuration
  • Comprendre l'importance de la différence entre reload et restart
  • Configurer un frontend dédié à l'administration
  • Tester l'accessibilité du tableau de bord de statistiques natif de HAProxy
  • Configurer le frontend principal pour le trafic HTTP
  • Configurer un backend par défaut
  • Comprendre la répartition de charge : Round Robin, Least connection, ...
  • Comprendre la notion de poids
  • Comprendre la notion de X-FORWARD-FOR
  • Comprendre la notion de HA
  • Manipuler les ACL
  • Configurer un check de niveau 7
  • Configurer la recherche de pattern dans la sortie du check
  • Limiter les connexions simultanées (Anti-DoS/DDoS)
  • Se protéger contre les attaques lentes (Slowloris)
  • Mettre en place un quota de requêtes (Rate Limiting)
  • Identifier et filtrer les automates (Anti-bot/Scraping)
  • Utiliser la terminaison silencieuse (Silent Drop) pour les flux interdits

Mise en place de l'infrastructure


Ce que vous allez apprendre dans cette section :
  • Lancer l'infrastructure multi-conteneurs

Déploiement de 3 serveurs web, d'un serveur Nginx et d'un cluster HAProxy via Docker Compose.



IMPORTANT : Vous devez lire cet article avant de commencer ce TP pour bien maîtriser les fondamentaux.

Nous vous recommandons aussi de suivre ces formations :
  • Docker : Pour mieux comprendre l'importance de la conteneurisation
  • Prometheus : Pour mieux comprendre la notion de métriques et leurs gestions
  • Opentelemetry : Pour mieux comprendre la notion de métriques et leurs gestions
  • Grafana : Pour mieux comprendre la visualisation des données de télémétrie
. Mais cela n'est pas indispensable, car nous fournirons pour ce TP toutes les commandes pour ces produits.
  1. Obtention des sources
    Vous devez cloner les sources du projet depuis ce REPO https://github.com/rousseltm/haproxy-formation.git dans le dossier de votre choix.
  2. Mise en place de l'infrastructure
    Pour tester nos configurations, on aura besoin d'une infrastructure minimale. Vous devez lancer les commandes suivantes pour la déployer sur Docker :
    cd haproxy-formation 
    sudo docker compose -f compose-infra.yaml up -d
    Attention : Toutes les commandes docker compose devront être lancées dans le dossier haproxy-formation.

Prise en main de la configuration


Ce que vous allez apprendre dans cette section :
  • Localiser et éditer le fichier principal
  • Démarrer une instance HAProxy 3.4 avec une configuration de base
  • Analyser les logs
  • Comprendre les sections de configuration
  • Comprendre l'importance de la modularité
  • Apprendre à gérer l'inclusion de dossiers de configuration
  • Comprendre l'importance de la différence entre reload et restart

Exploration de la structure de configuration et mise en place de la modularité.
  1. Accéder au fichier de base haproxy.cfg
    Le cœur de HAProxy réside dans son fichier de configuration principal : haproxy.cfg. Dans notre environnement Docker, ce fichier est monté en volume.
    Le fichier se situe dans config/haproxy/haproxy.cfg. Vous pouvez l'ouvrir avec votre éditeur de texte habituel pour observer les sections déjà présentes.
  2. Démarrage de l'instance de base
    Pour tester nos configurations, on aura besoin d'une infrastructure HAProxy 3.4 avec une configuration de base que l'on va modifier par la suite. Dans un premier temps, on va tester son fonctionnement avec la configuration de base avec les commandes suivantes :
    sudo docker compose up -d
  3. Vérification du démarrage
    L’objectif est d’apprendre à identifier les erreurs de configuration à travers les logs système et Docker et de vérifier l’absence d’erreurs dans les logs générés par HAProxy.
    Installation sur machine virtuelle ou machine physique : Les logs sont généralement disponibles dans /var/log/haproxy.log ou via la commande
    journalctl -u haproxy
    Installation via Docker Compose (notre cas) : Utilisez la commande suivante pour consulter les logs de toutes les instance :
    sudo docker compose logs 
    ou cette commande pour consulter celui d'une instance en particulier (nom conteneur 3: haproxy-formation-haproxy-3)
     docker logs <container_name>
    Avec une configuration par défaut ou incorrecte, vous pouvez rencontrer des erreurs comme :
    haproxy-1 | [ALERT] (1) : config : parsing [/usr/local/etc/haproxy/haproxy.cfg:71]: Missing LF on last line, file might have been truncated at position 32.
    Vous devez comprendre le message et le corriger
  4. L'importance de la modularité
    À grande échelle, maintenir un fichier haproxy.cfg monolithique devient complexe et risqué. La modularité permet de séparer les responsabilités (ex. : un fichier par application, un pour le monitoring, un pour la sécurité, etc.), facilitant ainsi le déploiement continu, les revues de code et la limitation des erreurs humaines lors des mises à jour.

    Par défaut, le service HAProxy est lancé avec l'option -f haproxy.cfg. Vous pouvez ajouter autant d'options -f que vous avez de fichiers, mais vous pouvez aussi utiliser la même option et passer un dossier en paramètre : HAProxy chargera tous les fichiers se terminant par .cfg dans ce dossier.

    Attention à bien prendre en compte la dépendance entre les modules !


    Dans notre cas, avec notre configuration Docker Compose, utilisez la commande suivante pour basculer vers l'utilisation du dossier conf.d (pensez à déplacer le fichier de conf dans ce dossier), qui se trouve au même niveau que le fichier haproxy.cfg. Les blocs de configuration des exercices suivants devront donc être placés dans un fichier .cfg de ce dossier, par exemple config/haproxy/conf.d/tp.cfg :
    sudo docker compose down; export HAPROXY_CONFIG=conf.d; sudo -E docker compose up -d
  5. Relance de la configuration
    Chaque modification du fichier nécessite une prise en compte par le moteur HAProxy.

    Reload vs Restart : En production, n'utilisez jamais le restart car il coupe les connexions. Le Reload (signal HUP) permet de charger la nouvelle conf sans aucune interruption de service.

Gestion des Frontends


Ce que vous allez apprendre dans cette section :
  • Configurer un frontend dédié à l'administration
  • Tester l'accessibilité du tableau de bord de statistiques natif de HAProxy
  • Configurer le frontend principal pour le trafic HTTP

Configuration des points d'entrée pour les statistiques et le trafic HTTP.
  1. Point d'entrée pour l'administration
    Créez un point d'entrée dédié au monitoring nommé 'admin'. Ce point d'entrée doit écouter sur le port 8404 (port par défaut). Vous devez activer l'interface de statistiques, définir la racine (/) comme URI d'accès et configurer un rafraîchissement automatique toutes les 5 secondes. Notez que vous pouvez réaliser cette configuration avec un bloc frontend ou un bloc listen, le résultat sera identique.
    Comme nous avons basculé vers le chargement du dossier conf.d, ajoutez cette configuration dans un fichier .cfg de ce dossier. Pour appliquer vos modifications, utilisez la commande export HAPROXY_CONFIG=conf.d; sudo -E docker compose restart haproxy (bien faire un reload en Production).
  2. Test de l'accès aux statistiques
    Après avoir configuré le frontend 'admin', vérifiez que l'interface de monitoring est bien opérationnelle. Vous pouvez utiliser votre navigateur ou une commande terminal pour tester l'accessibilité du service sur le port dédié.
  3. Frontend HTTP
    Configurez le frontend principal nommé 'http_in' pour recevoir le trafic web des utilisateurs. Il doit écouter sur le port 80 et rediriger par défaut toutes les requêtes vers le groupe de serveurs 'default' (qui sera créé par la suite).

Gestion des Backends


Ce que vous allez apprendre dans cette section :
  • Configurer un backend par défaut
  • Comprendre la répartition de charge : Round Robin, Least connection, ...
  • Comprendre la notion de poids
  • Comprendre la notion de X-FORWARD-FOR
  • Comprendre la notion de HA

Configuration des serveurs de destination pour traiter les requêtes.
  1. Le Backend par défaut
    Créez un groupe de serveurs nommé 'default'. Ce backend sera utilisé pour traiter les requêtes ne correspondant à aucune règle spécifique. Il doit fonctionner en mode HTTP, utiliser l'algorithme 'roundrobin' et pointer vers le serveur 'web1'. Configurez une règle pour que ce backend serve systématiquement le fichier 'default.html'.
  2. Reload à chaud via fichier de conf
    Ouvrez votre interface de statistiques (port 8404). Vous devriez normalement voir 1 serveur actif dans le backend default. L'objectif est d'ajouter le serveur web2 à ce pool à chaud, c'est-à-dire sans redémarrer le conteneur HAProxy, afin de préserver les connexions en cours. Les étapes :
    • Voir la date de création des conteneurs HAProxy : L'information est dans la colonne 'CREATED'
      sudo docker compose ps haproxy
    • Vous devez éditer le fichier pour ajouter le second serveur et relancer le service :
      sudo docker compose kill -s HUP haproxy
    • Vous devez vérifier dans l'interface que le nouveau serveur est bien présent et que la date de création du serveur n'a pas changé
  3. Reload à chaud via socat
    HAProxy dispose d'une Runtime API accessible via une socket Unix. Elle permet de modifier l'état du load balancer (poids, état des serveurs, ajout dynamique) sans aucun rechargement.
    Pour inspecter l'état interne ou passer des commandes directement dans votre conteneur, connectez-vous au shell via :
    sudo docker exec -it <nom_du_conteneur> sh

    Pour utiliser l'API, vous devez avoir activé la socket dans la section global de la configuration chargée par HAProxy :
    stats socket /tmp/admin.sock mode 600 level admin
    Recommandation de lecture : Pour approfondir la gestion dynamique des backends et des serveurs via la Runtime API, consultez notre article dédié : HAProxy : Ajout et suppression dynamique de backends.
    En ajoutant, vous devez voir le serveur apparaitre dans votre page de stats Mais comme vous avez peu le constater la commande socat est une commande locale donc il faut la jouter sur l'ensemble des instances de votre cluster HAProxy. De plus, comme indiqué dans la documentation, ajouter un serveur ne suffit pas pour qu'il reçoive le trafic, il faut l'activer ...
  4. Le Backend web_servers
    Créez un groupe de serveurs nommé 'web_servers'. Ce backend doit fonctionner en mode HTTP et utiliser l'algorithme de répartition 'least connectioin' avec chaque backend qui a un poids qui correspond à son id de serveur. Vous devez également ajouter une règle pour transmettre l'adresse IP réelle du client au backend via l'en-tête 'X-Real-IP' et déclarer les 3 nœuds applicatifs (web1, web2, web3) sur le port 80 avec une vérification de santé (check). Enfin, mettez à jour le frontend http_in pour envoyer le trafic par défaut vers ce backend.
  5. Scaling de HAProxy
    Le passage à l'échelle horizontal (scaling) consiste à multiplier les instances de HAProxy pour garantir la haute disponibilité (HA). Dans une architecture réelle, avoir une seule instance de load balancer crée un 'Single Point of Failure' (SPOF) : si HAProxy tombe, toute l'application est inaccessible, même si les serveurs web sont sains. En environnement Docker, le scaling permet de répartir la charge réseau et d'assurer une continuité de service lors des mises à jour (rolling updates). Vous devez lancer la commande Docker Compose avec le paramètre --scale haproxy=3 pour faire passer le nombre d'instances HAProxy à 3.

    Note : Multiplier le nombre de nœuds HAProxy ne suffit pas à le mettre en haute disponibilité. Il faut qu'il dispose d'une VIP : dans notre cas, c'est Nginx qui fera le load balancing pour assurer une haute disponibilité complète.

Routage avancé avec ACL


Ce que vous allez apprendre dans cette section :
  • Manipuler les ACL
  • Configurer un check de niveau 7
  • Configurer la recherche de pattern dans la sortie du check

Rediriger les requêtes commençant par /api vers le serveur 2.
  1. Modification ACL
    Le routage intelligent permet de diriger le trafic vers différents backends selon des critères précis. Dans cet exercice, vous devez reconfigurer HAProxy pour qu'il identifie les requêtes destinées à l'API (commençant par le chemin /api) et les envoie exclusivement vers le backend secure_servers qui contient les serveurs du service web mais uniquement de la 2e à la 10e occurence. Le trafic restant doit continuer à être distribué par le backend par défaut.

    Par defaut HAProxy va faire des tests de niveau 4 (TCP - IP:PORT) mais vous devez modifier le backend pour faire un test de vie de niveau 7 (HTTP - page web) qui vérifie que la page 'secure.html' retourne bien la chaîne 'Service\ '
  2. Whitelisting des IP
    Le filtrage par adresse IP est un pilier de la sécurité. Vous devez maintenant restreindre l'accès au dashboard de statistiques (port 8404) pour n'autoriser que les sources internes qui ont besoin de lire l'interface ou l'endpoint /metrics, par exemple le serveur Prometheus et le serveur Nginx d'administration.
    IMPORTANT : Veillez à bien comprendre le schéma d'architecture pour vous assurer que vos règles de routage permettent toujours l'accès à la console de statistiques et à l'endpoint /metrics.


    Whitelisting vs Blacklisting :

    HAProxy est compatible avec les deux approches via ses règles d'ACL.

    • Whitelisting (liste blanche) : Stratégie 'Default Deny'. On bloque tout par défaut et on n'autorise que les sources connues. C'est l'approche la plus robuste pour la sécurité.
      Cas d'usage : accès à une console d'administration, API interne réservée à des partenaires, restriction d'accès aux IP d'un VPN d'entreprise.
    • Blacklisting (liste noire) : Stratégie 'Default Allow'. On laisse passer tout le trafic sauf les IP identifiées comme malveillantes.
      Cas d'usage : blocage de bots connus (scrapers), protection temporaire contre une IP réalisant une attaque par force brute, ou Geo-blocking (blocage de régions entières).

Sécurité et Durcissement


Ce que vous allez apprendre dans cette section :
  • Limiter les connexions simultanées (Anti-DoS/DDoS)
  • Se protéger contre les attaques lentes (Slowloris)
  • Mettre en place un quota de requêtes (Rate Limiting)
  • Identifier et filtrer les automates (Anti-bot/Scraping)
  • Utiliser la terminaison silencieuse (Silent Drop) pour les flux interdits

Protection du cluster contre les abus et les attaques réseau.
  1. Protection contre le DoS et le DDoS
    Configurez le frontend http_in pour limiter chaque IP source à un maximum de 15 connexions TCP simultanées (couche 4). Une fois la configuration appliquée, tentez d'ouvrir plusieurs connexions en parallèle pour vérifier que HAProxy rejette les suivantes.
    Vérification : Simulez une charge avec une boucle shell pour ouvrir de nombreuses connexions en arrière-plan :
    for i in $(seq 1 20); do curl -s http://localhost & done
    Regardez vos logs HAProxy ou le dashboard : les connexions au-delà de 15 doivent être rejetées immédiatement.
    DoS vs DDoS : quelle différence ?
    • DoS (Denial of Service) : l'attaque provient d'une seule machine. HAProxy peut facilement la bloquer en limitant les connexions par IP.
    • DDoS (Distributed DoS) : l'attaque provient de milliers de sources (botnet). Bloquer une IP ne suffit plus, car le trafic est distribué.
    Recommandations de HAProxy (Lire l'article officiel) :
    • Défense en profondeur : pour les attaques volumétriques massives (couches 3 et 4), utilisez des services de protection Cloud (Cloudflare, AWS Shield) en amont.
    • Filtrage couche 7 : utilisez HAProxy pour identifier des signatures d'attaque spécifiques dans les en-têtes ou les URL via les ACL.
    • Stick Tables : elles restent essentielles pour limiter l'impact de chaque nœud du botnet sur vos ressources applicatives.
  2. Protection contre le Slowloris
    L'attaque Slowloris sature le serveur en envoyant des en-têtes HTTP très lentement. Implémentez une protection en limitant le temps de réception des en-têtes à 5 secondes.
    Simulation d'attaque : Lancez cette commande avant la configuration (la connexion restera bloquée), puis après (HAProxy coupera la connexion après 5 s) :
    curl -X GET "http://localhost:80/" \
         -H "X-Slow: $(head -c 5000 < /dev/zero | tr '\0' 'A')" \
         --limit-rate 1 \
         --verbose
    Explication des paramètres :
    • -H "X-Slow: ..." : génère un en-tête massif de 5000 octets (via head et tr) pour forcer un envoi long.
    • --limit-rate 1 : bride l'envoi à 1 octet/s. Sans protection, la connexion resterait ouverte plus d'une heure.
    • --verbose : permet d'observer en direct le moment exact où HAProxy interrompt la session.
    Recommandations de HAProxy (Lire l'article officiel) : Pour une protection optimale, HAProxy préconise de combiner plusieurs réglages :
    • timeout http-request 5s : limite le temps d'attente des en-têtes (défense principale).
    • timeout http-keep-alive 1s : libère rapidement les slots de connexion inactifs.
    • maxconn : limite le nombre global de connexions pour protéger les descripteurs de fichiers du système contre l'épuisement.
  3. Limiter les requêtes (Rate Limiting)
    Mettez en place un quota de 50 requêtes maximum toutes les 10 secondes par IP. Testez le dépassement du seuil et vérifiez que HAProxy retourne bien un code d'erreur HTTP 429.
    Vérification : Exécutez une rafale de requêtes curl pour saturer le quota :
    for i in $(seq 1 60); do curl -I http://localhost; done
    Vous devez observer des réponses HTTP/1.1 429 Too Many Requests après la 50e requête.
  4. Modules Anti-bot et Détection du scraping
    Bloquez les aspirateurs de données (scrapers) et les bots malveillants en identifiant leurs signatures User-Agent suspectes.
    Simulation de bot : Tentez d'accéder au site en simulant un bot connu via curl :
    curl -I -H "User-Agent: Googlebot-Scraper" http://localhost/
  5. Terminaison silencieuse de requête
    Le 'Silent Drop' est une technique de défense avancée : au lieu d'envoyer un code d'erreur (403/429) qui confirme au pirate l'existence d'une protection, HAProxy ignore simplement la requête. L'attaquant gaspille ses ressources à attendre une réponse qui ne viendra jamais.
    Vérification : Testez l'accès à un chemin interdit et constatez que curl reste en attente (hang) jusqu'au timeout :
    curl -v http://localhost/admin/config

Observabilité

Mise en place du monitoring, de l'exposition des métriques et de la télémétrie.
  1. Stats Dashboard
    Vérifiez que le point d'entrée d'administration configuré plus tôt expose toujours le dashboard de statistiques sur la racine du port 8404.
  2. Prometheus : Exposition des métriques
    Configurez HAProxy pour exposer les métriques de performance au format Prometheus sur l'URI /metrics. Cela permet à un serveur Prometheus de scraper l'état du load balancer.
    Vérification : Testez la récupération des métriques via curl :
    curl http://localhost:8404/metrics
    Vous devriez voir défiler les métriques au format texte brut (HELP et TYPE).
  3. Prise en charge d'OpenTelemetry (OTel)
    Configurez l'exportation native de données de télémétrie vers un collecteur OpenTelemetry.
    Note : La prise en charge native d'OpenTelemetry est disponible à partir de la version 3.4 de HAProxy.

Niveau de difficulté: (3/5)

Articles recommandés

Visualiser votre infrastructure avec HAProxy Topology Visualizer

Apprenez à utiliser HAProxy Topology Visualizer pour transformer vos fichiers...

HAProxy dans Kubernetes : L'Ingress Controller Haute Performance

Découvrez en profondeur l'intégration de HAProxy dans Kubernetes. Architectur...

Le Load Balancing : Principes, Algorithmes et Cas d'usage

Découvrez le fonctionnement de la répartition de charge (Load Balancing), son...

Anatomie de la configuration HAProxy

Comprendre la structure d'un fichier haproxy.cfg : sections Global, Defaults,...

Maîtriser les ACLs dans HAProxy

Guide complet sur les ACLs HAProxy : apprenez à configurer le routage intelli...

Sécurité et SSL avec HAProxy

Guide complet sur la terminaison SSL, le chiffrement des flux et la sécurisat...

Monitoring et Statistiques dans HAProxy

Comment activer le tableau de bord de statistiques natif et exposer des métri...

Persistance de session (Stickiness)

Comprendre comment garantir qu'un utilisateur reste sur le même serveur backe...

Health Checks et Haute Disponibilité

Comment HAProxy détecte les pannes et gère le basculement automatique vers le...

Installation de HAProxy

Guide complet pour installer HAProxy sur les serveurs Linux (Debian, RedHat) ...

L'écosystème HAProxy : De l'Open Source à HAProxy One

Comprendre les différences, avantages et interconnexions entre HAProxy OSS, E...

Bonnes Pratiques HAProxy : Optimisation, Sécurité et Haute Disponibilité

Découvrez les meilleures pratiques pour configurer HAProxy afin d'assurer per...

Aide-mémoire HAProxy : Les commandes essentielles

Un guide pratique regroupant toutes les commandes indispensables pour install...

HAProxy : Ajout et suppression dynamique de backends

Découvrez comment utiliser la Runtime API de HAProxy pour créer, configurer e...

ACME : Le guide du déploiement SSL/TLS automatisé

Comprendre le protocole ACME, ses avantages et comment configurer le renouvel...

HAProxy : Guide détaillé des directives de configuration

Une exploration complète des directives essentielles de HAProxy : de bind à h...

Glossaire de la formation

ACL (Access Control List)

Liste de contrôle d'accès définissant les permissions accordées sur des ressources. Dans HAProxy, les ACL sont des conditions flexibles permettant de ...

Backend

Section de la configuration HAProxy définissant un pool de serveurs cibles vers lesquels le trafic est redirigé. C'est ici que l'on configure l'algori...

Frontend

Section de la configuration HAProxy qui définit comment les requêtes sont reçues du côté client (adresse IP, port, certificats SSL) avant d'être envoy...

GSLB (Global Server Load Balancing)

Technique de répartition de charge à l'échelle mondiale, utilisant généralement le DNS pour diriger les utilisateurs vers le datacenter le plus proche...

HAProxy

Logiciel de load balancing et de proxying haute performance pour TCP et HTTP. HAProxy est le standard de l'industrie pour la gestion de trafic à très ...

Health Check

Mécanisme automatisé permettant au load balancer de tester périodiquement la disponibilité des serveurs afin d'exclure temporairement ceux qui sont en...

Load Balancing

Dispositif qui distribue le trafic applicatif sur un ensemble de serveurs afin d'optimiser l'usage des ressources, de minimiser les temps de réponse e...

SSL Offloading

Processus consistant à déléguer le déchiffrement du trafic HTTPS au load balancer pour libérer de la puissance CPU sur les serveurs d'application.

Stickiness

Mécanisme garantissant qu'un utilisateur est systématiquement redirigé vers le même serveur backend durant toute sa session, indispensable pour les ap...

Slowloris

Type d'attaque par déni de service (DoS) qui consiste à ouvrir de nombreuses connexions HTTP et à les maintenir ouvertes le plus longtemps possible en...

DoS / DDoS

Attaque visant à rendre un service indisponible en submergeant le serveur ou le réseau de trafic. On parle de DDoS (Distributed Denial of Service) lor...

SSL / TLS

Protocoles de sécurisation des échanges sur internet. TLS (Transport Layer Security) est le successeur moderne de SSL (Secure Sockets Layer). Ils perm...