Déploiement de Redis et Sentinel avec Docker swarm mode
Par Nicolas Dutertry le mercredi 5 juillet 2017, 13:59 - Lien permanent
Dans ce billet nous verrons comment déployer Redis avec Docker swarm mode de manière hautement disponible grâce à Sentinel. Pour cela nous utiliserons :
- Une instance master de Redis par laquelle passeront toutes les commandes
- Une instance slave de Redis permettant de répliquer les données du master
- 3 instances de Sentinel permettant de basculer sur le slave en cas de crash du master
Infrastructure
Pour déployer ces instances nous disposons de 3 machines (ou VM) qui formeront le swarm :
- Machine manager - adresse IP 192.168.56.2 : Cette machine fera office de manager du swarm.
- Machine worker1 - adresse IP 192.168.56.3 : Worker n°1 du swarm.
- Machine worker2 - adresse IP 192.168.56.4 : Worker n°2 du swarm.
Le problème des adresses IP
Docker swarm mode simplifie grandement le déploiement de services dans un cluster ainsi que la communication entre ces services grâce aux "overlay networks". Cependant, le déploiement de Sentinel pose problème car pour superviser les instances de Redis et communiquer avec les autres instances de Sentinel, il utilise leurs adresses IP qu'il considère comme fixes. Or les services déployés avec Docker swarm ont des adresses IP dynamiques : si un service s'arrête puis redémarre, il n'obtient pas forcément la même adresse IP qu'avant son arrêt. Ce fonctionnement met à mal Sentinel qui ne reconnait plus les instances arrêtées puis redémarrées.
Dans le futur, les évolutions de Docker nous permettrons peut-être d'utiliser un overlay network avec des adresses IP fixes. A l'heure actuelle (version 17.06 de Docker) la seule solution pour obtenir des adresses IP fixes est d'attacher les services sur le réseau de la machine hôte, plutôt que sur un overlay network. Cette solution n'est pas idéale mais c'est la seule qui fonctionne.
Persistance des données
Lorsque Sentinel supervise les instances de Redis, il est susceptible de modifier leur configuration. C'est le cas par exemple lorsqu'un slave devient master suite au crash du master. Pour fonctionner correctement, les instances de Redis et de Sentinel ne doivent pas perdre leur configuration en cas de redémarrage. Il faut donc utiliser des volumes docker pour stocker la configuration.
De plus pour un maximum de sécurité on souhaite stocker sur disque toutes les données de Redis avec l'option appendonly.
J'ai donc créé les 2 images Docker suivantes :
- ndutertry/redis-ha : Elle permet de lancer un conteneur Redis en master ou slave avec persistance de la configuration et des données.
- ndutertry/redis-sentinel : Elle permet de lancer un conteneur Sentinel avec persistance de la configuration.
Les sources et les options de configuration de ces images sont disponibles sur GitHub :
Contraintes de déploiement
Les contraintes liées aux adresses IP et à la persistance des données font qu'on ne peut pas laisser à Docker swarm la possibilité de déployer les instances sur n'importe quelle machine. on aura donc :
- Machine manager : Une instance de Sentinel.
- Machine worker1 : L'instance Redis master et une instance de Sentinel.
- Machine worker2 : L'instance Redis slave et une instance de Sentinel.
Création du stack
Il ne reste plus qu'à créer un fichier redis-ha-stack.yml correspondant au schéma suivant :
Les services du stack sont décrits ci-dessous.
Service redis-master
- Il correspond à l'instance master de Redis et il se base sur l'image ndutertry/redis-ha.
- Il utilise un volume redis-data mappé sur /data pour la persistance des données
- Il utilise un volume redis-conf mappé sur /etc/redis pour la persistance de la configuration
- Il est déployé sur worker1
- Il utilise le réseau de la machine hôte
Dans le stack il sera référencé ainsi :
redis-master: image: ndutertry/redis-ha volumes: - redis-data:/data - redis-conf:/etc/redis deploy: mode: global placement: constraints: - node.hostname == worker1 networks: - host
Service redis-slave
- Il correspond à l'instance slave de Redis et il se base sur l'image ndutertry/redis-ha.
- On positionne la variable d'environnement REDIS_MASTER_HOST utilisée par l'image pour en faire un slave et pointer vers le master.
- Il utilise un volume redis-data mappé sur /data pour la persistance des données
- Il utilise un volume redis-conf mappé sur /etc/redis pour la persistance de la configuration
- Il est déployé sur worker2
- Il utilise le réseau de la machine hôte
Dans le stack il sera référencé ainsi :
redis-slave: image: ndutertry/redis-ha volumes: - redis-data:/data - redis-conf:/etc/redis environment: - REDIS_MASTER_HOST=192.168.56.3 deploy: mode: global placement: constraints: - node.hostname == worker2 networks: - host
Service redis-sentinel
- Il correspond aux 3 instances de Sentinel et il se base sur l'image ndutertry/redis-sentinel.
- On positionne la variable d'environnement REDIS_MASTER_HOST utilisée par l'image pour pointer vers le master.
- Il utilise un volume sentinel-conf mappé sur /etc/redis pour la persistance de la configuration
- Il est déployé en mode global sur tous les noeuds
- Il utilise le réseau de la machine hôte
Dans le stack il sera référencé ainsi :
redis-sentinel: image: ndutertry/redis-sentinel volumes: - sentinel-conf:/etc/redis deploy: mode: global environment: - REDIS_MASTER_HOST=192.168.56.3 - SENTINEL_DOWN_AFTER=5000 - SENTINEL_FAILOVER=15000 networks: - host
Service simple-redis-app
On ajoute également un service simple-redis-app permettant de tester l'accès à Redis en affichant un compteur de visite :
- On positionne la variable d'environnement SENTINEL_HOST utilisée par l'image pour pointer vers l'une des instances de Sentinel.
- Il écoute sur le port 3000
- Il est déployé en 3 instances
Dans le stack il sera référencé ainsi :
simple-redis-app: image: ndutertry/simple-redis-app ports: - "3000:3000" environment: - SENTINEL_HOST=192.168.56.2 deploy: replicas: 3
Déploiement
Le fichier redis-ha-stack.yml complet est disponible sur GitHub : https://github.com/nicolas-dutertry...
Dans cette version on a remplacé les adresses IP et les noms des noeuds par des variables d'environnement. Pour déployer le stack avec Docker swarm on peut utiliser le script deploy.sh en passant en paramètre le nom des noeuds manager, worker n°1 et worker n°2 :
$ ./deploy.sh manager worker1 worker2
Test
Pour tester que la solution fonctionne on ouvre tout d'abord dans un navigateur l'url http://192.168.56.2:3000/. On vérifie que le compteur augmente en rafraîchissant la page.
Ensuite on arrête la machine worker1 et après quelques secondes on vérifie que l'application fonctionne toujours. Cela veut dire qu'on a basculé sur le slave, qui est maintenant devenu le master.
On redémarre worker1 et on arrête worker2. L'application fonctionne normalement toujours, puisqu'on a refait la bascule vers le master initial.
Enfin si l'on arrête toutes les machines et que l'on redémarre, on peut vérifier que la valeur du compteur n'a pas été perdue.
Adaptation
L'exemple d'infrastructure présenté ici peut bien entendu être adapté. On pourra par exemple augmenter la robustesse de l'ensemble en ajoutant des machines sur lesquelles se déploieront des instances supplémentaires de Sentinel et de slaves Redis.
Commentaires
At this moment I am goіng to do my breakfast, later than having my breakfаѕt coming over agaіn to read
further news.
Wood household furniture has one thing really
all natural about it. There is this feeling of coziness, of attributes
as well as of style that may be be located in wood household furniture.
Hardwood is actually birthed from the earth.
It feeds the fire, falls to pieces in to drafts as
well as ashes away. It is actually very near the
human existence in the world. Might be that is why it resonates so much with our company.
When you contact a wealthy mahogany workdesk, may be that is actually why you still get that cozy sensation.