On a pu voir dans la première partie de mon tutoriel la mise en place d’un cluster Unifi via une réplication MongoDB. La première partie est disponible ici ( https://wireless.fr/partie-1-mise-en-place-dun-serveur-unifi-en-haute-disponibilite/ ) pour ceux qui ne l’ont pas encore suivie !
Ce cluster, certes fonctionnel, manque d’automatisation : le failover entre les deux serveurs doit être réalisé manuellement, ce qui est vous en conviendrez une méthode un peu rustique ! On va donc travailler dans cette partie 2 à automatiser le failover lorsque Unifi ou MongoDB plante sur un des deux serveurs, pour pouvoir assurer la haute-disponibilité.
On reprend donc notre projet au point ou on l’avait laissé :
- Deux serveurs dédiés, le serveur Unifi1 d’IP X.X.X.X et le serveur Unifi2 d’IP Y.Y.Y.Y.
- Une IP Failover Z.Z.Z.Z, qui peut être attribuée a un des deux serveurs selon le besoin.
Les IPs sont des IP Publiques, accessibles depuis Internet.
Nous avons aussi trois enregistrements DNS, sur le domaine de votre choix. Ici pour l’exemple, votredomaine.fr :
- unifi1.votredomaine.fr pointant vers X.X.X.X,
- unifi2.votredomaine.fr pointant vers Y.Y.Y.Y,
- unifi.votredomaine.fr pointant vers Z.Z.Z.Z
Les deux serveurs dédiés sont hébergés sur la plateforme Dedi-Online (Iliad), ainsi que l’IP Failover. Ce tutoriel va donc exploiter l’API de Dedi-Online pour pouvoir automatiquement bouger l’IP Failover entre les serveurs en cas de problème. Je vous rassure, ce tutoriel est tout à fait utilisable sur d’autres plateformes comme OVH ou autres : il faudra seulement adapter le script vu plus bas pour votre plateforme. Le reste du tutoriel ne change pas !
A noter que le tutoriel fonctionne aussi avec des adresses privées, sur un réseau local, si votre cluster Unifi est local. Je préciserais dans le tutoriel comment l’adapter à votre infrastructure réseau 🙂
1. Mise en place du Failover via KEEPALIVED
Pour réaliser cette automatisation, nous allons nous baser sur le paquet Keepalived (http://www.keepalived.org/) qui permet de réaliser un cluster via le protocole VRRP, souvent utilisé dans les routeurs. Keepalived dispose de beaucoup de fonctions différentes : load-balancing, failover, master/slave cluster, etc … et va permettre ici d’automatiser notre cluster Unifi !
On va donc commencer par installer Keepalived sur les deux serveurs, il est disponible dans les dépôts Ubuntu/Debian par défaut :
root@unifi1:~# apt-get install -y keepalived
root@unifi2:~# apt-get install -y keepalived
Une fois installé, on va venir modifier les fichiers de configuration de Keepalived. En premier lieu, sur notre serveur primaire :
root@unifi1:~# nano /etc/keepalived/keepalived.conf
vrrp_script chk_mongod {
script "/usr/bin/pgrep mongod"
interval 2
}
vrrp_script chk_unifi {
script "/bin/systemctl status unifi"
interval 2
}
vrrp_instance VI_1 {
# The interface keepalived will manage
interface enp0s20
state BACKUP
# How often to send out VRRP advertisements
advert_int 2
# The virtual router id number to assign the routers to
virtual_router_id 51
# The priority to assign to this device. This controls
# who will become the MASTER and BACKUP for a given
# VRRP instance (a lower number get’s less priority).
priority 50
authentication {
auth_type PASS
auth_pass password
}
unicast_src_ip X.X.X.X
unicast_peer {
Y.Y.Y.Y
}
track_script {
chk_mongod
chk_unifi
}
# The virtual IP addresses to float between nodes.
virtual_ipaddress {
Z.Z.Z.Z
}
notify_master "/etc/keepalived/failover.sh"
}
Plusieurs choses à modifier dans ce fichier, en fonction de votre configuration :
- “interface enp0s20” définit ici le nom de votre interface principale. Vous pouvez utiliser la commande “ip a” pour voir les interfaces de votre serveur. Remplacez “enp0s20” par le nom de votre interface

- “unicast_src_ip X.X.X.X” définit l’IP du serveur sur lequel vous êtes, ici le serveur primaire. Remplacer X.X.X.X par l’IP de votre serveur primaire.
- “unicast_peer {Y.Y.Y.Y}” définit l’IP du serveur secondaire qu’il doit contacter. Remplacer Y.Y.Y.Y par l’IP de votre serveur secondaire.
- “virtual_ipaddress { Z.Z.Z.Z }” définit l’IP qui doit “flotter” ou basculer entre les serveurs. Remplacer Z.Z.Z.Z par votre IP Failover.
On note aussi qu’on a définit deux scripts au début du fichier de configuration : chk_mongod et chk_unifi . Ces deux scripts vont vérifier le bon fonctionnement du service Unifi et du service MongoDB (défini dans la Partie 1 du tutoriel), et renvoyer un code d’erreur ou non. Si Keepalived détecte que le script est en défaut , il déclenche une bascule vers le serveur secondaire.
Une fois modifié sur le serveur primaire, on fait les mêmes opérations sur le serveur secondaire :
root@unifi2:~# nano /etc/keepalived/keepalived.conf
vrrp_script chk_mongod {
script "/usr/bin/pgrep mongod"
interval 2
}
vrrp_script chk_unifi {
script "/bin/systemctl status unifi"
interval 2
}
vrrp_instance VI_1 {
# The interface keepalived will manage
interface enp1s0
state BACKUP
# How often to send out VRRP advertisements
advert_int 2
# The virtual router id number to assign the routers to
virtual_router_id 51
# The priority to assign to this device. This controls
# who will become the MASTER and BACKUP for a given
# VRRP instance (a lower number get’s less priority).
priority 50
authentication {
auth_type PASS
auth_pass password
}
unicast_src_ip Y.Y.Y.Y
unicast_peer {
X.X.X.X
}
track_script {
chk_mongod
chk_unifi
}
# The virtual IP addresses to float between nodes.
virtual_ipaddress {
Z.Z.Z.Z
}
notify_master "/etc/keepalived/failover.sh"
}
La configuration est similaire à celle sur le serveur primaire, sauf que unicast_src_ip et unicast_peer sont inversés, puisque nous sommes sur le serveur secondaire 😉
- “interface enp1s0” définit ici le nom de votre interface principale. Vous pouvez utiliser la commande “ip a” pour voir les interfaces de votre serveur. Remplacez “enp1s0” par le nom de votre interface
- “unicast_src_ip Y.Y.Y.Y” définit l’IP du serveur sur lequel vous êtes, ici le serveur secondaire. Remplacer Y.Y.Y.Y par l’IP de votre serveur secondaire.
- “unicast_peer {X.X.X.X}” définit l’IP du serveur primaire qu’il doit contacter. Remplacer X.X.X.X par l’IP de votre serveur primaire.
- “virtual_ipaddress { Z.Z.Z.Z }” définit l’IP qui doit “flotter” ou basculer entre les serveurs. Remplacer X.X.X.X par votre IP Failover.
Il est à noter dans les deux configurations la ligne notify_master “/etc/keepalived/failover.sh”.
L’argument notify_master est appelé lorsque Keepalived détecte une erreur et doit basculer. Il ne peut accueillir qu’un script Bash.
Idéalement c’est un argument utilisé pour notifier l’administrateur qu’un incident à eu lieu, par mail par exemple. Toutefois, on va le détourner ici pour lancer la bascule de l’IP Failover via l’API de Dedi-Online.
En effet, Keepalived va faire bouger notre IP Failover côté système entre serveur primaire et serveur secondaire, ce qui est le comportement attendu. Toutefois, comme souvent avec les IP Failover, il est nécessaire aussi de basculer sur l’interface de votre plateforme pour que le routage soit basculé d’un serveur à l’autre : sans ça, votre IP aura basculée mais elle ne répondra pas correctement car la route sera restée sur l’ancien serveur.
Si vous utilisez une configuration locale (avec des adresses privées sur un réseau LAN), vous pouvez passer directement à la partie 3, après avoir préalablement retirer de la configuration de Keepalived la ligne “notify_master “. N’oubliez pas de redémarrer les services Keepalived sur les deux serveurs.
2. Mise en place du script de bascule via l’API Dedi-Online
Cette partie va nous permettre de configurer le script “/etc/keepalived/failover.sh”, qui réalisera la bascule de notre IP Failover sur l’interface DediOnline. Le script doit être adapté en fonction de votre plateforme, se référer à la documentation disponible. Si vous avez besoin d’aide sur cette partie, n’hésitez pas à me contacter ou à commenter l’article 🙂
Comme souvent avec les IP Failover, une API est à disposition sur la plateforme d’hébergement pour pouvoir intégrer la bascule dans des scripts ou des applications. Sur Dedi-Online, l’API est mise à disposition sur ce lien : https://console.online.net/fr/api/
Sur les deux serveurs, on va créer et modifier le script “/etc/keepalived/failover.sh“. Il s’agit d’un appel à un script PHP que l’on va créer ensuite :
root@unifi1:~# nano /etc/keepalived/failover.sh
root@unifi2:~# nano /etc/keepalived/failover.sh
#!/usr/bin/env bash
php /etc/keepalived/failover.php
Avant de créer le script PHP de bascule, on installe PHP et PHP-Curl sur les deux serveurs :
root@unifi1:~# apt-get install -y php php-curl
root@unifi2:~# apt-get install -y php php-curl
Sur le serveur primaire, on modifie le script “/etc/keepalived/failover.php” et on ajoute les lignes suivantes :
root@unifi1:~# nano /etc/keepalived/failover.php
<?php
function call_online_api($token, $http_method, $endpoint, $get = array(), $post = array())
{
if (!empty($get)) {
$endpoint .= '?' . http_build_query($get);
}
$call = curl_init();
curl_setopt($call, CURLOPT_URL, 'https://api.online.net/api/v1' . $endpoint);
curl_setopt($call, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $token, 'X-Pretty-JSON: 1'));
curl_setopt($call, CURLOPT_RETURNTRANSFER, true);
if ($http_method == 'POST') {
curl_setopt($call, CURLOPT_POST, true);
curl_setopt($call, CURLOPT_POSTFIELDS, http_build_query($post));
}
return curl_exec($call);
}
$token = "56484846a46468464641za6d465a468464";
//$user_info = call_online_api($token, 'GET', '/user/info');
//echo $user_info;
//$failovers = call_online_api($token, 'GET', '/server/failover');
//echo $failovers;
// edit a failover IP
$post = array(
'source' => 'Z.Z.Z.Z',
'destination' => 'Y.Y.Y.Y',
);
$move_failover = call_online_api($token, 'POST', '/server/failover/edit', null, $post);
var_export($move_failover);
Pour rappel, ce script sera appelé lorsqu’on bascule du serveur primaire vers le secondaire. En conséquence, il faut modifier les informations suivantes dans le script :
- “$token = “56484846a46468464641za6d465a468464”” est le “token” qui valide la connexion à l’API Dedi-Online. Vous pouvez le générer directement via le lien suivant : https://console.online.net/fr/api/access
- ” ‘source’ => ‘Z.Z.Z.Z’ ” définit l’IP Failover qui sera basculée. Remplacer Z.Z.Z.Z par votre IP Failover.
- ” ‘destination’ => ‘Y.Y.Y.Y’ ” définit l’IP du serveur secondaire vers lequel sera basculé l’IP Failover. Remplacer Y.Y.Y.Y par l’IP de votre serveur secondaire.
Sur le serveur secondaire, on vient aussi modifier le script “/etc/keepalived/failover.php” :
root@unifi2:~# nano /etc/keepalived/failover.php
<?php
function call_online_api($token, $http_method, $endpoint, $get = array(), $post = array())
{
if (!empty($get)) {
$endpoint .= '?' . http_build_query($get);
}
$call = curl_init();
curl_setopt($call, CURLOPT_URL, 'https://api.online.net/api/v1' . $endpoint);
curl_setopt($call, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $token, 'X-Pretty-JSON: 1'));
curl_setopt($call, CURLOPT_RETURNTRANSFER, true);
if ($http_method == 'POST') {
curl_setopt($call, CURLOPT_POST, true);
curl_setopt($call, CURLOPT_POSTFIELDS, http_build_query($post));
}
return curl_exec($call);
}
$token = "56484846a46468464641za6d465a468464";
//$user_info = call_online_api($token, 'GET', '/user/info');
//echo $user_info;
//$failovers = call_online_api($token, 'GET', '/server/failover');
//echo $failovers;
// edit a failover IP
$post = array(
'source' => 'Z.Z.Z.Z',
'destination' => 'X.X.X.X',
);
$move_failover = call_online_api($token, 'POST', '/server/failover/edit', null, $post);
var_export($move_failover);
Pour rappel, ce script sera appelé lorsqu’on bascule du serveur secondaire vers le serveur primaire. En conséquence, il faut modifier les informations suivantes dans le script :
- “$token = “56484846a46468464641za6d465a468464”” est le “token” qui valide la connexion à l’API Dedi-Online. Vous pouvez le générer directement via le lien suivant : https://console.online.net/fr/api/access
- ” ‘source’ => ‘Z.Z.Z.Z’ ” définit l’IP Failover qui sera basculée. Remplacer Z.Z.Z.Z par votre IP Failover.
- ” ‘destination’ => ‘X.X.X.X’ ” définit l’IP du serveur primaire vers lequel sera basculé l’IP Failover. Remplacer X.X.X.X par l’IP de votre serveur primaire.
Sur les deux serveurs, ne pas oublier de rendre les scripts exécutables :
root@unifi1:~# chmod +x /etc/keepalived/failover.*
root@unifi2:~# chmod +x /etc/keepalived/failover.*
Enfin, sur les deux serveurs, on redémarre le service Keepalived pour prendre en compte les modifications réalisées :
root@unifi1:~# service keepalived restart
root@unifi2:~# service keepalived restart
Félicitations, votre cluster est maintenant fonctionnel et complètement automatisé !
3. Vérifications du bon fonctionnement de notre cluster
Sur les deux serveurs, on peut ensuite vérifier que Keepalived fonctionne bien en utilisant la commande “service keepalived status“
root@unifi1:~# service keepalived status
● keepalived.service - Keepalive Daemon (LVS and VRRP)
Loaded: loaded (/lib/systemd/system/keepalived.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2018-11-20 14:49:15 CET; 8s ago
Process: 9919 ExecStart=/usr/sbin/keepalived $DAEMON_ARGS (code=exited, status=0/SUCCESS)
Main PID: 9921 (keepalived)
CGroup: /system.slice/keepalived.service
├─9921 /usr/sbin/keepalived
├─9922 /usr/sbin/keepalived
└─9923 /usr/sbin/keepalived
Nov 20 14:49:15 unifi1 Keepalived_vrrp[9923]: VRRP_Instance(VI_1) Entering BACKUP STATE
Nov 20 14:49:15 unifi1 Keepalived_healthcheckers[9922]: Registering Kernel netlink reflector
Nov 20 14:49:15 unifi1 Keepalived_healthcheckers[9922]: Registering Kernel netlink command channel
Nov 20 14:49:15 unifi1 Keepalived_healthcheckers[9922]: Opening file '/etc/keepalived/keepalived.conf'.
Nov 20 14:49:15 unifi1 Keepalived_healthcheckers[9922]: Using LinkWatch kernel netlink reflector...
Nov 20 14:49:15 unifi1 Keepalived_vrrp[9923]: VRRP_Script(chk_mongod) succeeded
Nov 20 14:49:15 unifi1 Keepalived_vrrp[9923]: VRRP_Script(chk_unifi) succeeded
Nov 20 14:49:21 unifi1 Keepalived_vrrp[9923]: VRRP_Instance(VI_1) Transition to MASTER STATE
Nov 20 14:49:23 unifi1 Keepalived_vrrp[9923]: VRRP_Instance(VI_1) Entering MASTER STATE
Nov 20 14:49:23 unifi1 Keepalived_vrrp[9923]: Opening script file /etc/keepalived/failover.sh
root@unifi2:~# service keepalived status
● keepalived.service - Keepalive Daemon (LVS and VRRP)
Loaded: loaded (/lib/systemd/system/keepalived.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2018-11-20 14:49:21 CET; 5s ago
Process: 11015 ExecStart=/usr/sbin/keepalived $DAEMON_ARGS (code=exited, status=0/SUCCESS)
Main PID: 11017 (keepalived)
CGroup: /system.slice/keepalived.service
├─11017 /usr/sbin/keepalived
├─11018 /usr/sbin/keepalived
└─11019 /usr/sbin/keepalived
Nov 20 14:49:21 unifi2 Keepalived_vrrp[11019]: Opening file '/etc/keepalived/keepalived.conf'.
Nov 20 14:49:21 unifi2 systemd[1]: Started Keepalive Daemon (LVS and VRRP).
Nov 20 14:49:21 unifi2 Keepalived_vrrp[11019]: Using LinkWatch kernel netlink reflector...
Nov 20 14:49:21 unifi2 Keepalived_vrrp[11019]: VRRP_Instance(VI_1) Entering BACKUP STATE
Nov 20 14:49:21 unifi2 Keepalived_healthcheckers[11018]: Registering Kernel netlink reflector
Nov 20 14:49:21 unifi2 Keepalived_healthcheckers[11018]: Registering Kernel netlink command channel
Nov 20 14:49:21 unifi2 Keepalived_healthcheckers[11018]: Opening file '/etc/keepalived/keepalived.conf'.
Nov 20 14:49:21 unifi2 Keepalived_healthcheckers[11018]: Using LinkWatch kernel netlink reflector...
Nov 20 14:49:21 unifi2 Keepalived_vrrp[11019]: VRRP_Script(chk_unifi) succeeded
Nov 20 14:49:21 unifi2 Keepalived_vrrp[11019]: VRRP_Script(chk_mongod) succeeded
On voit que le serveur Unifi1 est considéré comme “Master” et le serveur Unifi2 est considéré en “Backup” state. On voit aussi que sur les deux serveurs, les scripts chk_unifi et chk_mongod sont en état “succeeded“, ce qui veut dire que les services Unifi et MongoDB tournent correctement sur les deux serveurs. Tout va bien donc !
Via la commande “ip a“, vous pouvez aussi vérifier sur quel serveur est l’IP Failover et vérifiez en même temps que l’état dans Keepalived correspond : seul le Master (“VRRP_Instance(VI_1) Entering MASTER STATE”) porte l’IP du cluster. Dans le cas ci-dessus, Unifi1 :
root@unifi1:~# ip a
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s20: mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:07:cb:03:b3:32 brd ff:ff:ff:ff:ff:ff
inet X.X.X.X/24 brd X.X.X.X scope global enp0s20
valid_lft forever preferred_lft forever
inet Z.Z.Z.Z/32 scope global enp0s20
valid_lft forever preferred_lft forever
inet6 ff:ff:ff:ff:ff:ff/64 scope link
valid_lft forever preferred_lft forever
Si vous souhaitez tester que tout est pleinement fonctionnel, lancez un ping depuis votre PC vers l’IP Failover Z.Z.Z.Z. Puis déclencher la bascule sur le serveur primaire en coupant le service Unifi (“service unifi stop“) ou MongoDB (“service mongod stop“). Si tout se passe comme prévu, vous subirez 30 secondes à 1 minute de coupure sur vos pings, le temps que le routage de l’IP Failover soit modifié. Puis votre serveur secondaire reprend le relais 🙂
Conclusion
Bravo, vous disposez d’un cluster Unifi pleinement fonctionnel et automatique ! Faites un maximum de tests pour vous assurer que tout fonctionne comme vous le souhaitez, en coupant le service Keepalived, Unifi, MongoDB, en redémarrant les serveurs, etc …
A noter ici que si on bascule sur le serveur secondaire, il n’y a pas de retour automatique sur le primaire, il faudra le faire manuellement. La configuration de Keepalived va dans ce sens pour éviter que quand le serveur primaire redémarre / redevient fonctionnel après avoir basculé, l’IP Failover revienne aussi. Il faudra une action manuelle pour basculer à nouveau vers le primaire, le temps de faire des tests et vérifications pour s’assurer que le primaire est bien fonctionnel !
Vous pouvez aussi aller plus loin en ajoutant des scripts de vérifications à la configuration de Keepalived, si vous souhaitez vérifier d’autres informations afin de générer une bascule 🙂
Si vous avez des idées pour améliorer la configuration ce tutoriel, n’hésitez pas à réagir via les commentaires ou via notre formulaire de contact !
A très bientôt, et à suivre bientôt une prochaine partie de notre tutoriel qui sera consacrée à la mise en place de HTTPS pour notre beau cluster tout neuf ! @ +