Tech Sketch Bucket of Technical Chips by TIS Inc.

Consulクラスタ上で順序制御を行うツール「Metronome」を作ってみた

Pocket

多数のサーバで構成されたシステムというのは一般的になっており、これらを管理・運用するためのソフトウェアも充実してきています。OSSでもHashiCorpのserf, consulといったオーケストレーションツールが公開されており、各サーバの状態を把握したり、ユーザからのイベントや台数の増減に合わせて各サーバで必要な処理を実行したりと、一括しての運用・管理が行えるようになっています。

しかし、これらのツールを使って処理を行う場合、全サーバで並行して処理が行われてしまいます。もちろん独立して処理を行えるサーバであればそれで良いのですが、1つのシステムを構成するサーバ群であるため、中には他サーバの終了を待ってから処理を行いたいなどの、順序制御を行いたい部分も出てくるかと思います。 この記事ではそういった場合に使用できる順序制御ツール「Metronome」について、実際にサーバのセットアップを行いながら見ていきたいと思います。

現行の問題点

改めて現行の問題点を整理してみます。例えば、以下に示すようなWeb-AP-DBのシステムを構築する場合を考えてみましょう。

サーバ構成図

この場合、サーバ上に載せるシステムにもよりますが、Webサーバ、APサーバ、DBサーバの間には以下のような関係が考えられます。

  • Webサーバはユーザからのリクエストを受け付けるため、システム全体が使用可能になってから起動したい
  • APサーバは初期データをDBに対して書き込むため、DBサーバが使用可能になってから起動したい
  • 高負荷時にAPサーバを自動的に追加する場合、APサーバが使用可能になってからWebサーバの設定を変更し、アクセスの振り分け先を追加したい

この他にもバックアップ処理や、障害時の自動復旧など、複数サーバ間での順序制御を行いたいケースは出てくると思います。serf, consulはユーザからのイベントや台数の増減に合わせて各サーバで並行して処理を行うことができますが、こういった順序制御の機能は含まれていないため、他サーバの処理が終わるまで待つためにはconfigure-apとconfigure-dbのようにイベントを分割して、呼び出し元で順序制御をおこなったり、もしくは各サーバで実行されるスクリプト中で他サーバの処理が終わるのを待つ必要があります。

厄介なことに、consulはイベントの結果を取得する方法に長けているとは言えない為、他サーバの処理が終わるのを待つためにはconsul KVSに結果を格納するなどの力技で解決する必要があり、順序を考慮した処理を書く際の悩みの種となっていました。

Metronome

こういった問題を解決するために開発したのが、イベントの順序制御を行う「Metronome」です。 Metronomeはconsulクラスタの上で動作し、consul KVSの中に作られたイベントキューを用いて順序制御を行います。

diagram

https://github.com/cloudconductor/metronome/wiki/Overview(ja)

各サーバ上にはイベントの順序や内容を記述したYAML形式の設定ファイルがあり、これを読み込んで動作することで順序制御を行いつつ各サーバ上でシェルスクリプトやChefなどを利用した処理を実行することができるようになっています。

それでは、実際に複数台で構成されたシステムを構築しながら、Metronomeの動作を確認してみましょう。今回はAWS上にAmazon Linux AMI 2015.09.1を使用して立ち上げた5つのインスタンスを使用していきます。

事前準備(consul, chef)

まずはMetronomeが動作するために必要なミドルウェアのインストールを行っていきます。

Metronomeはconsulクラスタ上で動作するため、事前にconsulをインストールしクラスタを構築しておく必要があります。また、今回はセットアップにchefを用いるため、chefdkも併せてインストールしておきます。

この記事ではconsulやchefは本題でないため、各コマンドの詳細は説明しませんが、JSONファイルを配置してconsul catalogに各サーバのサービス情報を登録し、ユーザからのイベント受信時にMetronomeに通知するように設定してあります。また、Berkshelfを用いてセットアップ用のcookbookを取得できるようにBerksfileを作成します。

