Operations 17 min read

Build a Highly Available RabbitMQ Cluster with Docker, HAProxy, and Keepalived

This guide walks through creating a resilient RabbitMQ cluster using two disk nodes and one RAM node, Docker and docker‑compose for deployment, HAProxy for load balancing with VIP failover, and Keepalived for master‑backup high availability, including configuration, scripts, and testing steps.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Build a Highly Available RabbitMQ Cluster with Docker, HAProxy, and Keepalived

RabbitMQ High‑Availability Cluster Architecture

Combine two RabbitMQ disk nodes and one RabbitMQ RAM node into an internal cluster. Two disk nodes are used to avoid loss of queues and exchanges if the sole disk node fails. HAProxy provides load balancing for the RabbitMQ cluster, and Keepalived creates a master‑backup pair of HAProxy nodes to eliminate a single point of failure. Clients access the service via a virtual IP (VIP) that points to the active HAProxy instance; when the master HAProxy fails, the VIP migrates to the backup.

Preparation

Install Docker and docker‑compose on each server, and prepare offline images rabbitmq.tar and haproxy.tar. Ensure all servers can ping each other.

RabbitMQ Cluster

Use RabbitMQ's built‑in clustering. Persistent queues cannot be recreated on another node if the original node crashes, while non‑persistent queues can automatically connect to an available node. The project uses non‑persistent queues, and at least two disk nodes are required to guarantee metadata creation after a disk node failure.

Service Distribution

192.168.1.213  Server deploys RabbitMQ Disc Node1.
192.168.1.203  Server deploys RabbitMQ Disc Node2.
192.168.1.212  Server deploys RabbitMQ RAM Node3.

Deploy the First RabbitMQ Node

Create directory /app/mcst/rabbitmq on the server, upload rabbitmq.tar and the compose file mcst-rabbitmq-node1.yaml via SFTP, then load the image:

$ docker load -i rabbitmq.tar
$ docker images   # verify import

Compose file mcst-rabbitmq-node1.yaml:

version: '3'
services:
  rabbitmq:
    container_name: mcst-rabbitmq
    image: rabbitmq:3-management
    restart: always
    ports:
      - 4369:4369
      - 5671:5671
      - 5672:5672
      - 15672:15672
      - 25672:25672
    environment:
      - TZ=Asia/Shanghai
      - RABBITMQ_ERLANG_COOKIE=iweru238roseire
      - RABBITMQ_DEFAULT_USER=mcst_admin
      - RABBITMQ_DEFAULT_PASS=mcst_admin_123
      - RABBITMQ_DEFAULT_VHOST=mcst_vhost
    hostname: rabbitmq1
    extra_hosts:
      - rabbitmq1:192.168.1.213
      - rabbitmq2:192.168.1.203
      - rabbitmq3:192.168.1.212
    volumes:
      - ./data:/var/lib/rabbitmq

Deploy with:

$ docker-compose -f mcst-rabbitmq-node1.yaml up -d

All three nodes must share the same RABBITMQ_ERLANG_COOKIE and have extra_hosts configured; otherwise the cluster cannot discover other nodes. This node serves as the cluster root.

Deploy the Second RabbitMQ Node

Repeat the same steps, uploading rabbitmq.sh to ./rabbitmq.sh and using the compose file mcst-rabbitmq-node2.yaml:

version: '3'
services:
  rabbitmq:
    container_name: mcst-rabbitmq
    image: rabbitmq:3-management
    restart: always
    ports:
      - 4369:4369
      - 5671:5671
      - 5672:5672
      - 15672:15672
      - 25672:25672
    environment:
      - TZ=Asia/Shanghai
      - RABBITMQ_ERLANG_COOKIE=iweru238roseire
      - RABBITMQ_DEFAULT_USER=mcst_admin
      - RABBITMQ_DEFAULT_PASS=mcst_admin_123
      - RABBITMQ_DEFAULT_VHOST=mcst_vhost
    hostname: rabbitmq2
    extra_hosts:
      - rabbitmq1:192.168.1.213
      - rabbitmq2:192.168.1.203
      - rabbitmq3:192.168.1.212
    volumes:
      - ./rabbitmq.sh:/home/rabbitmq.sh
      - ./data:/var/lib/rabbitmq

Deploy:

$ docker-compose -f mcst-rabbitmq-node2.yaml up -d

Enter the container and run the script (grant execution if needed):

$ docker exec -it mcst-rabbitmq /bin/bash
$ chmod +x /home/rabbitmq.sh
$ bash /home/rabbitmq.sh

Script content (disk node):

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbitmq1
rabbitmqctl start_app

Deploy the Third RabbitMQ Node (RAM)

Use compose file mcst-rabbitmq-node3.yaml:

