Rundeck によるバッチ実行サーバの冗長化について考えてみた、試してみた #Rundeck
ここ数日ジョブスケジューラ熱が高まっていますが、少し前に下の記事で知った Rundeck も気になっていました。
Rundeck - cronから移行しやすいジョブスケジューラを使ってみよう - インフラエンジニアway - Powered by HEARTBEATS
Rundeck の仕組みと冗長化ポイント
Rundeck はある1台のサーバ上で動作し、Web UI からジョブを登録したり実行したりできます。
ジョブは Rundeck が稼働するサーバのローカル上で実行することも、Rundeck が管理するノード(群)に対してリモートで実行させることもできます。
冗長化ポイントは以下2点です。
- ジョブ実行ノード
- Rundeck 稼働サーバ
この記事ではまず、前者のジョブ実行ノードの冗長化について考えます。
Rundeck ジョブ実行ノードの冗長化
(1) ジョブ実行ノードをHAクラスタ化する
シンプルに複数台のジョブ実行ノードを HAProxy や Keepalived などの高可用システムにぶら下げて、Rundeck はHAシステム経由でジョブを実行するようにします。
このやり方の場合、Rundeck の Job の対象ノードにはHAシステムのホスト名または仮想IPを指定するようにします。
(2) ジョブを複数台で実行し、各ジョブの最初でミューテックスを取得するようにする
ジョブは複数台で実行するが、各ジョブの最初の処理でジョブの UUID ごとにユニークなミューテックス(ロック)を取得する、というやり方です。
ミューテックスの取得に成功したジョブは継続処理しますが、失敗した場合は即座に終了するようにします。
アプリケーションフレームワークにこうした機構が実装されていれば、比較的手軽に実現できそうです。
実は Rundeck の Job 設定を工夫すれば、同じようなことは「一応」実現できました。
以下は、Vagrant で動かすことができる GitHub - rundeck/anvils-demo: A simple example showing off rundeck's basic features を使って試しに設定してみた例になります。
Rundeck の Workflow による Job のミューテックス制御
手元の Mac にリポジトリを git clone し、vagrant up すると、box のダウンロード => 起動 => provision による Rundeck のインストールとセットアップが実行され、およそ 20〜30分ほどで Rundeck の WebUI に http://192.168.50.2:4440 でアクセスできるようになりました。
ログイン画面が出るので admin/admin でログインし、anvils プロジェクトの「Jobs」画面から、以下のような Job を作成します。
Rundeck では単一ステップのジョブだけでなく、複数ステップから成る Workflow を作成することもできます。
各ステップには名前をつけることができます。
わかりやすいように "get lock", "procedure", "clean up" としました。
それぞれ中身はシェルコマンドです。
ここで、"get lock" は Rundeck 稼働サーバ上で mkdir /tmp/lockdir
を実行することで、簡易的なミューテックス取得処理となるように意図しています。
"procedure" は任意のリモートプロセスなのですが、今回は単にローカルサーバ上で success
を標準出力するだけです。
この Job を実行してみます。
tag:app にマッチするノード2台が実行対象です。
Fail してしまいました。
ただし、Summary 表の "FAILED" は失敗したノード数を表しています。
数字は1なので、もう1台では成功しています。
Report タブで各ノードのステップ実行結果を見てみます。
app1.anvils.com では "All Steps OK" となっており、Workflow が最後まで正常に実行されたことがわかります。
他方、app2.anvils.com では "get lock" ステップで失敗して、以降の処理を中断しました。
これはミューテックスによる排他制御であり、狙い通りの挙動です。
最後に出力である Log Output を確認しておきます。
app1.anvils.com でのみ実際の処理(=successの表示)が行われたことがわかります。
以上で、Rundeck によって、バッチジョブを複数台にディスパッチし、かつその内1台でのみ実行されるように設定可能なことがわかりました。
ただ、ジョブ全体の結果が Failed になってしまうのが少々残念なところです。
調べた限りでは、「1台でも実行成功したら成功とする」ような設定は見つからなかったので、仕方なさそうです。
おわりに
この記事では Rundeck によるバッチ実行ノードの冗長化について考えてみました。
また、Rundeck の機能を使うことで冗長化が「一応」実現可能なことを確認しました。
しかし、少々トリッキーなやり方になってしまいました。
Rundeck 自体に「対象ノード群のどれか1台でのみジョブを実行する」ような機能があったら便利ですね!
GitHub を覗いてみたら、そういう Issue が既に挙げられていました。(ので、"+1" してみました :D)
How to execute a job on only a single node · Issue #729 · rundeck/rundeck · GitHub
2つめの Rundeck サーバの冗長化についても書こうと思ったのですが、長くなったのでこのエントリはここまでにしておきます。