VMware Tanzu RabbitMQ 4.2のRPMパッケージをRocky Linuxにインストールするメモ

以下の手順では、VMware Tanzu RabbitMQのRPMパッケージをRocky Linux 9にインストールし、3台のクラスタを構成します。

ホスト名はrmq-1rmq-2rmq-3とします。また、以下の手順ではファイアウォールが無効になっている前提としますが、必要であれば以下のTCPポートを開放してください。

ポート 用途
4369 epmd (Erlang Port Mapper Daemon)
5672 AMQP (平文)
5671 AMQPS (TLS)
15672 HTTP (Management UI)
15671 HTTPS (Management UI)
25672 Erlang distribution
35672-35682 CLI tools

目次

VMware Tanzu RabbitMQのダウンロード

Broadcom Supportにログインして、VMware Tanzu RabbitMQのダウンロードページにアクセスします。

最新バージョンを選択します。この手順書では4.2.5を使用します。

image

"I agree to the Terms and Conditions"にチェック(要リンククリック)を入れて、

image

EL9用のインストーラーを~/Downloadsなどにダウンロードします。

image

(必要であれば)rpmに含まれるファイルを確認します。

rpm -qlp tanzu-rabbitmq-server-4.2.5-1.el9.x86_64.rpm

Tanzu RabbitMQのインストール

このセクションでの作業は rmq-1 上で行います。

インストール作業に使用する、あるいは作業に便利なパッケージをインストールします。

sudo dnf install -y wget lsof less vim

RabbitMQに必要なErlangのRPMパッケージをダウンロードします。

wget https://github.com/rabbitmq/erlang-rpm/releases/download/v27.3.4.10/erlang-27.3.4.10-1.el9.x86_64.rpm

Tanzu RabbitMQと依存パッケージをインストールします。

sudo dnf install -y logrotate erlang-27.3.4.10-1.el9.x86_64.rpm tanzu-rabbitmq-server-4.2.5-1.el9.x86_64.rpm

インストールされたパッケージのバージョンを確認します。

$ rpm -qa | grep -E 'erlang|rabbitmq'
erlang-27.3.4.10-1.el9.x86_64
tanzu-rabbitmq-server-4.2.5-1.el9.x86_64

$ sudo rabbitmqctl --version
4.2.5

Tanzu RabbitMQのサービスを有効化し、サービスを起動します。

sudo systemctl enable tanzu-rabbitmq-server
sudo systemctl start tanzu-rabbitmq-server

Tanzu RabbitMQサービスの状態を確認します。Started Tanzu RabbitMQ server.が出力されていることを確認してください。

$ systemctl status tanzu-rabbitmq-server | cat
● tanzu-rabbitmq-server.service - Tanzu RabbitMQ server
     Loaded: loaded (/usr/lib/systemd/system/tanzu-rabbitmq-server.service; enabled; preset: disabled)
    Drop-In: /run/systemd/system/service.d
             └─zzz-lxc-service.conf
     Active: active (running) since Thu 2026-04-16 16:19:43 JST; 11s ago
   Main PID: 1632 (beam.smp)
      Tasks: 52 (limit: 617192)
     Memory: 198.1M (peak: 235.4M)
        CPU: 4.063s
     CGroup: /system.slice/tanzu-rabbitmq-server.service
             ├─1632 /usr/lib64/erlang/erts-15.2.7.7/bin/beam.smp -W w -MBas ageffcbf -MHas ageffcbf -MBlmbcs 512 -MHlmbcs 512 -MMmcs 30 -pc unicode -P 1048576 -t 5000000 -stbt db -zdbbl 128000 -sbwt none -sbwtdcpu none -sbwtdio none -- -root /usr/lib64/erlang -bindir /usr/lib64/erlang/erts-15.2.7.7/bin -progname erl -- -home /var/lib/rabbitmq -- -pa "" -noshell -noinput -s rabbit boot -boot start_sasl -syslog logger "[]" -syslog syslog_error_logger false -kernel prevent_overlapping_partitions false --
             ├─1645 erl_child_setup 32768
             ├─1692 /usr/lib64/erlang/erts-15.2.7.7/bin/inet_gethost 4
             ├─1693 /usr/lib64/erlang/erts-15.2.7.7/bin/inet_gethost 4
             └─1696 /bin/sh -s rabbit_disk_monitor

