## I. How to create and configure a RabbitMQ cluster ### 0. Prerequisites - 3 VMs (rabbit-1, rabbit-2, rabbit-3) running Ubuntu 20.04/22.04 with hostname properly configured - SSH access to each VM ### 1. Initial setup - Update and upgrade each VM: `sudo apt update && sudo apt upgrade -y` - Install RabbitMQ on all nodes: `sudo apt install rabbitmq-server` - Enable RabbitMQ management plugin: `sudo rabbitmq-plugins enable rabbitmq_management` ### 2. Cluster configuration - On the first node **(rabbit-1)**, create the cluster by running: - `sudo rabbitmqctl stop_app` - `sudo rabbitmqctl reset` - `sudo rabbitmqctl start_app` - `sudo cat /var/lib/rabbitmq/.erlang.cookie` -> `SJ2Et8HOmHJRBwOPOxs1kHzT4vGt7nUM17sBByW/MWP3fcxUNyISiYmi` Copy the cookie to other nodes - On the second and third nodes **(rabbit-2, rabbit-3)**, join the cluster by running: - `sudo systemctl stop rabbitmq-server` - `echo 'SJ2Et8HOmHJRBwOPOxs1kHzT4vGt7nUM17sBByW/MWP3fcxUNyISiYmi' > /var/lib/rabbitmq/.erlang.cookie` - `sudo systemctl start rabbitmq-server` - `sudo rabbitmqctl stop_app` - `sudo rabbitmqctl reset` - `sudo rabbitmqctl join_cluster --ram rabbit@rabbit-1` - `sudo rabbitmqctl start_app` ### 3. Verification - Access the RabbitMQ web management interface at http://rabbit-1:15672/ with the username and password set up during cluster configuration - Check that all nodes are listed as part of the cluster in the "Cluster Nodes" section of the management interface ## II. RabbitMQ durable queue ### `Vhost`, `Exchanges`, `Queues`, and `Bindings` Config environment ``` export VHOST_NAME=app-1 export USER_NAME=app-1-user export USER_PASSWORD=adminpassword export EXCHANGE_NAME=app-1-ex export QUEUE_NAME=app-1-q export ROUTING_KEY=app-1-rk ``` ### **0. Create a Vhost and user** ``` sudo rabbitmqctl add_vhost $VHOST_NAME sudo rabbitmqctl add_user $USER_NAME $USER_PASSWORD sudo rabbitmqctl set_user_tags $USER_NAME administrator sudo rabbitmqctl set_permissions $USER_NAME --vhost $VHOST_NAME ".*" ".*" ".*" sudo rabbitmqctl list_vhosts sudo rabbitmqctl list_user_permissions $USER_NAME ``` ### **1. Creating an Exchange** To create an exchange in RabbitMQ, run the following command: ``` sudo rabbitmqadmin -u $USER_NAME -p $USER_PASSWORD -V $VHOST_NAME \ declare exchange \ name=$EXCHANGE_NAME type=direct ``` The type of the exchange available `direct`, `topic`, or `fanout`. ### **2. Creating a durable Queue** To create a queue in RabbitMQ, run the following command: ``` sudo rabbitmqadmin -u $USER_NAME -p $USER_PASSWORD -V $VHOST_NAME \ declare queue \ name=$QUEUE_NAME durable=true queue_type=quorum ``` ### **3. Binding an Exchange to a Queue** To bind an exchange to a queue in RabbitMQ, run the following command: ``` sudo rabbitmqadmin -u $USER_NAME -p $USER_PASSWORD -V $VHOST_NAME \ declare binding \ source=$EXCHANGE_NAME destination_type=queue destination=$QUEUE_NAME routing_key=$ROUTING_KEY ``` ### **4. Publishing a Message to a Quorum Queue** To publish a message to a quorum queue in RabbitMQ, run the following command on node **rabbit-1**: ``` sudo rabbitmqadmin -u $USER_NAME -p $USER_PASSWORD -V $VHOST_NAME \ publish payload="Hello rabbit `date`" \ exchange=$EXCHANGE_NAME routing_key=$ROUTING_KEY ``` ### **5. Testing durability** To verify the message was published, run the following command: ``` sudo sudo rabbitmqadmin -u $USER_NAME -p $USER_PASSWORD -V $VHOST_NAME \ get queue=$QUEUE_NAME ``` Now poweroff the **rabbit-1** and run get message on **rabbit-2** and **rabbit-3** ``` ubuntu@rabiit-1:~$ sudo poweroff ubuntu@rabiit-2:~$ export VHOST_NAME=app-1 export USER_NAME=app-1-user export USER_PASSWORD=adminpassword export EXCHANGE_NAME=app-1-ex export QUEUE_NAME=app-1-q export ROUTING_KEY=app-1-rk ubuntu@rabiit-2:~$ sudo rabbitmqadmin -u $USER_NAME -p $USER_PASSWORD -V $VHOST_NAME \ get queue=$QUEUE_NAME ubuntu@rabiit-3:~$ export VHOST_NAME=app-1 export USER_NAME=app-1-user export USER_PASSWORD=adminpassword export EXCHANGE_NAME=app-1-ex export QUEUE_NAME=app-1-q export ROUTING_KEY=app-1-rk ubuntu@rabiit-2:~$ sudo rabbitmqadmin -u $USER_NAME -p $USER_PASSWORD -V $VHOST_NAME \ get queue=$QUEUE_NAME ``` ## III. Config a single access point and failover with keepalived To set up Keepalived with RabbitMQ cluster, follow these steps: ### **1. Install Keepalived on all nodes in the RabbitMQ cluster:** ``` $ sudo apt-get install keepalived ``` ### **2. Edit the Keepalived configuration file** `/etc/keepalived/keepalived.conf` on each node to include the virtual IP address and the RabbitMQ cluster nodes: ``` global_defs { router_id rabbit1 } vrrp_script chk_rabbitmq { script "/usr/local/bin/rabbitmq-check" interval 2 } vrrp_instance VI_1 { state MASTER interface ens3 virtual_router_id 51 priority 101 authentication { auth_type PASS auth_pass rabbitmq } virtual_ipaddress { 10.248.20.100 } track_script { chk_rabbitmq } } ``` Replace `rabbit1` with a unique router ID on each node. Modify `interface` and `virtual_ipaddress` values as appropriate for your environment. **Important**: If all three servers in a Keepalived configuration have the same priority number, Keepalived will not be able to determine which server should be the master. This can result in conflicts and instability in the cluster --> **Increase the proirity for each node** ``` ## rabbit1: priority 101 ## rabbit2: priority 102 ## rabbit3: priority 103 ## In this sequence, the master ip will likely fallback from rabbit-3 --> rabbit-2 --> rabbit-1 ``` ### **3. Create the `rabbitmq-check` script on each node with the following content:** ``` #!/bin/bash # RabbitMQ check script for Keepalived # # Check if the RabbitMQ service is running and reachable # Define the RabbitMQ host and port RABBITMQ_HOST="localhost" RABBITMQ_PORT="5672" # Check RabbitMQ status sudo rabbitmqctl status 2>&1 >/dev/null # Check the exit status of command if [ $? -eq 0 ]; then exit 0 else exit 1 fi ``` > **Future** Need to modify this script to check with a real rabbitmq client Make the script executable: ``` $ sudo chmod +x /usr/local/bin/rabbitmq-check ``` ### **4. Restart the Keepalived service on all nodes:** ``` $ sudo service keepalived restart ``` Now, you should have Keepalived running with a virtual IP address that will move between the nodes in the RabbitMQ cluster if one of them goes down. ### **5. Tesing keepalive IP** Use the command below to test the connectivity with the keepalive IP while stopping `rabbitmq-server` in each node ``` while true; do sudo rabbitmqadmin --host 10.248.20.100 -u $USER_NAME -p $USER_PASSWORD -V $VHOST_NAME get queue=$QUEUE_NAME; done ``` Now we can use the IP 10.248.20.100 as a signle access point for our RabbitMQ ## IV. Load balance with a single access point and failover with keepalived To maximize resource utilization in a highly available RabbitMQ cluster, you can employ a load-balancing setup with Keepalived. This design ensures that traffic is distributed across multiple servers, allowing for efficient utilization of resources. ``` git clone https://github.com/bloomberg/amqpprox.git cd amqpprox/ sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt install gcc-10 gcc-10-base gcc-10-doc g++-10 -y sudo apt install libstdc++-10-dev libstdc++-10-doc -y sudo apt-get install make cmake -y sudo apt install python3-pip pip install conan==1.59 conan profile detect make setup make init make ```