rabbitmq_logo
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