Serf/Consulで管理を自動化! ~実践的な手法を紹介~

第2回 Serfのイベントハンドラで自動化を使いこなす

この記事を読むのに必要な時間:およそ 4 分

イベントハンドラの使い方

イベントハンドラを使うには,Serfエージェント起動時のオプションで,-event-handler=<コマンドスクリプト名>の形式で指定します。より具体的な使い方と,イベントハンドラの自由度を高める環境変数の取り扱い方を見ていきます。

イベント発生毎に時刻を記録するには?

ここでは簡単な例として,イベント発生時にdateコマンドの時刻を記録することを考えます。ファイル/tmp/serf.logに書き出すには,次のように-event-handler=オプションを使い,エージェントを起動します。

$ serf agent -event-handler="date >> /tmp/serf.log"

エージェント起動直後に/tmp/serf.logを開くと,既に時刻が記録されていることが分かります。これは,エージェント自身をSerfクラスタとして認識するmember-joinイベントが発生したからです。

$ cat /tmp/serf.log
2015  3 29 日曜日 16:18:12 JST

以降は,コマンドライン上でserf event checkのようにカスタムイベントを実行したり,クラスタへ他のエージェントを参加させたり離脱のタイミングで時刻が記録されます。

特定のイベント時のみ実行するには?

イベント発生毎に実行するだけでなく,特定のイベント時にだけ実行させることもできます。その場合は,エージェントを-event-handler=<イベント名>:<コマンドやスクリプト>の形式で起動します。例えば,メンバ参加時(member-join)だけイベント発生時刻を記録したい場合は,次のようにして起動します。

$ serf agent -event-handler="member-join=date >> /tmp/serf-member-join.log"

この状態で再度serf event checkのようにユーザイベントを起動しても,テキストファイルには時刻は記録されません。そのかわり,member-joinイベント発生時は時刻が記録されることが分かります。

イベント名と時刻を記録するには?

時刻を記録するだけでなく,どのようなイベントが何時発生したかを確認できます。イベント名やノード名は,環境変数を通して取得します。ここではイベント名と時刻を記録するためのスクリプトevent.shを作成し,実行パーミッションを設定します。

$ touch event.sh
$ chmod 700 ./event.sh

エディタでファイルを編集し,次のように書き換えます。

event.sh

#!/bin/sh

date
echo SERF_EVENT = ${SERF_EVENT}
while read line; do
echo $line
done

それから,今度は次のようにevent.shをイベントハンドラとして実行します。

$ serf agent -event-handler="./event.sh >> /tmp/serf-event.log"

任意のイベントを発行したり,クラスタに新しくメンバが参加するイベントが発生したりすると,発生時の時刻やイベント名や付随する情報が記録されていることが分かります。

2015  3 29 日曜日 16:55:47 JST
SERF_EVENT = member-join
sakura1.pocketstudio.net 192.168.39.11
2015  3 29 日曜日 16:55:55 JST
SERF_EVENT = user
2015  3 29 日曜日 16:56:00 JST
SERF_EVENT = member-join
sakura3.pocketstudio.net 192.168.39.13

クエリを試すには?

イベントハンドラでqueryを指定し,ノード上から結果を取得したい場合は-event-handler=query=<コマンドまたはスクリプト名>の形式でSerfエージェントを起動します。例えばuptimeコマンドを実行するクエリの指定は次のようにします。

$ serf agent -event-handler="query=uptime"

このときに注意するのは,クエリを実行したいサーバすべてで-event-handler=の指定が必要です。設定後,コマンドラインでserf query uptimeイベントを発生すると,次のように各サーバでuptimeコマンドを実行した結果が表示されます。

$ serf query uptime
Query 'uptime' dispatched
Ack from 'sakura1.pocketstudio.net'
Response from 'sakura1.pocketstudio.net':  17:38:47 up 368 days, 21:38,  3 users,  load average: 0.12, 0.35, 0.30
Ack from 'sakura3.pocketstudio.net'
Response from 'sakura3.pocketstudio.net':  17:38:48 up 368 days, 21:42,  1 user,  load average: 0.29, 0.29, 0.21
Total Acks: 2
Total Responses: 2

その他の環境変数と応用の仕方

Serfのイベント情報は,環境変数と標準出力を使って取得できます。これまで見て来たシェルスクリプトだけでなく,RubyやPerl・Pythonなどのスクリプトでも利用できます。そのため,環境変数SERF_EVENTでイベント名を判別し,条件判定に応用することもできます。

主な環境変数は,以下の通りです。

SERF_EVENT

発生したイベント名です。ここにはmember-join, member-leave, member-failed, member-update, member-leap, user, query が入ります。

SERF_SELF_NAME

イベントハンドラを実行する自分自身のホスト名です。

SERF_TAG_<タグ名>

<タグ名>で指定した値です。

SERF_USER_EVENT

ユーザイベントの名称が入ります。このときの環境変数SERF_EVENTuserです。

SERF_QUERY_NAME

クエリの名称が入ります。このときの環境変数SERF_EVENTqueryです。

イベントハンドラと環境変数の関係を理解するには,GitHubで公開しているサンプルスクリプトが役に立ちます。serf-event.shを作成し,ログ出力レベルとデバッグモードにします。

$ serf agent -log-level=debug -event-handler=./serf-event.sh

起動後はSerfのクラスタに追加・削除したり,イベントを発行したりすることで,どのようにデータのやりとりしているか分かりやすいと思います。

まとめ

Serfには2種類のイベントがあり,それぞれのイベント発生のタイミングでイベントハンドラと呼ばれるスクリプトやコマンドを実行する方法を見てきました。

次回は,Serfをより細かく使いこなす方法を見ていきます。これまではコマンドライン上で,Serfの実行オプションを指定してきました。それだけでなく,一般的なツールと同様に,Serfは外部ファイルから設定を読み込む方法をご紹介します。

参考情報

著者プロフィール

前佛雅人(ぜんぶつまさひと)

クリエーションライン株式会社 Technology Evangelist

ホスティングサービスで運用保守サポートに携わった後,現職へ。サポート業務や新技術検証・開発業務を行う。趣味で監視や自動化に関するOSS検証や翻訳を行うのが好き。辛口の日本酒が大好き。

Twitter:@zembutsu

コメント

コメントの記入