-
Notifications
You must be signed in to change notification settings - Fork 2
Droongaノードの死活管理をSerfで行う手順
実験環境の構築手順に基づいて、以下の3ノードがセットアップ済みであると仮定する。
- node0: 192.168.100.50
- node1: 192.168.100.51
- node2: 192.168.100.52
各ノード上で行う。
-
ダウンロードページからバイナリを入手し、パスの通ったディレクトリに実行ファイルを設置する。
% wget https://dl.bintray.com/mitchellh/serf/0.5.0_linux_amd64.zip % unzip 0.5.0_linux_amd64.zip % sudo mv serf /usr/local/bin/
-
各ノードでサービスを起動する。ノード名とバインド先IPアドレスは、自分自身を指す値とする。 ここではポート番号の指定を省略しており、Serf既定のポート
7946
が使われる。(node0) % serf agent -node=node0 -bind=192.168.100.50 \ -event-handler=/path/to/command \ -log-level=debug ---- (node1) % serf agent -node=node1 -bind=192.168.100.51 \ -event-handler=/path/to/command \ -log-level=debug ---- (node2) % serf agent -node=node2 -bind=192.168.100.52 \ -event-handler=/path/to/command \ -log-level=debug
- この時、各ノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
- $SERF_EVENT:
member-join
- stdin:
node0 192.168.100.50
- $SERF_EVENT:
- この時、各ノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
-
サービスを起動したコンソールとは別のコンソールで、他のノードのIPアドレスを指定して
serf join
を実行する。(node0) % serf join 192.168.100.51 % serf join 192.168.100.52 ---- (node1) % serf join 192.168.100.50 % serf join 192.168.100.52 ---- (node2) % serf join 192.168.100.50 % serf join 192.168.100.51
- join先は、クラスタを構成する自分以外のノードであれば誰でも構わない。 (実際の運用時は、catalog.jsonからIPアドレスを収集してくることになる?)
- 複数回joinしても問題ない。 (ただし、既にjoin済みの場合はエラーのイベントが発生するようなので、あるノードへのjoinに失敗したら次のノードにjoinを試みる、といった形でfallbackするのがよさそう。)
- この時、各ノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
- $SERF_EVENT:
member-join
- stdin:
node1 192.168.100.51\nnode2 192.168.100.52
- $SERF_EVENT:
-
クラスタへの参加に成功したかどうか、
serf members
コマンドで確認する。% serf members node0 192.168.100.50:7946 alive node1 192.168.100.51:7946 alive node2 192.168.100.52:7946 alive
-
どれか1つのノード(例えばnode1)でSerfのプロセスを終了してみる。 するとイベントが自動的にメンバーに通知されて、各メンバーが持つメンバーリストが更新される。
-
serf leave
を実行しても、自動的にプロセスが終了する。 - この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
- $SERF_EVENT:
member-leave
- stdin:
node1 192.168.100.51
- $SERF_EVENT:
-
-
他のノード(node0かnode2)で
serf members
してみる。(node0) % serf members node0 192.168.100.50:7946 alive node1 192.168.100.51:7946 left node2 192.168.100.52:7946 alive
leftとなっているのが、離脱中のノードである。
-
離脱したノードで再度Serfを起動する。
(node1) % serf agent -node=node1 -bind=192.168.100.51 \ -event-handler=/path/to/command \ -log-level=debug
この時点ではまだ、このノードはクラスタに復帰していない。
(node0) % serf members node0 192.168.100.50:7946 alive node1 192.168.100.51:7946 left node2 192.168.100.52:7946 alive ---- (node1) % serf members node1 192.168.100.51:7946 alive
-
再度クラスタに参加する。node1から他のノードへ
serf join
する。(node1) % serf join 192.168.100.50
- この時、クラスタに残っていたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
- $SERF_EVENT:
member-join
- stdin:
node1 192.168.100.51
- $SERF_EVENT:
- この時、クラスタに残っていたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
-
クラスタへの参加に成功したかどうか、
serf members
コマンドで確認する。% serf members node0 192.168.100.50:7946 alive node1 192.168.100.51:7946 alive node2 192.168.100.52:7946 alive
-
どれか1つのノード(例えばnode1)で、serfのプロセスを強制終了してみる。 すると、残ったノードに対してイベントが自動的に通知されて、各メンバーが持つメンバーリストが更新される。
- この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
- $SERF_EVENT:
member-failed.
- stdin:
node1 192.168.100.51
- $SERF_EVENT:
- この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
-
他のノード(node0かnode2)で
serf members
してみる。(node0) % serf members node0 192.168.100.50:7946 alive node1 192.168.100.51:7946 failed node2 192.168.100.52:7946 alive
failedとなっているのが、障害発生により暗黙的に離脱中のノードである。
-
離脱したノードのserfをもう一度起動する。
- この時、クラスタに残っていたノードでは一定時間ごとのポーリングによりノードの復帰が検知され、自動的に、イベントハンドラに以下の情報が渡される(以下はnode0の場合)。
- $SERF_EVENT:
member-join
- stdin:
node1 192.168.100.51
- $SERF_EVENT:
- serfを起動し直したノードでは、「自分がjoin」のイベントが発生した後、しばらく経ってから「クラスタに残っていたほか野ノードがjoin」のイベントが発生する。
- この時、クラスタに残っていたノードでは一定時間ごとのポーリングによりノードの復帰が検知され、自動的に、イベントハンドラに以下の情報が渡される(以下はnode0の場合)。
-
クラスタへの復帰に成功したかどうか、
serf members
コマンドで確認する。% serf members node0 192.168.100.50:7946 alive node1 192.168.100.51:7946 alive node2 192.168.100.52:7946 alive
-
どれか1つのノード(例えばnode1)のVMをリセットしてみる。 すると、残ったノードに対してイベントが自動的に通知されて、各メンバーが持つメンバーリストが更新される。
- この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
- $SERF_EVENT:
member-failed.
- stdin:
node1 192.168.100.51
- $SERF_EVENT:
- この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
-
他のノード(node0かnode2)で
serf members
してみる。(node0) % serf members node0 192.168.100.50:7946 alive node1 192.168.100.51:7946 failed node2 192.168.100.52:7946 alive
failedとなっているのが、障害発生により暗黙的に離脱中のノードである。
-
離脱したノードのVMを再開し、
serf agent
を実行してサービスを起動する。- この時、クラスタに残っていたノードでは一定時間ごとのポーリングによりノードの復帰が検知され、自動的に、イベントハンドラに以下の情報が渡される(以下はnode0の場合)。
- $SERF_EVENT:
member-join
- stdin:
node1 192.168.100.51
- $SERF_EVENT:
- 復帰したノードの側でも、クラスタに残っていたノードからのメッセージにより
serf join
が自動的に実行される。
- この時、クラスタに残っていたノードでは一定時間ごとのポーリングによりノードの復帰が検知され、自動的に、イベントハンドラに以下の情報が渡される(以下はnode0の場合)。
-
クラスタへの復帰に成功したかどうか、
serf members
コマンドで確認する。% serf members node0 192.168.100.50:7946 alive node1 192.168.100.51:7946 alive node2 192.168.100.52:7946 alive
-
クラスタに参加中のノードからイベントを送る。
(node0) % serf event "my-event" "my-data"
- この時、クラスタに所属しているノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
- $SERF_EVENT:
user
- $SERF_USER_EVENT:
my-event
- stdin:
my-data
- $SERF_EVENT:
- 他のノードだけでなく、自分自身にも同時に通知される。
- この時、クラスタに所属しているノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。
-
クラスタに参加中のノードからイベントを送る。
(node0) % serf query -node=node1 "my-event" "my-data"
- この時、
-node
オプションで指定されたノードではイベントハンドラに以下の情報が渡される(以下はnode1の場合)。- $SERF_EVENT:
query
- $SERF_USER_QUERY:
my-event
- stdin:
my-data
- $SERF_EVENT:
- 自分自身にも通知できる。
- 関係ないノードには通知されない。
- この時、
- Serfのインストールと起動はChefで自動化しておくのが望ましいか?
- 誰かが作ったChef cookbookはある。 https://github.com/bbaugher/serf
- Serfのイベントハンドラとして機能するコマンドをDroonga Engineの
bin/droonga-handle-serf-event
として含める。 このコマンドの働きは以下の通りとする。-
member-join
,member-leave
,member-failed
イベントの受信時:liveなノードのリスト(ファイル)を更新する。 -
user
,query
イベントの受信時:ノードの死活状態の変更に関するものであった場合、liveなノードのリスト(ファイル)を更新する。 - ノードのリストのファイルの位置は、以下のようにしてコマンドライン引数で指定する。
serf agent -event-handler="droonga-handle-serf-event --list=/path/to/list-file"
- イベントを受信した際は、内部で
serf members
を実行し、完全な情報を元にその都度完全なリストを生成することにする。
-
- Serfのノード名は、Droonga Engineのボリュームの
address
のhost:port/tag.db
におけるhost
の部分に揃える。 - Droonga Engineは、初期状態で、catalog.jsonに記述されているすべてのノードがliveであると想定したliveなノードのリストを持つ。
- Droonga Engineは、メッセージを配送する必要が生じた時は、メモリ上にあるliveなノードのリストに基づいて配送先を決定する。
- Droonga Engineは、liveなノードのリスト(ファイル)が書き換えられたことを何らかの方法で検知して、メモリ上にあるliveなノードのリストを破棄し、ファイルから最新のliveなノードのリストを読み込む。
- Serfが起動した時点で「自分しかノードがいないクラスタに参加した」という事を意味するイベントを受信するが、それをトリガーとして、初期状態のliveなノードのリストはすぐに破棄され、自分だけが生きているという内容のliveなノードのリストがメモリ上に保持された状態となる。
- SerfとDroonga Engineは、互いにliveなノードのリスト(ファイル)のみを通じて連携しあう。お互いがお互いのプロセスを直接起動するということはない。
- これは、依存関係を可能な限り断ち切り、自動テストを容易に行えるようにするために、有効な方針である。
- Droonga Engineは、guard/listenを使ってファイルの変更を監視する。
- guard/listenは、ファイルの変更を監視するコマンドラインツールとして知られるguardが内部的に使用しているライブラリである。