0
1

RabbitMQのQueue関連の設定をRest APIを利用して自動化した時のメモ

Last updated at Posted at 2021-01-19

はじめに

Kubernetes(k8s)環境でHelmを利用してRabbitMQクラスターを稼動させています。
開発環境はDockerを利用しているのですが、マシンを変更する度に手動でQueueを設定するのは面倒になる場面が出てきたのでRest APIを利用することにしました。

公式ドキュメントにもrabbitmqadminなどのCLIツールは紹介されていますが、どうしても汎用性を持たせるためにどう使って良いか分からない、間違った設定をしてしまう、といった問題が発生しがちなので、自分のルールを強制させるためにはツールが必要です。

なおアプリケーション毎にVirtualHostを作成するなどのルールについての詳細は別の記事を参照してください。

また最後にも書いていますが、ここで説明しているコードはGitHub上で公開しています。

その他に実装のために参考にした資料は下記のとおりです。

参考資料

実行環境

  • Ubuntu 20.04.1 LTS amd64版
  • Ruby 2.7 (deb package)
    • httpclient (Gem package, bundlerを使用)
  • RabbitMQ Docker Container, rabbitmq:3.8.9-management

APIの概要

基本となる設定をJSON形式かYAML形式で準備し、コマンドの引数に指定します。

設定したい項目は次のとおりです。

  • Userの追加・削除
  • Virtual Hostの追加・削除・Permission設定
  • Exchangeの追加・削除・Bind設定
  • Queueの追加・削除

開発環境のセットアップ

Rubyと標準的なhttpclientを利用することにしたので環境設定は、Gemfileとbundlerを利用した、慣れた方法を取ります。

Gemfile
source 'https://rubygems.org'
gem "httpclient"
gem "json"
Makefile
.PHONY: setup clean

setup:
        bundle config set path lib
        bundle install

clean:
        ( find . -name '*~' -type f -exec rm {} \; -print )
        rm -rf lib/ruby
        rm -rf Gemfile.lock

bundle config setup path libを実行すると、ホームディレクトリ下の~/.bundle/configに設定が書き込まれます。
従来はbundle setup --path libのような記述をしていましたが、この場合はカレントディレクトリ下の./.bundle/configに設定が書き込まれます。
この違いは、Dockerコンテナなどを作成する際に注意が必要になる点ですので、bundle installしたライブラリが読み込めない場合には、~/.bundle/configが配置されているか、適切な内容か確認するようにしてください。

~/.bundle/configファイル
---
BUNDLE_PATH: "lib"

適当な作業用ディレクトリにこれらのファイルを配置してから、makeコマンドでライブラリを準備します。

$ make setup
bundle config set path lib 
bundle install
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using bundler 2.1.4
Fetching httpclient 2.8.3
Installing httpclient 2.8.3
Fetching json 2.5.1
Installing json 2.5.1 with native extensions
Bundle complete! 2 Gemfile dependencies, 3 gems now installed.
Bundled gems are installed into `./lib`

$ ls
Gemfile  lib/  Makefile

Dockerを利用したRabbitMQサーバーの起動

Docker公式イメージにはいくつかのTagが登録されていますが、Webブラウザから利用できるWeb Console UIを利用するためには、-managementがついているTag名を指定する必要があります。

rabbitmqコンテナの起動
$ sudo docker run -it --rm -d -p 5672:5672 -p 15672:15672 \
	--env RABBITMQ_ERLANG_COOKIE="secretcookie" \
	--env RABBITMQ_DEFAULT_USER="user" \
	--env RABBITMQ_DEFAULT_PASS="4eb4e543c5c27954" \
	--name rabbitmq  rabbitmq:3.8.9-management

Webブラウザからは http://localhost:15672/ 経由でアクセスできます。
オプションを指定しない時のデフォルトのID,Passwordは、guest,guest になっているので、ネットワーク接続を許す環境では RABBITMQ_DEFAULT_USER, RABBITMQ_DEFAULT_PASS で必ず変更するようにしてください。

RabbitMQ Management APIの利用

コンテナが起動すれば、Webブラウザから操作ができますが、ここからはRest APIを利用して必要な設定を行ないます。

テストとして、curlとjqコマンドを利用してAPIにアクセスできるかテストしてみます。

