Clusters Linux : haute disponibilité de A à Z
HAProxy, Keepalived/VRRP, Pacemaker, Corosync, Galera Cluster, NFS partagé : construisez une infrastructure zéro downtime avec des outils open source éprouvés.
Un cluster est un ensemble de serveurs qui travaillent ensemble pour former un système unique plus fiable, plus performant ou plus puissant. En infrastructure Linux, on distingue trois grandes familles : les clusters de haute disponibilité (HA) qui éliminent les points de défaillance uniques, les clusters de répartition de charge (Load Balancing) qui distribuent le trafic, et les clusters HPC (High Performance Computing) pour le calcul intensif. Ce guide couvre les architectures, outils et configurations concrets pour les deux premiers types.
Concepts fondamentaux
Pourquoi un cluster ?
L'objectif est simple : si un serveur tombe, le service continue. Les métriques clés sont :
- Disponibilité (Availability) : exprimée en pourcentage du temps d'uptime (99.9% = 8h d'indispo/an, 99.99% = 52 min/an, 99.999% = 5 min/an)
- RTO (Recovery Time Objective) : temps maximum acceptable pour restaurer le service après une panne
- RPO (Recovery Point Objective) : perte de données maximale acceptable (en temps)
- SPOF (Single Point of Failure) : composant dont la panne provoque l'arrêt complet du service
Types de clustering
- Active/Passive (HA) : un nœud actif + un nœud en veille. Failover automatique en cas de panne. Ressources doublées mais non utilisées.
- Active/Active (Load Balancing) : tous les nœuds traitent du trafic simultanément. Meilleure utilisation des ressources.
- N+1 : N nœuds actifs + 1 de secours. Compromis entre coût et disponibilité.
- HPC (High Performance Computing) : calcul distribué sur des dizaines ou milliers de nœuds (Slurm, PBS, OpenMPI).
Un cluster n'est pas une solution de sauvegarde. Si une corruption de données se propage sur tous les nœuds, votre cluster 'hautement disponible' est entièrement corrompu. Cluster ≠ backup.
Architecture typique d'un cluster HA web
# Architecture 3 nœuds : Load Balancer + 2 serveurs web
#
# Internet
# │
# ▼
# ┌──────────────────┐
# │ Load Balancer │ ← HAProxy (actif)
# │ IP: 10.0.0.1 │ +
# │ VIP: 10.0.0.100 │ ← Keepalived (IP virtuelle)
# └────────┬─────────┘
# │
# ┌──────┴──────┐
# ▼ ▼
# ┌──────┐ ┌──────┐
# │ Web1 │ │ Web2 │ ← Serveurs Apache/Nginx
# │10.0.0.2│ │10.0.0.3│ ← Partagent le même storage
# └──────┘ └──────┘
# │
# ┌───┴───┐
# │ DB │ ← MariaDB (ou Galera Cluster)
# │10.0.0.4│
# └───────┘HAProxy — Load Balancer de référence
HAProxy (High Availability Proxy) est le standard de facto pour la répartition de charge HTTP/TCP. Il est utilisé par GitHub, Twitter, Airbnb et des milliers d'autres entreprises.
Installation
apt install -y haproxy
# Version
haproxy -v
# HAProxy version 2.x
# Activer le démarrage auto
systemctl enable haproxyConfiguration haproxy.cfg
La configuration HAProxy est divisée en sections : global (paramètres du processus), defaults, frontend (accepte le trafic), backend (groupe de serveurs) et listen (raccourci frontend+backend).
# Sauvegarder la config par défaut
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
nano /etc/haproxy/haproxy.cfg#---------------------------------------------------------------------
# Section GLOBAL — paramètres du processus HAProxy
#---------------------------------------------------------------------
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# SSL/TLS : Performances et sécurité
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
tune.ssl.default-dh-param 2048
#---------------------------------------------------------------------
# Section DEFAULTS — valeurs par défaut héritées par toutes les sections
#---------------------------------------------------------------------
defaults
log global
mode http # Mode HTTP (ou tcp pour non-HTTP)
option httplog
option dontlognull # Ne pas logger les connexions sans requête
option http-server-close
option forwardfor except 127.0.0.0/8 # Transmettre la vraie IP client
option redispatch # Réessayer sur un autre serveur si connexion échoue
retries 3
timeout connect 5s
timeout client 50s
timeout server 50s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 503 /etc/haproxy/errors/503.http
#---------------------------------------------------------------------
# Section FRONTEND — point d'entrée du trafic
#---------------------------------------------------------------------
frontend http_in
bind *:80
default_backend web_servers
# Redirection HTTP → HTTPS
redirect scheme https code 301 if !{ ssl_fc }
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/monsite.com.pem alpn h2,http/1.1
default_backend web_servers
# ACL pour router selon le sous-domaine
acl is_api hdr(host) -i api.monsite.com
acl is_app hdr(host) -i app.monsite.com
use_backend api_servers if is_api
use_backend app_servers if is_app
default_backend web_servers
# Headers de sécurité
http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
http-response set-header X-Frame-Options "DENY"
#---------------------------------------------------------------------
# Section BACKEND — groupe de serveurs web
#---------------------------------------------------------------------
backend web_servers
balance roundrobin # Algorithme : round-robin, leastconn, source (sticky)
option httpchk GET /health # Health check HTTP (doit retourner 200)
http-check expect status 200
# Cookies de session sticky (même client → même serveur)
cookie SERVERID insert indirect nocache
server web1 10.0.0.2:80 check inter 2s fall 3 rise 2 weight 1 cookie web1
server web2 10.0.0.3:80 check inter 2s fall 3 rise 2 weight 1 cookie web2
# check : activer le health check
# inter 2s : vérifier toutes les 2 secondes
# fall 3 : considérer comme down après 3 échecs
# rise 2 : considérer comme up après 2 succès
backend api_servers
balance leastconn # Connexion la moins chargée (bon pour API)
option httpchk GET /api/health
server api1 10.0.0.5:8080 check
server api2 10.0.0.6:8080 check
#---------------------------------------------------------------------
# Interface de statistiques HAProxy
#---------------------------------------------------------------------
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
stats auth admin:MotDePasseStats
stats hide-version# Vérifier la syntaxe
haproxy -c -f /etc/haproxy/haproxy.cfg
# Démarrer/recharger
systemctl restart haproxy
systemctl reload haproxy # Rechargement sans coupure (graceful)
# Surveiller en temps réel (socket d'administration)
echo "show info" | socat stdio /run/haproxy/admin.sock
echo "show stat" | socat stdio /run/haproxy/admin.sock | column -t -s ','
# Désactiver temporairement un serveur (maintenance)
echo "disable server web_servers/web1" | socat stdio /run/haproxy/admin.sock
# Réactiver
echo "enable server web_servers/web1" | socat stdio /run/haproxy/admin.sockKeepalived — IP virtuelle flottante (VIP)
Keepalived implémente le protocole VRRP (Virtual Router Redundancy Protocol). Il permet à plusieurs serveurs de partager une IP virtuelle (VIP) — si le serveur MASTER tombe, le BACKUP prend la VIP en quelques secondes.
# Sur les DEUX serveurs load balancer
apt install -y keepalived
# Activer le forwarding IP (nécessaire pour VRRP)
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -pConfiguration du nœud MASTER
# /etc/keepalived/keepalived.conf (MASTER — LB1)
cat > /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
router_id LB1 # Identifiant unique du routeur
script_user root
enable_script_security
}
# Script de vérification de santé HAProxy
vrrp_script check_haproxy {
script "killall -0 haproxy" # Retourne 0 si HAProxy tourne
interval 2 # Vérifier toutes les 2 secondes
weight -20 # Si échoue : baisser la priorité de 20
fall 2 # Nombre d'échecs avant de décrémenter
rise 2 # Nombre de succès pour remonter
}
vrrp_instance VI_1 {
state MASTER # Ce nœud est MASTER au démarrage
interface eth0 # Interface réseau de la VIP
virtual_router_id 51 # Doit être identique sur MASTER et BACKUP (1-255)
priority 100 # Priorité MASTER > BACKUP (100 > 90)
advert_int 1 # Intervalle d'annonce VRRP (secondes)
authentication {
auth_type PASS
auth_pass Sup3rS3cret! # Mot de passe partagé MASTER/BACKUP
}
virtual_ipaddress {
10.0.0.100/24 dev eth0 # L'IP virtuelle flottante
}
track_script {
check_haproxy # Lier la priorité à l'état de HAProxy
}
}
EOFConfiguration du nœud BACKUP
# /etc/keepalived/keepalived.conf (BACKUP — LB2)
cat > /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
router_id LB2
script_user root
enable_script_security
}
vrrp_script check_haproxy {
script "killall -0 haproxy"
interval 2
weight -20
fall 2
rise 2
}
vrrp_instance VI_1 {
state BACKUP # Ce nœud est BACKUP au démarrage
interface eth0
virtual_router_id 51 # Identique au MASTER
priority 90 # Priorité inférieure au MASTER
advert_int 1
authentication {
auth_type PASS
auth_pass Sup3rS3cret! # Identique au MASTER
}
virtual_ipaddress {
10.0.0.100/24 dev eth0 # Même VIP que le MASTER
}
track_script {
check_haproxy
}
}
EOF# Démarrer Keepalived sur les deux nœuds
systemctl enable keepalived
systemctl start keepalived
# Vérifier l'état et quel nœud a la VIP
ip addr show eth0 | grep "10.0.0.100" # Doit apparaître sur le MASTER uniquement
# Surveiller les logs VRRP
journalctl -u keepalived -f
# Simuler une panne (arrêter HAProxy sur le MASTER)
systemctl stop haproxy
# → Keepalived détecte l'échec du script → réduit la priorité sous 90 → BACKUP prend la VIP
# Observer le basculement sur le BACKUP
# ip addr show eth0 | grep "10.0.0.100" # Apparaît maintenant sur LB2Pacemaker + Corosync — Cluster manager avancé
Pour des clusters plus complexes (bases de données, NFS, services avec état), Pacemaker (gestionnaire de ressources) + Corosync (communication inter-nœuds) forment la stack HA de référence sous Linux.
# Sur tous les nœuds du cluster
apt install -y pacemaker corosync pcs fence-agents
# Définir un mot de passe pour l'utilisateur hacluster (identique sur tous les nœuds)
passwd hacluster
# Nouveau mot de passe: ••••••••
systemctl enable pacemaker corosync
systemctl start pcsd # Service PCS (interface de gestion)
# Depuis le nœud 1 : authentifier les nœuds entre eux
pcs host auth node1.local node2.local -u hacluster -p MotDePasseHaCluster
# Créer le cluster
pcs cluster setup MONCLUSTER node1.local node2.local
# Démarrer le cluster sur tous les nœuds
pcs cluster start --all
pcs cluster enable --all# Vérifier l'état du cluster
pcs status
# Cluster name: MONCLUSTER
# Cluster Summary:
# * Stack: corosync
# * Current DC: node1.local (version ...) - partition with quorum
# * 2 nodes configured
# * 0 resource instances configured
#
# Node List:
# * Online: [ node1.local node2.local ]
# Désactiver le STONITH en lab (PAS en production !)
pcs property set stonith-enabled=false
# Désactiver le quorum policy en cluster 2 nœuds
pcs property set no-quorum-policy=ignoreAjouter des ressources au cluster
# Ressource VIP (IP virtuelle)
pcs resource create VirtualIP IPaddr2 ip=10.0.0.100 cidr_netmask=24 nic=eth0 op monitor interval=30s
# Ressource Apache
pcs resource create ApacheHTTP apache configfile=/etc/apache2/apache2.conf statusurl="http://127.0.0.1/server-status" op monitor interval=20s
# Contrainte : VirtualIP doit tourner sur le même nœud qu'Apache
pcs constraint colocation add ApacheHTTP with VirtualIP INFINITY
# Contrainte : VirtualIP doit démarrer avant Apache
pcs constraint order VirtualIP then ApacheHTTP
# Vérifier les ressources
pcs status resources
# * VirtualIP (ocf::heartbeat:IPaddr2): Started node1.local
# * ApacheHTTP (ocf::heartbeat:apache): Started node1.localSTONITH (Shoot The Other Node In The Head) est crucial en production. Sans lui, si un nœud perd la communication réseau mais continue à fonctionner, les deux nœuds peuvent réclamer la VIP simultanément — c'est le 'split-brain', qui cause des corruptions de données. Configurez toujours un agent STONITH (IPMI, iLO, iDRAC, fence_aws, fence_gce) en production.
Galera Cluster — Base de données en cluster
Galera est un cluster de réplication synchrone multi-maître pour MariaDB/MySQL. Tous les nœuds acceptent des lectures ET des écritures. Un commit n'est validé que quand tous les nœuds l'ont accepté.
# Sur tous les nœuds (Debian/Ubuntu)
apt install -y mariadb-server galera-4
# Configuration identique sur tous les nœuds (/etc/mysql/mariadb.conf.d/60-galera.cnf)
cat > /etc/mysql/mariadb.conf.d/60-galera.cnf << 'EOF'
[galera]
wsrep_on = ON
wsrep_provider = /usr/lib/galera/libgalera_smm.so
wsrep_cluster_name = "GaleraCluster"
wsrep_cluster_address = "gcomm://10.0.0.10,10.0.0.11,10.0.0.12"
wsrep_node_address = "10.0.0.10" # IP de CE nœud (différent sur chaque nœud)
wsrep_node_name = "db1" # Nom unique de ce nœud
# Méthode de transfert d'état initial (IST/SST)
wsrep_sst_method = rsync
# Synchronisation binlog
binlog_format = ROW
default_storage_engine = InnoDB
innodb_autoinc_lock_mode = 2
innodb_flush_log_at_trx_commit = 0
# Performance
wsrep_slave_threads = 4
wsrep_max_ws_size = 2G
EOF
# Démarrage du PREMIER nœud (bootstrap)
galera_new_cluster
# Vérifier l'état du cluster Galera
mysql -e "SHOW STATUS LIKE 'wsrep%';" | grep -E "wsrep_cluster_size|wsrep_connected|wsrep_ready"
# wsrep_cluster_size : 1 (d'abord), puis 2, puis 3 au démarrage des autres nœuds
# wsrep_connected : ON
# wsrep_ready : ON
# Sur les autres nœuds (pas de galera_new_cluster, juste start)
systemctl start mariadbStockage partagé avec NFS
Dans un cluster de serveurs web, tous les nœuds doivent accéder aux mêmes fichiers (code source, médias uploadés). NFS est la solution classique pour partager ce stockage.
# ── Sur le serveur NFS ──
apt install -y nfs-kernel-server
mkdir -p /srv/nfs/webapp
chown www-data:www-data /srv/nfs/webapp
# Configurer les exports NFS
cat >> /etc/exports << 'EOF'
/srv/nfs/webapp 10.0.0.0/24(rw,sync,no_subtree_check,no_root_squash)
EOF
exportfs -ra
systemctl restart nfs-kernel-server
# Vérifier les exports
showmount -e localhost
# ── Sur chaque nœud web ──
apt install -y nfs-common
# Montage temporaire
mount -t nfs 10.0.0.20:/srv/nfs/webapp /var/www/html
# Montage permanent dans /etc/fstab
echo "10.0.0.20:/srv/nfs/webapp /var/www/html nfs rw,sync,hard,intr,rsize=8192,wsize=8192,_netdev 0 0" >> /etc/fstab
mount -aSurveiller l'état du cluster
# ── Pacemaker ──
pcs status # État général
pcs status resources # État des ressources
pcs status nodes # État des nœuds
crm_mon -1 # Snapshot (alternatif)
crm_mon -r # Mise à jour continue
# ── Corosync ──
corosync-cfgtool -s # Anneaux de communication
corosync-quorumtool # État du quorum
# ── HAProxy ──
# Interface web : http://10.0.0.1:8404/stats
# En ligne de commande
watch -n1 'echo "show stat" | socat stdio /run/haproxy/admin.sock | cut -d, -f1,2,18,19,48'
# ── Galera ──
mysql -e "SHOW STATUS LIKE 'wsrep_cluster_size';"
mysql -e "SHOW STATUS LIKE 'wsrep_local_state_comment';"
# wsrep_local_state_comment : Synced = tout va bien
# wsrep_cluster_size : doit être le nombre de nœuds attendusTester la résilience (chaos testing)
Ne découvrez jamais une panne pour la première fois en production. Testez régulièrement vos failovers en environnement de staging.
# ── Test 1 : Panne du nœud actif HAProxy/Keepalived ──
# Sur LB1 (MASTER) :
systemctl stop haproxy
# Observation : LB2 doit prendre la VIP en <3 secondes
# Vérification : ip addr show eth0 sur LB2 doit montrer 10.0.0.100
# Trafic : curl -I http://10.0.0.100 doit continuer à répondre
# ── Test 2 : Panne d'un serveur web backend ──
# Sur web1 :
systemctl stop apache2
# HAProxy détecte l'échec du health check en ~6s (3 × inter 2s)
# Tout le trafic bascule sur web2
# curl -k https://10.0.0.100 doit continuer à répondre
# Vérification dans les stats HAProxy : web1 apparaît DOWN (rouge)
# ── Test 3 : Panne d'un nœud Galera ──
# Sur db2 :
systemctl stop mariadb
# Galera : cluster_size passe de 3 à 2
# Les requêtes continuent sur db1 et db3
# Au redémarrage de db2, il resynchronise automatiquement (IST ou SST)
systemctl start mariadb
mysql -e "SHOW STATUS LIKE 'wsrep_local_state_comment';" # → Synced
# ── Test 4 : Network partition (simuler un split-brain) ──
# Sur node1 :
iptables -I INPUT -s 10.0.0.11 -j DROP
iptables -I OUTPUT -d 10.0.0.11 -j DROP
# Le cluster doit rester actif sur le nœud avec le quorum
# STONITH doit shooter l'autre nœud (si configuré)
# Cleanup :
iptables -D INPUT -s 10.0.0.11 -j DROP
iptables -D OUTPUT -d 10.0.0.11 -j DROPChecklist de mise en production
- 1Synchronisation NTP sur tous les nœuds (chrony ou timesyncd) — essentiel pour Galera et Corosync
- 2Firewall : ports Corosync (UDP 5404-5405), Galera (4444, 4567, 4568), HAProxy stats, NFS ouverts entre nœuds
- 3STONITH configuré et testé — jamais de cluster HA en production sans fencing
- 4Monitoring des ressources cluster (Prometheus + blackbox_exporter, Grafana)
- 5Alerting sur : nœud DOWN, cluster_size < expected, quorum perdu
- 6Procédure de failover documentée et testée par l'équipe
- 7Plan de reprise : que faire si tous les nœuds tombent simultanément ?
- 8Tests chaos réguliers en staging (au moins trimestriels)
- 9Sauvegardes indépendantes du cluster (le cluster n'est PAS un backup)
Pour les clusters Kubernetes (K8s), les concepts sont similaires mais l'outillage change : etcd remplace Corosync pour le consensus, le scheduler K8s remplace Pacemaker pour la gestion des ressources, et les PersistentVolumes remplacent le NFS partagé. La courbe d'apprentissage est plus raide mais la flexibilité bien supérieure pour les microservices.
Sources & références
- 1HAProxy Documentation
Documentation complète de référence HAProxy 2.8
- 2Keepalived User Guide
Documentation officielle Keepalived avec exemples VRRP
- 3Pacemaker Documentation — ClusterLabs
Guide officiel Pacemaker : configuration, ressources, STONITH
- 4Galera Cluster for MySQL — Documentation
Documentation complète Galera : architecture, SST, IST, tuning
- 5Linux-HA Project
Projet fondateur du clustering HA sous Linux
Testez vos configurations
Xytherion Tools propose des outils gratuits pour vérifier vos DNS, auditer votre SSL, tester SPF/DKIM/DMARC et bien plus — directement depuis votre navigateur.