Skip to content

Instantly share code, notes, and snippets.

@shichi-at-nttr
Last active August 18, 2023 11:21
Show Gist options
  • Save shichi-at-nttr/9d358dcaeda2e0729f02f4a45f4c63b8 to your computer and use it in GitHub Desktop.
Save shichi-at-nttr/9d358dcaeda2e0729f02f4a45f4c63b8 to your computer and use it in GitHub Desktop.
Consul環境下でのRabbitMQのクラスタ構築

Consul環境下でのRabbitMQのクラスタ構築

目的

  • /etc/hosts を書かずにRabbitMQのクラスタを構築したい
  • ansibleを使ってクラスタ化まで実行したい

前提

  • RabbitMQの各ホストがConsulで名前解決できる状態にある   - 例えば node01.node.consulnode02.node.consul として個別ホストにアクセスできる
    • サービスとしては rabbitmq.service.consul としてアクセスできる
    • dnsmasqを利用し、シームレスに名前解決できる

課題

普通にRabbitMQを構成すると、RabbitMQノード名はホスト名を用いて rabbit@node01 のように自動設定される。 非クラスタ環境ではこれで問題ないが、 この場合、クラスタを組む際には node01 が名前解決できなければならない。

具体的には

rabbitmqctl join_cluster rabbit@node01

のステップで node01 が名前解決できずに失敗する

とはいえ、

rabbitmqctl join_cluster rabbit@node01.node.consul

とすると、consul+dnsmasqにより node01.node.consul は名前解決できるが、 対向側のRabbitMQが rabbit@node01 の名前で起動しているので ノード名がマッチせず、ジョインに失敗する。

採用したくない解決策

ここで node01 が名前解決できればよいことから、 /etc/hosts に記述すれば解決する。

最低限、RabbitMQのマスタノードを記載すれば良い。

しかし、consulを用いてhostsファイルを使わずに構築した環境なので、 このためだけにhostsを書くのは避けたい。

解決策

次の方針で解決する。

  1. RabbitMQのデフォルトのノード名を用いない
  2. ノードのドメインは「長いもの」を使う

以上をRabbitMQの設定ファイル /etc/rabbitmq/rabbitmq-env.conf に記載することで対処する。

具体的な設定項目は

  1. NODENAME=rabbit@node01.node.consul
  2. USE_LONGNAME=true

その他注意点

ノード名の変更はrabbitmq-server起動中に実行してはならない。 (ノード名不一致で rabbitmqctl が実行できなくなる)

rabbitmqctl stop_app
systemctl stop rabbitmq-server
vi /etc/rabbitmq/rabbitmq-env.conf でノード名を変更する
systemctl start rabbitmq-server

の順で実行する。

---
all:
vars:
ansible_python_interpreter: /usr/bin/python3
mqnodes:
hosts:
node01: # ひとつめがマスターノード
node02:
node03:
---
# RabbitMQクラスタ構築
# グループ「mqnodes」にRabbitMQ各ノードを定義しておく。
# すでに各ノードにRabbitMQがインストール済みである前提。
# 1. スレーブノード(=非マスター)停止
# 2. マスタの.erlang.cookieファイルをスレーブにコピー
# 3. スレーブノードをクラスタに参加させる
# 4. スレーブノード起動
# 5. キューのミラーリングポリシーを設定
- hosts: mqnodes
become: yes
tasks:
# スレーブノードを停止する
- name: rabbitmq-cluster | stop @ slave
command: rabbitmqctl stop_app
when: inventory_hostname != groups['mqnodes'][0]
- name: rabbitmq-cluster | reset @ slave
command: rabbitmqctl reset
when: inventory_hostname != groups['mqnodes'][0]
- name: rabbitmq-cluster | stop RabbitMQ service @ slave
systemd: state=stopped name=rabbitmq-server
when: inventory_hostname != groups['mqnodes'][0]
# マスタノードの.erlang.cookieをスレーブノードにコピーする
- name: rabbitmq-cluster | capture .erlang.cookie @ master
command: cat /var/lib/rabbitmq/.erlang.cookie
register: rabbitmq_erlang_cookie
when: inventory_hostname == groups['mqnodes'][0]
- debug: var=hostvars[groups['mqnodes'][0]].rabbitmq_erlang_cookie.stdout
- name: rabbitmq-cluster | copy .erlang.cookie @ slave
copy:
backup: no
dest: /var/lib/rabbitmq/.erlang.cookie
content: |
{{ hostvars[groups['mqnodes'][0]].rabbitmq_erlang_cookie.stdout }}
owner: rabbitmq
group: rabbitmq
mode: 0400
when: inventory_hostname != groups['mqnodes'][0]
# スレーブノード再起動・リセット
- name: rabbitmq-cluster | send sigterm @ slave
shell: pkill -u rabbitmq || true
when: inventory_hostname != groups['mqnodes'][0]
- name: rabbitmq-cluster | restart @ slave
systemd: state=restarted name=rabbitmq-server
when: inventory_hostname != groups['mqnodes'][0]
# スレーブノードをクラスタに参加させる (stop-reset-join)
- name: rabbitmq-cluster | stop_app @ slave
command: rabbitmqctl stop_app
when: inventory_hostname != groups['mqnodes'][0]
- name: rabbitmq-cluster | reset @ slave
command: rabbitmqctl reset
when: inventory_hostname != groups['mqnodes'][0]
- name: rabbitmq-cluster | join to cluster @ slave
command: rabbitmqctl join_cluster "rabbit@{{ groups['mqnodes'][0] }}.node.consul"
when: inventory_hostname != groups['mqnodes'][0]
# スレーブノード起動
- name: rabbitmq-cluster | start_app @ slave
command: rabbitmqctl start_app
when: inventory_hostname != groups['mqnodes'][0]
# クラスタ名変更
- name: rabbitmq-cluster | change cluster name @ master
command: rabbitmqctl set_cluster_name "rabbit@cluster"
when: inventory_hostname == groups['mqnodes'][0]
# キューのミラーリングポリシーを設定 (全ノードで同期する)
- name: rabbitmq-cluster | set mirroring policy @ master
rabbitmq_policy:
node: "rabbit@{{ inventory_hostname }}.node.consul"
name: HA
pattern: .*
tags:
ha-mode: all
when: inventory_hostname == groups['mqnodes'][0]
---
# RabbitMQ本体のインストール
- name: import RabbitMQ-repo GPG Keys
apt_key: keyserver="hkps.pool.sks-keyservers.net" id="6B73A36E6026DFCA"
- name: add RabbitMQ apt repository
apt_repository:
repo: "deb http://www.rabbitmq.com/debian/ testing main"
state: present
- name: install RabbitMQ
apt: name=rabbitmq-server state=present
# クラスタリング用に設定ファイル調整する
# (ノード名をFQDNで扱うようにする)
- name: create conf file
copy:
dest: /etc/rabbitmq/rabbitmq-env.conf
content: |
USE_LONGNAME=true
NODENAME=rabbit@{{ inventory_hostname }}.node.consul
- name: enable RabbitMQ WebUI
rabbitmq_plugin: name=rabbitmq_management state=enabled
# 再起動してノード名変更を有効化
- name: daemon-reload
command: systemctl daemon-reload
- name: restart RabbitMQ service
systemd: state=restarted name=rabbitmq-server enabled=yes
# 管理画面用のユーザ
- name: make RabbitMQ user
rabbitmq_user:
node: "rabbit@{{ inventory_hostname }}.node.consul"
user: admin
password: "{{ rabbitmq_admin_password }}"
vhost: /
configure_priv: .*
read_priv: .*
write_priv: .*
tags: administrator
state: present
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment