[TP] HAProxy et Docker : construire un cluster load balancé de haute disponibilité
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 :Déploiement de 3 serveurs web, d'un serveur Nginx et d'un cluster HAProxy via Docker Compose.
- Lancer l'infrastructure multi-conteneurs
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 :. Mais cela n'est pas indispensable, car nous fournirons pour ce TP toutes les commandes pour ces produits.
- 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
-
Obtention des sources
Vous devez cloner les sources du projet depuis ce REPOhttps://github.com/rousseltm/haproxy-formation.gitdans le dossier de votre choix. -
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 -dAttention : Toutes les commandes
docker composedevront être lancées dans le dossierhaproxy-formation.
Prise en main de la configuration
Ce que vous allez apprendre dans cette section :Exploration de la structure de configuration et mise en place de la modularité.
- 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
-
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. -
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 -
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
Avec une configuration par défaut ou incorrecte, vous pouvez rencontrer des erreurs comme :/var/log/haproxy.logou via la commande
Installation via Docker Compose (notre cas) : Utilisez la commande suivante pour consulter les logs de toutes les instance :journalctl -u haproxy
ou cette commande pour consulter celui d'une instance en particulier (nom conteneur 3: haproxy-formation-haproxy-3)sudo docker compose logsdocker logs <container_name>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 -
L'importance de la modularité
À grande échelle, maintenir un fichier
haproxy.cfgmonolithique 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-fque 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.cfgdans 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 dossierconf.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.cfgde ce dossier, par exempleconfig/haproxy/conf.d/tp.cfg:sudo docker compose down; export HAPROXY_CONFIG=conf.d; sudo -E docker compose up -d -
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 :Configuration des points d'entrée pour les statistiques et le trafic HTTP.
- 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
-
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 blocfrontendou un bloclisten, le résultat sera identique.Comme nous avons basculé vers le chargement du dossier
conf.d, ajoutez cette configuration dans un fichier.cfgde ce dossier. Pour appliquer vos modifications, utilisez la commandeexport HAPROXY_CONFIG=conf.d; sudo -E docker compose restart haproxy(bien faire un reload en Production). -
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é. -
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 :Configuration des serveurs de destination pour traiter les requêtes.
- 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
-
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'. -
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é
- Voir la date de création des conteneurs HAProxy : L'information est dans la colonne 'CREATED'
-
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 adminRecommandation 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 ... -
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 frontendhttp_inpour envoyer le trafic par défaut vers ce backend.
-
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=3pour 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 :Rediriger les requêtes commençant par /api vers le serveur 2.
- Manipuler les ACL
- Configurer un check de niveau 7
- Configurer la recherche de pattern dans la sortie du check
-
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\ '
-
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).
- 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é.
Sécurité et Durcissement
Ce que vous allez apprendre dans cette section :Protection du cluster contre les abus et les attaques réseau.
- 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 contre le DoS et le DDoS
Configurez le frontendhttp_inpour 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 :
Regardez vos logs HAProxy ou le dashboard : les connexions au-delà de 15 doivent être rejetées immédiatement.for i in $(seq 1 20); do curl -s http://localhost & doneDoS 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é.
- 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.
-
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) :
Explication des paramètres :curl -X GET "http://localhost:80/" \ -H "X-Slow: $(head -c 5000 < /dev/zero | tr '\0' 'A')" \ --limit-rate 1 \ --verbose-H "X-Slow: ...": génère un en-tête massif de 5000 octets (viaheadettr) 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.
-
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 :
Vous devez observer des réponsesfor i in $(seq 1 60); do curl -I http://localhost; doneHTTP/1.1 429 Too Many Requestsaprès la 50e requête. -
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/ -
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.-
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. -
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 :
Vous devriez voir défiler les métriques au format texte brut (HELP et TYPE).curl http://localhost:8404/metrics -
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.
Articles recommandés
Apprenez à utiliser HAProxy Topology Visualizer pour transformer vos fichiers...
Découvrez en profondeur l'intégration de HAProxy dans Kubernetes. Architectur...
Découvrez le fonctionnement de la répartition de charge (Load Balancing), son...
Comprendre la structure d'un fichier haproxy.cfg : sections Global, Defaults,...
Guide complet sur les ACLs HAProxy : apprenez à configurer le routage intelli...
Guide complet sur la terminaison SSL, le chiffrement des flux et la sécurisat...
Comment activer le tableau de bord de statistiques natif et exposer des métri...
Comprendre comment garantir qu'un utilisateur reste sur le même serveur backe...
Comment HAProxy détecte les pannes et gère le basculement automatique vers le...
Guide complet pour installer HAProxy sur les serveurs Linux (Debian, RedHat) ...
Comprendre les différences, avantages et interconnexions entre HAProxy OSS, E...
Découvrez les meilleures pratiques pour configurer HAProxy afin d'assurer per...
Un guide pratique regroupant toutes les commandes indispensables pour install...
Découvrez comment utiliser la Runtime API de HAProxy pour créer, configurer e...
Comprendre le protocole ACME, ses avantages et comment configurer le renouvel...
Une exploration complète des directives essentielles de HAProxy : de bind à h...
Glossaire de la formation
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 ...
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...
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...
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...
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 ...
Mécanisme automatisé permettant au load balancer de tester périodiquement la disponibilité des serveurs afin d'exclure temporairement ceux qui sont en...
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...
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.
Mécanisme garantissant qu'un utilisateur est systématiquement redirigé vers le même serveur backend durant toute sa session, indispensable pour les ap...
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...
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...
Protocoles de sécurisation des échanges sur internet. TLS (Transport Layer Security) est le successeur moderne de SSL (Secure Sockets Layer). Ils perm...