Apr 16 16:19:41 rmq-1 rabbitmq-server[1632]:   Doc guides:  https://www.rabbitmq.com/docs
Apr 16 16:19:41 rmq-1 rabbitmq-server[1632]:   Support:     https://www.rabbitmq.com/docs/contact
Apr 16 16:19:41 rmq-1 rabbitmq-server[1632]:   Tutorials:   https://www.rabbitmq.com/tutorials
Apr 16 16:19:41 rmq-1 rabbitmq-server[1632]:   Monitoring:  https://www.rabbitmq.com/docs/monitoring
Apr 16 16:19:41 rmq-1 rabbitmq-server[1632]:   Upgrading:   https://www.rabbitmq.com/docs/upgrade
Apr 16 16:19:41 rmq-1 rabbitmq-server[1632]:   Logs: /var/log/rabbitmq/rabbit@rmq-1.log
Apr 16 16:19:41 rmq-1 rabbitmq-server[1632]:         <stdout>
Apr 16 16:19:41 rmq-1 rabbitmq-server[1632]:   Config file(s): (none)
Apr 16 16:19:43 rmq-1 rabbitmq-server[1632]:   Starting broker... completed with 0 plugins.
Apr 16 16:19:43 rmq-1 systemd[1]: Started Tanzu RabbitMQ server.

リッスンしているポートを確認します。

$ sudo lsof -n -i -P | grep -i listen | grep rabbitmq
beam.smp 1632 rabbitmq   24u  IPv4 32113044      0t0  TCP *:25672 (LISTEN)
beam.smp 1632 rabbitmq   39u  IPv6 32116046      0t0  TCP *:5672 (LISTEN)

RabbitMQに対してpingが通ることを確認します。

$ sudo rabbitmq-diagnostics ping
Will ping rabbit@rmq-1. This only checks if the OS process is running and registered with epmd. Timeout: 60000 ms.
Ping succeeded

rmq-1をクローンして、rmq-2とrmq-3を作成

ここまで作業した内容を rmq-2rmq-3 にも適用します。 rmq-1 VMをクローンして rmq-2rmq-3 を作ると良いでしょう。もし、 rmq-2rmq-3 も最初から構築する場合は rmq-1/var/lib/rabbitmq/.erlang.cookie の内容をコピーして rmq-2rmq-3 の起動前に配置してください。

$ sudo cat /var/lib/rabbitmq/.erlang.cookie
QQFAJVSPYEVMCQLYCPTH

rmq-1rmq-2rmq-3 のIPアドレスとホスト名を全ノードの /etc/hosts に記入してください。以下は例です。事前に決めた固定IPアドレスを使う場合は rmq-1 の複製時点で作成しておくと良いでしょう。

cat <<EOF | sudo tee -a /etc/hosts
192.168.139.169 rmq-1
192.168.139.101 rmq-2
192.168.139.245 rmq-3
EOF

RabbitMQクラスタの作成

rmq-2rmq-3 上で次のコマンドを実行し、 rmq-1 のクラスタに参加します。

sudo rabbitmqctl join_cluster rabbit@rmq-1

Warning

旧バージョンのRabbitMQの場合は、クラスタのセットアップに追加の手順が必要です。

以下のコマンドは任意のノード上で実行してください。

次のコマンドでクラスタの状態を確認します。3台のノードが表示されていることを確認してください。

$ sudo rabbitmqctl cluster_status
Cluster status of node rabbit@rmq-1 ...
Basics

Cluster name: rabbit@rmq-1
Total CPU cores available cluster-wide: 48

Cluster Tags

(none)

Disk Nodes

rabbit@rmq-1
rabbit@rmq-2
rabbit@rmq-3

Running Nodes

rabbit@rmq-1
rabbit@rmq-2
rabbit@rmq-3

Versions

rabbit@rmq-1: Tanzu RabbitMQ 4.2.5 on Erlang 27.3.4.10
rabbit@rmq-2: Tanzu RabbitMQ 4.2.5 on Erlang 27.3.4.10
rabbit@rmq-3: Tanzu RabbitMQ 4.2.5 on Erlang 27.3.4.10

