Cluster RabbitMQ avec Docker Swarm

Docker 25/10/2017

rabbitmq_logo
⚠️ Important ! Cet article reste en ligne pour partager certaines informations mais techniquement il n'est plus possible de l'appliquer dans le sens où le dépôt des sources de l'image Docker a été supprimé définitivement.

RabbitMQ est un logiciel open source d'agent de message, qui implémente le procotole AMQP (Advanced Message Queuing Protocol) et est écrit en Erlang (source: wikipedia). Les bibliothèques client à interface sont disponibles dans beaucoup de language (Python, Perl, PHP, ...), je ne vais pas rester sur l'outil, vous trouverez plein de choses sur le net.

L'installation de RabbitMQ n'a rien de très compliqué en soit (y'a juste un package à installer dans le meilleur des cas) mais ça reste insuffisant pour avoir de la haute dispo, ce qu'on cherche dans la plupart des cas. Cet article vise donc le déploiement d'une stack RabbitMQ (et Consul) via Docker Swarm 😃. Je pars du principe que vous avez au minimum vos noeuds (managers/workers) de déployés (je prépare aussi un article sur le sujet avec Terraform/Scaleway).

L'idée ici étant de déployer une stack RabbitMQ sur vos noeuds avec X réplicas, par exemple avoir un total de 20 instances RabbitMQ sur 4 noeuds (ça fait 5/noeud) afin de profiter d'une haute dispo, biensûr le RabbitMQ est dans un mode de clustering automatique. Vous pouvez donc passer de 20 à 60 instances, cela sera ajouté automatiquement au cluster, même fonctionnement à l'inverse, sur ce niveau, vous vous occupez de rien !

On commence par cloner le dépôt :

git clone https://github.com/djerfy/Dockerfiles.git 
cd Dockerfiles/rabbitmq-autocluster

Maintenant il ne reste plus à adapter la configuration et à déployer la stack ! Dans un premier temps ouvrez le fichier docker-stack.yml pour l'ajustement des valeurs (ex: PlaceHereYourSecretErlangCookie pour le secret du cluster, PlaceHereYourAdminPassword pour le password d'admin) :

version: "3"

services:
    consul:
        image: "consul:latest"
        labels: [app=amqp-consul]
        ports:
            - "8500:8500"
        networks:
            - amqp
        environment:
            - 'CONSUL_BIND_INTERFACE=eth1'
            - 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}'
        command: agent -server -ui -client=0.0.0.0 -bootstrap-expect=2 -retry-join=consul
        deploy:
            replicas: 2
            placement:
                constraints: [node.role == manager]
            resources:
                reservations:
                    memory: 128M
            restart_policy:
                condition: on-failure
                delay: 5s
                max_attempts: 3
                window: 120s
            update_config:
                parallelism: 1
                delay: 10s
                failure_action: continue

    rabbitmq:
        image: "djerfy/rabbitmq-autocluster:latest"
        labels: [app=amqp-rabbitmq]
        ports:
            - "5672:5672"
            - "15672:15672"
        networks:
            - amqp
        environment:
            - 'AUTOCLUSTER_TYPE=consul'
            - 'AUTOCLUSTER_CLEANUP=true'
            - 'AUTOCLUSTER_DEREGISTER_AFTER=60'
            - 'AUTOCLUSTER_DELAY=20'
            - 'CLEANUP_WARN_ONLY=false'
            - 'CONSUL_HOST=consul'
            - 'CONSUL_PORT=8500'
            - 'CONSUL_SVC=rabbitmq'
            - 'CONSUL_SVC_ADDR_AUTO=true'
            - 'RABBIMQ_ERLANG_COOKIE=PlaceHereYourSecretErlangCookie'
            - 'RABBITMQ_DEFAULT_VHOST=/'
            - 'RABBITMQ_DEFAULT_USER=admin'
            - 'RABBITMQ_DEFAULT_PASS=PlaceHereYourAdminPassword'
        command: rabbitmq-server
        deploy:
            replicas: 4
            resources:
                reservations:
                    memory: 256M
            restart_policy:
                condition: on-failure
                delay: 15s
                max_attempts: 3
                window: 120s
            update_config:
                parallelism: 2
                delay: 20s
                failure_action: continue

networks:
    amqp:

Lorsque tout ça est bien adapté à vos besoins, vous pouvez déployer la stack :

docker stack deploy -c docker-stack.yml amqp

Un docker service ls doit vous afficher vos 2 services, Consul et RabbitMQ :

ID                  NAME                MODE                REPLICAS            IMAGE                                PORTS
yigqvai7slc5        amqp_consul         replicated          2/2                 consul:latest                        *:18500->8500/tcp
fx3vhp6bhxrr        amqp_rabbitmq       replicated          4/4                <your_name>/rabbitmq-autocluster:latest   *:5672->5672/tcp,*:15672->15672/tcp

Rendez-vous sur l'interface de management du RabbitMQ (IP de l'hôte sur le port 15672) et utiliser le compte d'admin configuré dans le docker-stack.yml. Vous devriez voir vos noeuds de cette manière :
djerfy-macbook-2017-10-21-a--19.44.03

Et sur Consul (IP de l'hôte sur le port 8500) ceci :
screenshot_-2019-07-13-at-09.26.39

Avec la liste des services enregistrés (consul et rabbitmq):
screenshot_-2019-07-13-at-09.25.45
screenshot_-2019-07-13-at-09.24.44

Après c'est à vous de scaler le RabbitMQ selon vos besoins, l'entrée/sortie dans le cluster sera automatique, c'est pas beau ça ? 😋

docker service update --replicas=50 amqp_rabbitmq

Il y a d'autres articles en préparation concernant le clustering RabbitMQ, soyez donc patient pour voir la suite (abonnez-vous au flux RSS, ce sera plus simple) !

Enjoy!
XorHak


PS n°1 : vos noeuds seront automatiquement ajoutés au cluster mais le fonctionnement n'est pas optimale par défaut (c'est à dire que les queues ne sont pas répliqués sur chaque noeud par défaut). Connectez-vous sur l'un des noeuds (le premier c'est bien) puis ajoutez cette policy : rabbitmqctl set_policy ha-all "" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

PS n°2 : le Consul est en cluster mais limité à 2 uniquement (sinon changer aussi la valeur de l'option -bootstrap-expect.

PS n°3 : vous remarquerez qu'il n'y a plus le Dockerfile dans le dépôt car au final j'ai simplement repris un existant dont les sources Github sont ici.

PS n°4 : ce fonctionnement est limité aux versions 3.6.x de RabbitMQ

Tags

🌱 DJΞRFY 🚀

👨🏻‍💻 Tech Lead SRE. Like #Linux, #Apple, #Kubernetes, #Docker, #Unraid, #Traefik, #Hacking, #Chia. Member of @OpenChia Team 🌱 ¯\_(ツ)_/¯