はじめに
MQTTブローカー「EMQX」は、スケーラビリティと高可用性を重視した設計になっており、クラスタリング機能を備えています。
本記事では、Docker環境上でEMQXのクラスタリングを試す手順を紹介します。
参考
検証環境
今回使用したVM(Proxmox上)の構成は以下の通りです:
項目 | 内容 |
---|---|
RAM | 16.00 GiB |
CPU | 8コア(1ソケット、8コア) [x86-64-v2-AES] |
OS | Ubuntu 24.04.2 LTS |
この環境上でDockerとDocker Composeを使用してEMQXクラスタを構築します。
使用ツール・バージョン
- Ubuntu Server 24.04.2
- Docker 28.0.4
- Docker Compose v2.34.0
- EMQX 5.8.6(今回はオープンソース版を使用)
構成概要
以下のような2ノード構成でEMQXクラスタを構築します。
-
emqx2-1
(EMQXノード) -
emqx2-2
(EMQXノード)
同一ネットワーク内で2ノードが相互にクラスタリングされ、どのノードに接続してもメッセージが共有される構成です。
0. UbuntuにDocker Engineをインストールする
以下は公式ドキュメントより引用
URL:https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository
-
Set up Docker's apt repository.
# Add Docker's official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to Apt sources: echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update
-
Install the Docker packages.(Latest)
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
-
Verify that the installation is successful by running the hello-world image:
sudo docker run hello-world
This command downloads a test image and runs it in a container. When the container runs, it prints a confirmation message and exits.
-
ユーザーをdockerグループに追加する
sudo gpasswd -a hogehoge docker
1. Docker Compose構成
EMQXの公式Dockerイメージ(emqx/emqx:latest)を使用し、クラスタをDocker Composeで構築します。
以下は、2ノード(emqx2-1
, emqx2-2
)間でクラスタリングを行う基本構成例です。必要に応じてノード数を拡張してください。
version: '3'
services:
emqx1:
container_name: emqx2-1 # ※公式ドキュメントには書かれてないが、識別しやすくするために明示的に指定
image: emqx/emqx:latest
environment:
- "EMQX_NAME=emqx" # ノード名のプレフィックス(クラスタリングに使用)
- "EMQX_HOST=node1.emqx.io" # クラスタ内で一意のホスト名
- "EMQX_CLUSTER__DISCOVERY_STRATEGY=static"
- "EMQX_CLUSTER__STATIC__SEEDS=[emqx@node1.emqx.io, emqx@node2.emqx.io]"
networks:
emqx-bridge:
aliases:
- node1.emqx.io
emqx2:
container_name: emqx2-2 # ※こちらも同様に補助的に付与
image: emqx/emqx:latest
environment:
- "EMQX_NAME=emqx"
- "EMQX_HOST=node2.emqx.io"
- "EMQX_CLUSTER__DISCOVERY_STRATEGY=static"
- "EMQX_CLUSTER__STATIC__SEEDS=[emqx@node1.emqx.io, emqx@node2.emqx.io]"
networks:
emqx-bridge:
aliases:
- node2.emqx.io
networks:
emqx-bridge:
driver: bridge
2. 2つのノードを起動
先ほど作成したdocker-compose.yml
を使用して、EMQXクラスタノード(emqx2-1
, emqx2-2
)を起動します。
docker compose -p my_emqx_broker2 up -d
公式ドキュメントで使用されているdocker-compose
(ハイフンあり)は旧バージョンのコマンド形式であり、Docker Compose v2以降ではdocker compose
(ハイフンなし)が推奨されています。
正常に起動しているかどうかを確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd0c84955d0f emqx/emqx:latest "/usr/bin/docker-ent…" 33 hours ago Up 33 hours 1883/tcp, 4370/tcp, 5369/tcp, 8083-8084/tcp, 8883/tcp, 18083/tcp emqx2-1
8de033b356b6 emqx/emqx:latest "/usr/bin/docker-ent…" 33 hours ago Up 33 hours 1883/tcp, 4370/tcp, 5369/tcp, 8083-8084/tcp, 8883/tcp, 18083/tcp emqx2-2
いずれかのノード内でemqx_ctl
コマンドを実行し、クラスタリングが成功しているかを確認します。
$ docker exec -it emqx2-1 sh -c "emqx_ctl cluster status"
Cluster status: #{running_nodes => ['emqx@node1.emqx.io','emqx@node2.emqx.io'],
stopped_nodes => []}
running_nodes
に2つのノードが表示されていれば、クラスタが正常に構成されている状態です。
3. MQTTクライアントを使用して動作確認
クラスタ構成が正しく動作しているか確認するために、MQTTクライアントとしてefrecon/mqtt-clientを使用します。このコンテナイメージにはmosquitto_sub
およびmosquitto_pub
が含まれており、簡単にMQTTメッセージの送受信を試すことができます。
-
Subscriberを起動(
node2.emqx.io
に接続)
まず、node2.emqx.io
をホストとするSubscriberを起動し、emqx/test
トピックを購読します。$ docker run -it --rm \ --name sub \ --network my_emqx_broker2_emqx-bridge \ efrecon/mqtt-client \ sub -h node2.emqx.io -t "emqx/test"
-
Publisherを起動(
node1.emqx.io
に接続)
別のターミナルから、node1.emqx.io
に接続し、同じトピックにメッセージを送信します。$ docker run --rm \ --name pub \ --network my_emqx_broker2_emqx-bridge \ efrecon/mqtt-client \ pub -h node1.emqx.io -t "emqx/test" -m "Hello from publisher"
-
メッセージが届いているか確認
Subscriberの出力に以下のようなメッセージが表示されていれば、クラスタリングが正しく機能しています。Hello from publisher
このように、別ノード間でメッセージの送受信ができていることから、EMQXクラスタ構成が正常に機能していることが確認できます。
通信の流れをパケットキャプチャで確認(おまけ)
Wiresharkを使用して、EMQXクラスタ構成におけるメッセージの通信経路をパケットキャプチャで可視化しました。
以下はその一連の流れです。(ssh越しにDockerのネットワークをキャプチャしています。※この方法については、今後また紹介予定です)
今回のネットワーク構成は以下のようになります。
-
Publisherから
node1.emqx.io
へのメッセージ送信- 送信元IP:172.20.0.5(Publishier)
- 宛先IP:172.20.0.3(
node1.emqx.io
)
MQTT Publishパケット:
- TCPポート: 1883
- Topic: emqx/test
- Payload: "Hello from publisher"
-
node1.emqx.io
からnode2.emqx.io
へのクラスタ間転送- EMQXノード間のクラスタ通信には、デフォルトでTCPポート
5369
(Docker環境の場合)が使用されます。 - 送信元IP:172.20.0.3(
node1.emqx.io
) - 宛先IP:172.20.0.2(
node2.emqx.io
)
- EMQXノード間のクラスタ通信には、デフォルトでTCPポート
-
node2.emqx.io
からSubscriberにメッセージを送信- 送信元IP:172.20.0.2(node2.emqx.io)
- 宛先IP:172.20.0.4(Subscriber)
まとめ
今回は、Docker Composeを用いたEMQXクラスタ構築および動作確認までの流れを解説しました。
今後はEMQXクラスタにおけるルーティングの仕組みを調査します。