version: '3'
services:
  rabbitmq:
    container_name: mcst-rabbitmq
    image: rabbitmq:3-management
    restart: always
    ports:
      - 4369:4369
      - 5671:5671
      - 5672:5672
      - 15672:15672
      - 25672:25672
    environment:
      - TZ=Asia/Shanghai
      - RABBITMQ_ERLANG_COOKIE=iweru238roseire
      - RABBITMQ_DEFAULT_USER=mcst_admin
      - RABBITMQ_DEFAULT_PASS=mcst_admin_123
      - RABBITMQ_DEFAULT_VHOST=mcst_vhost
    hostname: rabbitmq3
    extra_hosts:
      - rabbitmq1:192.168.1.213
      - rabbitmq2:192.168.1.203
      - rabbitmq3:192.168.1.212
    volumes:
      - ./rabbitmq-ram.sh:/home/rabbitmq-ram.sh
      - ./data:/var/lib/rabbitmq

Deploy:

$ docker-compose -f mcst-rabbitmq-node3.yaml up -d

Inside the container, run: $ bash /home/rabbitmq-ram.sh RAM node script:

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq1
rabbitmqctl start_app

Check cluster status: rabbitmqctl cluster_status Result shows disc nodes rabbit@rabbitmq1, rabbit@rabbitmq2 and RAM node rabbit@rabbitmq3. The management UI is reachable at http://192.168.1.213:15672.

HAProxy Load Balancing

Create directory /app/mcst/haproxy, upload the haproxy.tar, the HAProxy configuration file, and the compose file.

Compose file mcst-haproxy.yaml:

version: '3'
services:
  haproxy:
    container_name: mcst-haproxy
    image: haproxy:2.1
    restart: always
    ports:
      - 8100:8100
      - 15670:5670
    environment:
      - TZ=Asia/Shanghai
    extra_hosts:
      - rabbitmq1:192.168.1.213
      - rabbitmq2:192.168.1.203
      - rabbitmq3:192.168.1.212
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro

Key points are the extra_hosts mapping of RabbitMQ nodes and mounting a custom haproxy.cfg.

HAProxy configuration ( haproxy.cfg) excerpt:

global
    log 127.0.0.1 local0 info
    maxconn 4096

defaults
    log global
    mode tcp
    option tcplog
    retries 3
    option redispatch
    maxconn 2000
    timeout connect 5s
    timeout client 120s
    timeout server 120s

listen stats
    bind *:8100
    mode http
    stats enable
    stats realm Haproxy\ Statistics
    stats uri /
    stats auth admin:admin123

listen rabbitmq
    bind *:5670
    mode tcp
    balance roundrobin
    server rabbitmq1 rabbitmq1:5672 check inter 5s rise 2 fall 3
    server rabbitmq2 rabbitmq2:5672 check inter 5s rise 2 fall 3
    server rabbitmq3 rabbitmq3:5672 check inter 5s rise 2 fall 3

Deploy HAProxy:

$ docker-compose -f mcst-haproxy.yaml up -d

HAProxy Service Distribution

192.168.1.212  Server deploys HAProxy Master.
192.168.1.203  Server deploys HAProxy Backup.

Start HAProxy on both nodes and verify the cluster status via the HAProxy stats UI at http://192.168.1.212:8100/.

Install Keepalived for HAProxy Master‑Backup

Download Keepalived 2.0.20, extract, and compile with required dependencies (gcc, openssl‑devel, libnl, libnl‑devel). Use a local yum repository if the server has no internet access.

$ tar -xf keepalived-2.0.20.tar.gz
$ cd keepalived-2.0.20
$ ./configure
$ make
$ make install

Verify installation:

$ keepalived --version

Create Keepalived Configuration

File /etc/keepalived/keepalived.conf for the master node:

vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 5
    weight -2
}

vrrp_instance VI_1 {
    state MASTER
    interface ens192
    virtual_router_id 51
    priority 101
    virtual_ipaddress {
        192.168.1.110
    }
    track_script {
        chk_haproxy
    }
}

Backup node configuration is identical except state BACKUP and priority 100.

vrrp_instance VI_1 {
    state BACKUP
    interface ens192
    virtual_router_id 51
    priority 100
    virtual_ipaddress {
        192.168.1.110
    }
    track_script {
        chk_haproxy
    }
}

Start Keepalived:

$ systemctl restart keepalived

Test Keepalived Failover

On both master and backup, run ip addr to see which server holds the VIP 192.168.1.110. Stop HAProxy on the master; the VIP should migrate to the backup. Restart HAProxy on the master; the VIP should move back. Access HAProxy services via the VIP and port to confirm functionality.

At this point, a highly available RabbitMQ cluster with HAProxy load balancing and Keepalived master‑backup failover is fully operational.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Operationshigh-availabilityHAHAProxykeepalived
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.