CPU Cores

Node: rabbit@rmq-1, available CPU cores: 16
Node: rabbit@rmq-2, available CPU cores: 16
Node: rabbit@rmq-3, available CPU cores: 16

Maintenance status

Node: rabbit@rmq-1, status: not under maintenance
Node: rabbit@rmq-2, status: not under maintenance
Node: rabbit@rmq-3, status: not under maintenance

Alarms

(none)

Network Partitions

(none)

Listeners

Node: rabbit@rmq-1, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@rmq-1, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Node: rabbit@rmq-2, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@rmq-2, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Node: rabbit@rmq-3, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@rmq-3, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0

Feature flags

Flag: classic_mirrored_queue_version, state: enabled
Flag: classic_queue_type_delivery_support, state: enabled
Flag: direct_exchange_routing_v2, state: enabled
Flag: feature_flags_v2, state: enabled
Flag: implicit_default_bindings, state: enabled
Flag: khepri_db, state: enabled
Flag: listener_records_in_ets, state: enabled
Flag: maintenance_mode_status, state: enabled
Flag: message_containers, state: enabled
Flag: message_containers_deaths_v2, state: enabled
Flag: quorum_queue, state: enabled
Flag: quorum_queue_non_voters, state: enabled
Flag: rabbit_exchange_type_local_random, state: enabled
Flag: rabbitmq_4.0.0, state: enabled
Flag: rabbitmq_4.1.0, state: enabled
Flag: rabbitmq_4.2.0, state: enabled
Flag: restart_streams, state: enabled
Flag: stream_filtering, state: enabled
Flag: stream_queue, state: enabled
Flag: stream_sac_coordinator_unblock_group, state: enabled
Flag: stream_single_active_consumer, state: enabled
Flag: stream_update_config_command, state: enabled
Flag: tracking_records_in_ets, state: enabled
Flag: user_limits, state: enabled
Flag: virtual_host_metadata, state: enabled

(任意で) クラスタ名を rabbit@rmq-1 から rmq-cluster に変更します。

sudo rabbitmqctl set_cluster_name rmq-cluster

変更されたことを確認します。

$ sudo rabbitmqctl cluster_status | grep "Cluster name:"
Cluster name: rmq-cluster

admin ユーザーを作成します。初期状態で設定されている guest ユーザーは localhost からのみ利用可能です。

sudo rabbitmqctl add_user admin 'VMware1!'
sudo rabbitmqctl set_user_tags admin administrator
sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"

ユーザー一覧を確認します。

$ sudo rabbitmqctl list_users
Listing users ...
user	tags
admin	[administrator]
guest	[administrator]

(任意で) guest ユーザーを削除します。

sudo rabbitmqctl delete_user guest

Management Pluginの有効化

次のコマンドを各ノード上で実行し、RabbitMQのManagement Pluginを有効化します。

sudo rabbitmq-plugins enable rabbitmq_management

リッスンしているポートを確認して15672が追加されたことを確認します。

$ sudo lsof -n -i -P | grep -i listen | grep rabbitmq
beam.smp 1632 rabbitmq   24u  IPv4 32113044      0t0  TCP *:25672 (LISTEN)
beam.smp 1632 rabbitmq   39u  IPv6 32116046      0t0  TCP *:5672 (LISTEN)
beam.smp 1632 rabbitmq   43u  IPv4 32195644      0t0  TCP *:15672 (LISTEN)

いずれかのノードのIPの15672ポートにブラウザでアクセスし、 admin ユーザーでログインします。次のような画面が表示されます。

image

初回は"⚠ All stable feature flags must be enabled after completing an upgrade."という警告が出ます。

新機能を有効にするfeature flagをONにします。

# stdin を /dev/null にリダイレクトしてTTY 判定を回避する
sudo rabbitmqctl enable_feature_flag all < /dev/null

警告が消えたことを確認します。

image

動作確認

簡単なPythonプログラムで動作確認します。

python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install pika

次の rabbitmq_cluster_check.py を作成してください。

