Haute disponibilité et équilibrage de charge avec ClusterHAT
L'idée est d'utiliser le ClusterHAT qui pilote plusieurs Pi Zero pour implémenter le "load balancing", en français "l'équilibrage de charge".
De quoi s'agit-il ?
En fonction du nombre de visiteurs, il se peut que le serveur Web soit occupé au moment où une nouvelle requête HTTP arrive. Surtout si celle-ci déclenche l'exécution d'une action PHP.
Ce qui caractérise les sites Web, c'est qu'on ne peut maîtriser a priori le nombre de visiteurs. De fait, exposé sur Internet et visible dans le monde entier, potentiellement un site Web peut être consulté par 6 milliards de visiteurs.
L'équilibrage de charge consiste à multiplier les serveurs Web pour un même site et faire en sorte qu'il y ait toujours un serveur prêt pour répondre aux requêtes entrantes. En revanche, tous les serveurs doivent partager les mêmes fichiers pour qu'il n'ait pas de différence dans les réponses selon le serveur Web qui répond.
Ce qui caractérise les sites Web, c'est qu'on ne peut maîtriser a priori le nombre de visiteurs. De fait, exposé sur Internet et visible dans le monde entier, potentiellement un site Web peut être consulté par 6 milliards de visiteurs.
L'équilibrage de charge consiste à multiplier les serveurs Web pour un même site et faire en sorte qu'il y ait toujours un serveur prêt pour répondre aux requêtes entrantes. En revanche, tous les serveurs doivent partager les mêmes fichiers pour qu'il n'ait pas de différence dans les réponses selon le serveur Web qui répond.
Pré-requis
- Le contrôleur du cluster (le Raspberry Pi 3) doit être installé avec un serveur NFS et le répertoire /var/www/pub doit être exposé en NFS. C'est ce répertoire qui contient les fichiers des sites Web qui seront utilisés par les serveurs Web des Pi Zero. Consulter les articles "Partager un dossier par NFS" et "Monter un dossier distant par NFS".
Cette technique est décrite dans l'article intitulé "Partager un dossier par NFS". - Chaque Pi Zero doit être installé avec un serveur Apache2 et PHP 7.0 opérationnel. Consulter les articles "Créer un serveur Web" et "Créer un serveur PHP 7.0".
- - juin 02, 2018
- Le répertoire /var/www/pub du contrôleur doit être monté, via NFS, sur le répertoire /var/www/html configuré dans Apache2 de chaque Pi Zero. Comme cela tous les Pi Zero utilisent les mêmes fichiers html, php, etc.
Cette technique est décrite dans l'article intitulé "Monter un dossier distant par NFS".
Installation d'un proxy
Pour implémenter l'équilibrage de charge, il est nécessaire de disposer d'un proxy. Correctement paramétré, le proxy va orienter la requête vers l'un des serveurs prêts à répondre.
Dans le cas du ClusterHAT, le proxy est installé sur le contrôleur du cluster, c'est à dire sur le Raspberry PI 3 sur lequel est connecté le ClusterHAT . Le proxy orientera les requêtes sur l'un ou l'autre des Pi Zero disponibles.
Pour Rasbian, il existe un proxy open source appelé HaProxy. Il est installé par la commande apt-get.
pi@cluster01:~ $ sudo apt-get update
. . .
pi@cluster01:~ $ sudo apt-get upgrade
. . .
pi@cluster01:~ $ sudo apt-get install haproxy
. . .
pi@cluster01:~ $
. . .
pi@cluster01:~ $ sudo apt-get upgrade
. . .
pi@cluster01:~ $ sudo apt-get install haproxy
. . .
pi@cluster01:~ $
Configuration de HaProxy
Après l'installation, démarrer HaProxy ne sert à rien. En effet, il faut le configurer pour qu'il oriente les requêtes HTTP, normalement écoutées sur le port 80 du contrôleur cluster01, vers les Pi Zero.
Il n'y a pas de serveur Apache installé sur le contrôleur du cluster (nommé cluster01). En revanche, un serveur Apache (et PHP 7) a été installé sur chaque Pi Zero. Pour que tous les Pi Zero renvoient le même contenu, il faut que le répertoire /var/www/html utilisé comme racine des sites web, soit vide et soient monté en NFS sur un répertoire partagé du contrôleur, /var/www/pub par exemple.
sur lesquels un serveur Apache a été installé. Le mode opératoire est décrit dans les articles "Partager un dossier par NFS" et "Monter un dossier distant par NFS".
L’URL que sollicite l'internaute passe par le contrôleur. Il ne sait ni si ce sont des Pi Zero qui répondent, ni combien il y en a. C'est donc le proxy installé sur le contrôleur qui va répondre à défaut d'un serveur Apache et qui va orienter les requêtes vers le bon serveur. Il faut donc indiquer au proxy ce qu'il doit faire. Cela se fait dans le fichier /etc/haproxy/haproxy.cfg.
pi@cluster01:~ $ sudo nano /etc/haproxy/haproxy.cfg
pi@cluster01:~ $
pi@cluster01:~ $
Il suffit d'ajouter à la fin du fichier ce qui est surligné en vert.
Dans la configuration de HaProxy il y a deux parties :
Dans la configuration de HaProxy il y a deux parties :
- La partie frontend qui permet définir les aiguillages de redirection. Dans l'exemple ci-dessous, l n'y a qu'un seul frontend pour tous les hosts qui écoutent le port 80 vont être affectés par les paramètres.
- La ou les parties backend qui permet de définir comme se fait la redirection. Dans l'exemple ci-dessous, il n'y a qu'un seul backend pour lequel la redirection s'effectue à tour de rôle (roundrobin) sur les trois serveurs slave01, 02 et 03. Ceux-ci sont configurés pour répondre sur le port 8080.
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# An alternative list with additional directives can be obtained from
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend ClusterHat-nodes
bind *:80
mode http
default_backend Web-nodes
backend Web-nodes
mode http
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server Pi-Zero-01 slave01:8080 check
server Pi-Zero-02 slave02:8080 check
server Pi-Zero-03 slave03:8080 check
stats enable
stats uri /stats
stats hide-version
stats auth admin:admin
stats refresh 30s
stats show-node
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# An alternative list with additional directives can be obtained from
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend ClusterHat-nodes
bind *:80
mode http
default_backend Web-nodes
backend Web-nodes
mode http
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server Pi-Zero-01 slave01:8080 check
server Pi-Zero-02 slave02:8080 check
server Pi-Zero-03 slave03:8080 check
stats enable
stats uri /stats
stats hide-version
stats auth admin:admin
stats refresh 30s
stats show-node
Ce qui est surligné en jaune correspond à des étiquettes HaProxy qui peuvent être choisies à volonté.
Ce qui est surligné en rouge correspond aux noms des serveurs (déterminés au moment de leur configuration par raspi-config). Ces noms peuvent être remplacés par les adresses IP des serveurs.
Ce qui est surligné en rouge correspond aux noms des serveurs (déterminés au moment de leur configuration par raspi-config). Ces noms peuvent être remplacés par les adresses IP des serveurs.
Démarrage du proxy
Au démarrage du Raspberry, le proxy ne démarre pas automatiquement. D'un coté, il vaut mieux car le cluster n'étant pas démarré non plus, les Pi Zero sont inaccessibles et le proxy n'aurait pas pu démarré correctement. Si tout ce passe bien, il n'y a aucun message qui s'affiche. Si un message est affiché, c'est qu'une erreur s'est produite et que le proxy n'a pas démarré correctement, probablement à cause d'une erreur de syntaxe dans le fichier de configuration.
pi@cluster01:~ $ clusterhat on
pi@cluster01:~ $ sudo service haproxy start
pi@cluster01:~ $
pi@cluster01:~ $ sudo service haproxy start
pi@cluster01:~ $
Pour effectuer un démarrage automatique de l'ensemble, il faudrait ajouter un script bash dans /etc/init.d. Cela fera l'objet d'un article ultérieur.
Test de la configuration
Pour tester la configuration, nous allons créer un script index.php dans le répertoire /var/www/pub du contrôleur du cluster.
pi@cluster01:~ $ sudo nano /var/www/pub/index.php
pi@cluster01:~ $
pi@cluster01:~ $
Le script suivant affiche d'abord le nom et l'adresse du serveur, puis la liste de tous les paramètres du serveur PHP.
<?php
$hostaddress = $_SERVER['SERVER_ADDR'];
$hostname = gethostbyaddr($hostaddress);
echo "Réponse provenant de $hostname ( $hostaddress )<br />";
?>
<h2>Variable $_SERVER</h2>
<?php
foreach ($_SERVER as $key=>$value)
{
echo "$key=$value<br />";
}
?>
$hostaddress = $_SERVER['SERVER_ADDR'];
$hostname = gethostbyaddr($hostaddress);
echo "Réponse provenant de $hostname ( $hostaddress )<br />";
?>
<h2>Variable $_SERVER</h2>
<?php
foreach ($_SERVER as $key=>$value)
{
echo "$key=$value<br />";
}
?>
Commentaires
Enregistrer un commentaire