curlとjqコマンドによるAPIへの接続テスト
$ curl -u user:4eb4e543c5c27954 -H "Content-Type: application/json" http://localhost:15672/api/overview | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2417  100  2417    0     0  63605      0 --:--:-- --:--:-- --:--:-- 63605
{
  "management_version": "3.8.9",
  "rates_mode": "basic",
  "sample_retention_policies": {
    "global": [
      600,
      3600,
      28800,
      86400
...

ここから必ずBASIC認証を行なうこと、Content-Typeにapplication/jsonを指定することが分かります。
これでRabbitMQのバージョンなどは確認できたので、userやvirtual hostの作成・削除を行なう方法から探っていきます。

スクリプトによるUserの追加

Rubyを利用してUserを追加するスクリプト全体は次のようになりました。
ここではまだ実際に利用することを想定しておらず、前半に変数の定義をまとめている程度にとどめて、コードは後からリファクタリングすることにします。

rabbitmq-adduser.rb全体
#!/usr/bin/ruby
# coding: utf-8

## 共通の設定項目 (前半)
$: << "./lib"
require 'bundler/setup'
require 'json'
require 'httpclient'

RQ_USER = "user"
RQ_PASS = "4eb4e543c5c27954"
RQAPI_URLBASE = "http://127.0.0.1:15672/api"

## ここから固有の処理 (後半)
client = HTTPClient.new(:force_basic_auth => true)
rqapi_url = RQAPI_URLBASE + "/users/user01"
client.set_auth(rqapi_url, RQ_USER, RQ_PASS)

req = { :password => "secret", :tags => "administrator" }
resp = client.put(rqapi_url, req.to_json, "Content-Type" => "application/json")

Virtual Hostの追加

Userの追加とスクリプトの前半は同一なので、後半部分のみ掲載します。
VirtualHostには "/user01" を設定しています。

rabbitmq-addvhost.rbの後半部分
...

client = HTTPClient.new(:force_basic_auth => true)
rqapi_url = RQAPI_URLBASE + "/vhosts/%2fuser01"
client.set_auth(rqapi_url, RQ_USER, RQ_PASS)

resp = client.put(rqapi_url, nil, "Content-Type" => "application/json")

Permissionの設定

Virtual Host "/user01" に、"user01"ユーザーへのアクセス許可を設定します。

rabbitmq-addperm.rb後半部分抜粋
...

client = HTTPClient.new(:force_basic_auth => true)
rqapi_url = RQAPI_URLBASE + "/permissions/%2fuser01/user01"
client.set_auth(rqapi_url, RQ_USER, RQ_PASS)

ret = { :configure => ".*", :write => ".*", :read => ".*" }
resp = client.put(rqapi_url, ret.to_json, "Content-Type" => "application/json")

User, Virtual Host, Permissionの削除方法

基本的には"DELETE"を送信すれば良いはずです。BODYがなくても削除可能か確認してみます。

rabbitmq-delete-all.rb後半部分抜粋
...

client = HTTPClient.new(:force_basic_auth => true)
for url in ["/permissions/%2fuser01/user01", "/users/user01", "/vhosts/%2fuser01"]
  rqapi_url = RQAPI_URLBASE + url
  client.set_auth(rqapi_url, RQ_USER, RQ_PASS)
  resp = client.delete(rqapi_url, nil, "Content-Type" => "application/json")
end

これで全ての定義が削除できました。
ExchangeとQueueの操作も基本的には同様だと思われるので、本番用のスクリプトを作りながら検証していきます。

自分ルールに沿ったRabbitMQの設定用スクリプト

まず設定に必要な項目は固有なアプリケーション名です。設定と接続に利用するUserは本来分離するべきですが、ここでは1つのAdministrationロールを持つUserを作成してアプリからもこれを利用することとします。

sample-config.json
{
  "appname":"app01",
  "password":"secret",
  "queues":["queue01", "queue02"]
  "node":"rabbit@2478a000dddd"
}

見なれない"node"はWeb UIからログインした際に右上に表示されているCluster名です。
Queueの定義に必要なため、自動的に取得するべきか悩みましたが、とりあえず設定ファイルに記述しています。

image.png

【2023/10/19追記】Docker環境でホスト名を固定したい場合にはdocker runコマンドの引数に--hostname <your hostname>を追加してください。

このファイルを読み込み、RabbitMQ関連のもろもろの設定を自動化するスクリプトの最終形態はGithubに登録しています。

実行例

設定ファイルを引数にコマンドを実行すると一括でUSERの作成からBindingまで完了します。

実行例
$ ./setup-rabbitmq-queues.rb setup sample-config.json

とりあえずこれで十分なのですが、しばらく使ってみて必要な変更を加えていく予定です。

以上

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1