#!/usr/bin/env python3
"""
RabbitMQ クラスタ動作確認スクリプト

- クラスタ内の任意のノードに接続 (フェイルオーバー)
- Quorum Queue を作成
- 指定数のメッセージを Publish
- 同じキューから Consume し、件数・内容を検証
- 成功時 exit 0 / 失敗時 exit 1

必要なパッケージ:
    pip install pika

実行例 (TLS あり):
    python3 rabbitmq_cluster_check.py \
        --hosts rabbit01,rabbit02,rabbit03 \
        --port 5671 \
        --user admin --password 'YOUR_PASSWORD' \
        --ca /etc/rabbitmq/certs/ca.crt \
        --count 5 --cleanup

実行例 (TLS なし):
    python3 rabbitmq_cluster_check.py \
        --hosts rabbit01,rabbit02,rabbit03 \
        --port 5672 --no-tls \
        --user admin --password 'YOUR_PASSWORD' \
        --count 5 --cleanup
"""

import argparse
import ssl
import sys
import time
import uuid

import pika


def build_params(hosts, port, vhost, user, password,
                 use_tls, ca_file, skip_verify):
    credentials = pika.PlainCredentials(user, password)

    ssl_context = None
    if use_tls:
        ssl_context = ssl.create_default_context(cafile=ca_file)
        if skip_verify:
            ssl_context.check_hostname = False
            ssl_context.verify_mode = ssl.CERT_NONE

    params_list = []
    for host in hosts:
        kwargs = dict(
            host=host,
            port=port,
            virtual_host=vhost,
            credentials=credentials,
            connection_attempts=2,
            retry_delay=1,
            socket_timeout=10,
            heartbeat=30,
        )
        if use_tls:
            kwargs["ssl_options"] = pika.SSLOptions(ssl_context, server_hostname=host)
        params_list.append(pika.ConnectionParameters(**kwargs))
    return params_list


def connect_with_failover(params_list):
    last_err = None
    for params in params_list:
        try:
            conn = pika.BlockingConnection(params)
            print(f"[OK]   Connected to {params.host}:{params.port}")
            return conn
        except Exception as e:
            print(f"[WARN] Failed to connect to {params.host}: {e}")
            last_err = e
    raise RuntimeError(f"All nodes unreachable. Last error: {last_err}")