参考までに各サーバで実行したコマンドを以下に羅列しておきます。

Metronomeのセットアップ

Metronomeのセットアップを行います。MetronomeはCloudConductor公式サイトにてバイナリが公開中です。他環境用のバイナリも作れますが、動作確認が取れていないため、現在はLinux/x86-64用のバイナリのみを公開しています。

続いてMetronome用の設定ファイルを作成します。このファイルではconsulに対する接続情報や、順序制御する内容を記述したファイルへのパスなどを指定しています。今回は一部のパラメータのみを指定していますが、他の指定項目についてはUser manualを参照してください。

順序制御用ファイルの作成

順序制御の内容を記述したtask.ymlを作成します。このファイルはchefによるセットアップを行う為、Berksfileと同じディレクトリに作成することとします。

各サーバで行う処理の内容は以下の通りです。

  • Webサーバ: 確認用のログ出力 & apacheのインストールおよび起動
  • APサーバ: 確認用のログ出力 & tomcatのインストールおよび起動
  • DBサーバ: 確認用のログ出力 & postgresqlのインストールおよび起動

ordered_tasks以下に各処理を記述しているため、各処理の終了を待ちながら、DBサーバ、APサーバ、Webサーバの順にセットアップ処理が実行されます。各タスクでは順序制御が行えていることを示すため、時間のログ出力を行った後に30秒待機し、その後chefを用いて各ミドルウェアのセットアップを行います。

以下のtask.ymlではシェルスクリプトを実行するexecute、chefを実行するchefの2種類のオペレーションをoperations以下に記述していますが、他のオペレーションについてはScheduling file formatを参照してください。

処理の実行

それではMetronomeのインストール、起動を行い、セットアップ処理を流してみたいと思います。 処理の実行にはconsulに対してイベントの送付ができれば方法は問わないため、今回はシンプルにconsulのREST APIを叩いてみます。

/var/log/metronome.log/tmp/setup/logs以下に書き出されるログを見ていると、DBサーバ、APサーバ、Webサーバの順に処理が流れていくのが分かるかと思います。

結果確認

イベントの結果はconsul kvsに以下のような階層構造で記録されます。

例えば今回の場合はeventを発火した際にEvent IDとしてe774fc99-39ae-8e06-0f90-d9b51fb7b467が返ってきているため、以下のようなキーを参照することでイベント、タスク、各ノードの結果を取得することができます。

CloudConductorでMetronomeを使用する場合はこれらの結果を集約して見やすく表示していますが、setupイベント全体の結果を見てみると、Statussuccessとなっており、正常に処理が行えたことがわかります。

順序制御の結果確認

それでは各サーバでの実行結果を確認してみましょう。 各サーバで実行した結果は以下のようになりました。

webサーバ1

webサーバ2

APサーバ1

APサーバ2

DBサーバ

まとめると以下のようになります。

サーバ 時間
DB 07:54:03
AP1 07:55:03
AP2 07:55:02
Web1 07:56:26
Web2 07:56:25

30秒のウェイトによって時間はかかっていますが、ログの時間を見るとDBサーバ、APサーバ1/2、Webサーバ1/2の順番で前の処理の終了を待ってから次のセットアップ処理が行われ、また、APサーバ1と2のように同一タスクの場合には並列に処理が行われていることが見てとれるかと思います。

まとめ

consulは多数のサーバを管理する上で便利なソフトですが、各サーバに役割を振って1つのシステムを構成していくと不満も出てくると思います。まだ粗削りな点はありますが、そういったときはconsulにMetronomeを組み合わせて順序制御を行ってみてはいかがでしょうか。 興味を持っていただけた方はGithub上のwikiに詳細が記載されていますので、こちらも併せてご覧いただければ幸いです。

エンジニア採用中!私たちと一緒に働いてみませんか?