Consul には様々な機能があります。Serf に使い慣れていれば、サーバ・ノード間の関係や、CLI や agent としてのコマンドの扱いは、Serf の通りだとは思います。
しかし、まったく新しい概念がいくつかあり、主立ったものは JSON を使ったインターフェースと、それを通した「 Blocking Query 」(ブロッキング・クエリ)ではないでしょうか。
割と新しい概念であり、使いどころは「これから」という所は多少あるものの、仕組みとしてはシンプルで分かりやすいものかと思います。
■ blocking query とは
Consul の持っている特色の1つに HTTP 経由の API を持つほか、bloking query という仕組みを内包している点だと思います。
blocking query とは、Consul のドキュメントには、「エンドポイント(API へのリクエスト先)の種類によっては、応答をブロックできる」とあります。すなわち、変化があるまでは、現状を維持するしくみであり、状況の変換があれば応答がある仕組みです。
この仕組みは非常にシンプルですが、運用・監視業界にとっては、エポックメイキング的な仕組みではないでしょうか。
従来のツールにとっては、監視対象が正常である/正常ではない、という仕組みのほか、閾値を超過した/しない期間における異常(と定義した値、ないし、ツール内部に於ける異常時)を検出するものでした。
しかし、Consul において面白いのは、監視対象の障害検出を「逐次」行う点です(逐次、というのは、ツール上における定義が、従来の監視ルールにおける定義のソレとは違うような印象があるためです)。
具体的には、ある運用監視ツールが障害(ノードが応答しないなどの障害)を検出したとしても、従来のツールであれば「サーバ」が障害を検出を識別/認識できないと、次の対応(わかりやすいのが、ロードバランサの切り分けなど、サービスの迂回)に対するアクションを起こせなかった点ではと思われます。
ところが、consul であれば、障害検出に Serf の仕組みを内包しているため、障害を比較的速く検出しつつ、アクションを起こすためのトリガとなる仕組みが提供されているのです。
■ blocking query を使うためには Raft Index の把握が必要
前提として覚えておくべきは、Consul は Ralf プロトコルに従って動作します。Raft は、いわゆる分散処理における有用なプロトコルの一つですが(とか書きつつ、自分は詳しくなのでごめんなさい、専門の方に解説をゆずります)、一貫性に強いという仕組みを持っています。
その、一貫性となる基準が「index」です。何かしら、ノード上で検出された動作毎に、この index 値は更新されていきます。この「index」を知るには、コマンドラインでは
$ consul info
です(2014/6/17修正: index と書いていましたが、info です)。この結果には、様々なシステム及びクラスタに関する情報が表示されますが、重要なのは「commit_indes」の値です。
raft: applied_index = 2226 commit_index = 2226 fsm_pending = 0 last_log_index = 2226
この「index」値を把握せず、’blocking query’を処理しようとしても、動作しません。正確には、index 値よりも低い値をリクエストしても(URLの引数で index= を指定する所がありますが、秒数を指定しても)即座に応答が返ってくる状況です。
具体的には、index 値を把握しないままで ‘critical’ なノードのリスト化しようと、
'http://192.168.39.5:8500/v1/health/state/critical?wait=5s&index=1500'
このように指定しても、blocking query としては動作しません(curl でコマンドを実行してリクエストしても、即座に応答します=bloking query ではありません)。
では、逆に ‘index’を適切に把握していると consul の応答はどう変わるのでしょうか。
blocking query が動作するのは
- Raft Index をリクエスト時の引数として適切に指定した時
- 指定した時間をタイムアウトした時
この、いずれかの条件を満たす必要があります。
具体的には、次のようなリクエストを行ったとして、
# curl -v 'http://192.168.39.5:8500/v1/health/state/critical?wait=30m&index=2000'
この状態で応答が返るのは、
- 30m ( 30 分 ) のタイムアウトが発生した(リクエストから 30 分後)
- 異常が発生した
このいずれかです。
Raft の Index が ‘2226’ であるならば、この index 値は 2226 より大きくしないと blockng query は動作せず、2226 を越えるリクエストをしなければ、blocking query は動作しません。逆に言いますと、blocking query を活用したいのであれば、都度、インデックスがどこまで進んでいるか ‘Raft Index’ を把握する仕組みが必要です(ここはツールの要なのか、現状公開されているバージョンでは、インデックスのみを指し示す、API のポイントなりコマンドはありません=infoのみ)。別解として、HTTP リクエスト時のヘッダの取得(curl -v )を行う事で、index 値を知る方法があります。
なお、前者(タイムアウト)であれば、予想される値と、おそらくシステムが持つであろう値と比較することで、タイムアウトかどうかの比較は簡単です。
重要なのは後者です。異常が発生したタイミングで、すぐにサーバから応答が得られます。従来のツールであれば、ある程度のタイムラグが発生します。それは、監視サーバ(マスタ)側が検出した後、その情報に対してクライアントがアクセスして結果を得るまでです。
consul にアクセスするクライアントであれば(consul が入っている必要はなく、大切なのは HTTP インターフェースに対してアクセスできること)、障害発生後、直ちにさまざまなアクションを起こしうる点です。
しかし、もしここで Serf を使っていれば、「そのタイミングのイベントハンドラに応じて何か実行できれば」と思いますが、現状公開中の Serf と Consul のプロトコルには互換性がありません(でも、たぶん、いつかプロトコルは追いつくのでは、、と思っていますが)。現在は、blocking query を使って処理する何かは、Consul で提供されないため、自分で実装しなくてはいけません。
そんな感じで、まだまだ抽象的な Consul ですが、Serf と連携するだけでも出来る事は広まりますし、ほかのツールとの連携性も高いのではと思っています(例えば、個人的には Consul + Sensu を使った自動監視と、発生したトリガを「適切に」処理する何かが必要、というシーンに活用できるのではと)。
もし、少しでも、Consul や Serf に興味が持ちましたら、是非、自分で触って体感して、blog に書くなりして、色々情報交換できると楽しいんじゃないかなと思います。