def main():
    p = argparse.ArgumentParser(description="RabbitMQ cluster sanity check")
    p.add_argument("--hosts", default="rabbit01,rabbit02,rabbit03",
                   help="comma-separated hostnames (default: rabbit01,rabbit02,rabbit03)")
    p.add_argument("--port", type=int, default=5671,
                   help="AMQP port (default: 5671 for TLS, use 5672 for plain)")
    p.add_argument("--vhost", default="/", help="vhost (default: /)")
    p.add_argument("--user", default="admin", help="username (default: admin)")
    p.add_argument("--password", required=True, help="password")
    p.add_argument("--queue", default="test.quorum.check",
                   help="queue name (default: test.quorum.check)")
    p.add_argument("--count", type=int, default=5, help="number of messages (default: 5)")
    p.add_argument("--no-tls", action="store_true", help="disable TLS")
    p.add_argument("--ca", default="/etc/rabbitmq/certs/ca.crt",
                   help="CA certificate path for TLS")
    p.add_argument("--skip-verify", action="store_true",
                   help="skip TLS hostname/cert verification (NOT for production)")
    p.add_argument("--cleanup", action="store_true",
                   help="delete queue after test")
    args = p.parse_args()

    hosts = [h.strip() for h in args.hosts.split(",") if h.strip()]
    use_tls = not args.no_tls

    print("=" * 60)
    print(f" Target:     {hosts} port={args.port} vhost={args.vhost}")
    print(f" User:       {args.user}")
    print(f" Queue:      {args.queue} (quorum)")
    print(f" Messages:   {args.count}")
    print(f" TLS:        {'enabled (CA=' + args.ca + ')' if use_tls else 'disabled'}")
    print("=" * 60)

    params_list = build_params(
        hosts=hosts, port=args.port, vhost=args.vhost,
        user=args.user, password=args.password,
        use_tls=use_tls, ca_file=args.ca, skip_verify=args.skip_verify,
    )

    # ---- Connect (with failover) ----
    connection = connect_with_failover(params_list)
    channel = connection.channel()
    channel.confirm_delivery()  # Publisher Confirms 有効化

    # ---- Declare Quorum Queue ----
    print(f"[INFO] Declaring quorum queue: {args.queue}")
    channel.queue_declare(
        queue=args.queue,
        durable=True,
        arguments={"x-queue-type": "quorum"},
    )

    # ---- Publish ----
    run_id = uuid.uuid4().hex[:8]
    print(f"[INFO] Publishing {args.count} messages (run_id={run_id})")
    sent = []
    for i in range(1, args.count + 1):
        body = f"[{run_id}] msg-{i:03d} ts={int(time.time())}"
        channel.basic_publish(
            exchange="",
            routing_key=args.queue,
            body=body.encode("utf-8"),
            properties=pika.BasicProperties(
                delivery_mode=2,          # persistent
                content_type="text/plain",
            ),
            mandatory=True,
        )
        sent.append(body)
        print(f"  -> SENT {body}")

    # ---- Consume ----
    print(f"[INFO] Consuming up to {args.count} messages")
    received = []
    # 今回送ったメッセージだけを対象にする (run_id でフィルタ)
    for _ in range(args.count * 2):  # 余裕をもってループ
        method, _, body = channel.basic_get(queue=args.queue, auto_ack=False)
        if method is None:
            break
        msg = body.decode("utf-8")
        if run_id in msg:
            received.append(msg)
            channel.basic_ack(delivery_tag=method.delivery_tag)
            print(f"  <- RECV {msg}")
        else:
            # 別 run_id のメッセージは requeue
            channel.basic_nack(delivery_tag=method.delivery_tag, requeue=True)
        if len(received) == args.count:
            break

    # ---- Verify ----
    missing = set(sent) - set(received)
    success = (len(sent) == len(received)) and not missing

    print("-" * 60)
    print(f" Sent:     {len(sent)}")
    print(f" Received: {len(received)}")
    if missing:
        print(f" Missing:  {len(missing)}")
        for m in sorted(missing):
            print(f"   - {m}")
    print("-" * 60)

    # ---- Cleanup ----
    if args.cleanup:
        print(f"[INFO] Deleting queue: {args.queue}")
        channel.queue_delete(queue=args.queue)

    connection.close()

    if success:
        print("[PASS] RabbitMQ cluster check succeeded.")
        sys.exit(0)
    else:
        print("[FAIL] RabbitMQ cluster check failed.")
        sys.exit(1)


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("[ABORT] Interrupted by user.")
        sys.exit(130)
    except Exception as e:
        print(f"[ERROR] {e}")
        sys.exit(1)

スクリプトを実行します。

python rabbitmq_cluster_check.py --hosts rmq-1,rmq-2,rmq-3 --port 5672 --user admin --password 'VMware1!' --count 5 --no-tls --cleanup

次のような出力になればOKです。

============================================================
 Target:     ['rmq-1', 'rmq-2', 'rmq-3'] port=5672 vhost=/
 User:       admin
 Queue:      test.quorum.check (quorum)
 Messages:   5
 TLS:        disabled
============================================================
[OK]   Connected to rmq-1:5672
[INFO] Declaring quorum queue: test.quorum.check
[INFO] Publishing 5 messages (run_id=0fb619ec)
  -> SENT [0fb619ec] msg-001 ts=1776328534
  -> SENT [0fb619ec] msg-002 ts=1776328534
  -> SENT [0fb619ec] msg-003 ts=1776328534
  -> SENT [0fb619ec] msg-004 ts=1776328534
  -> SENT [0fb619ec] msg-005 ts=1776328534
[INFO] Consuming up to 5 messages
  <- RECV [0fb619ec] msg-001 ts=1776328534
  <- RECV [0fb619ec] msg-002 ts=1776328534
  <- RECV [0fb619ec] msg-003 ts=1776328534
  <- RECV [0fb619ec] msg-004 ts=1776328534
  <- RECV [0fb619ec] msg-005 ts=1776328534
------------------------------------------------------------
 Sent:     5
 Received: 5
------------------------------------------------------------
[PASS] RabbitMQ cluster check succeeded.