Serfを試してみました。
非集中型のクラスタ管理ツールのSerfを触ってみました。クラスタ管理というと何かいろいろ大変そうなイメージですが、Serfを利用すると簡単にサーバの死活監視や情報の収集が可能になります。
Serf is a decentralized solution for cluster membership, failure detection,and orchestration. Lightweght and highly available.
本家のサイトのトップページに書かれているようにserfは軽量で高可用性の非集中型のクラスタ管理ツールです。
Serfについて
Serfの本家サイト:https://www.serfdom.io/Serf is a decentralized solution for cluster membership, failure detection,and orchestration. Lightweght and highly available.
本家のサイトのトップページに書かれているようにserfは軽量で高可用性の非集中型のクラスタ管理ツールです。
- インストールは簡単。
- serfの静的バイナリを各サーバにコピーするだけOK。
- マスターサーバのような全体を管理しているノードはない
- 全てのノードで実行されているserfは平等。
- ゴシッププロトコルを利用したノード間のメッセージングツール
- ノード間でお互いに通信して情報を全体に伝播させる。
- 各ノードで実行されているserf agent が情報のやりとりをする。
- クラスタ内のノードの増減についてのイベント
- クラスタ内のノードの生死についてのイベント
- ユーザ独自のイベントを通知することも可能
- イベントをトリガにして任意の処理(スクリプト)を実行できる。
- これによっていろいろ応用が効くようになる。
- serf leaveコマンドを実行
- SIGINTあるいはCtrl-Cでserf agentプロセスを終了させる。
また複数のアプリケーションを組み合わせて利用する場合に全体の統制をとるのに利用できます。元々そのような管理の仕組みのないアプリケーションの組み合わせでも全体を統制するような仕組みを構築できます。
インストール
公式サイトに(静的)バイナリで配布されているのでそれをダウンロードしてきて展開し適当なパスにコピーすればOKです。今回は/usr/local/binに置く事にしました。
# wget https://releases.hashicorp.com/serf/0.6.4/serf_0.6.4_linux_amd64.zip
# unzip 0.6.4_linux_amd64.zip
# cp serf /usr/local/bin
# unzip 0.6.4_linux_amd64.zip
# cp serf /usr/local/bin
Serfではこの基本的にserfコマンドのみを利用し、serf <コマンド名> [ 引数 ...]という形式で複数の機能を実行します。
実行方法
今回はVagrant+Virtualboxの仮想環境で検証していますが、実マシンはもちろんコンテナ環境でも問題ないです。とりあえず、debian01,debian02という名前の2つの仮想サーバを立ち上げます。サーバのアドレスは次のようになっています。
debian01 : 192.168.0.101
debian02 : 192.168.0.102
debian03 : 192.168.0.103 (後ほど出てきます)
まだ以下のログでサーバ毎の時間がずれていますが気にしないでください(すみません)debian02 : 192.168.0.102
debian03 : 192.168.0.103 (後ほど出てきます)
まずそれぞれの仮想サーバでserf agentを実行します。コマンドはそのまま実行するとforegroundでの実行になります。今回はログをそのまま表示するためにforegroundで実行していますが、実際に利用する場合はbackgroundでの実行になると思います。
debian01上で
root@debian01:# serf agent -node=debian01 -bind=192.168.0.101
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
Node name: 'debian01'
Bind addr: '192.168.0.101:7946'
RPC addr: '127.0.0.1:7373'
Encrypted: false
Snapshot: false
Profile: lan
==> Log data will now stream in as it occurs:
2015/12/02 10:15:41 [INFO] agent: Serf agent starting
2015/12/02 10:15:41 [INFO] serf: EventMemberJoin: debian01 192.168.0.101
2015/12/02 10:15:42 [INFO] agent: Received event: member-join
root@debian01:# serf agent -node=debian01 -bind=192.168.0.101
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
Node name: 'debian01'
Bind addr: '192.168.0.101:7946'
RPC addr: '127.0.0.1:7373'
Encrypted: false
Snapshot: false
Profile: lan
==> Log data will now stream in as it occurs:
2015/12/02 10:15:41 [INFO] agent: Serf agent starting
2015/12/02 10:15:41 [INFO] serf: EventMemberJoin: debian01 192.168.0.101
2015/12/02 10:15:42 [INFO] agent: Received event: member-join
同様なことをdebian02上でも実行します。
ノードのクラスタへの参加
agentを実行した段階ではまだお互いに"自分のクラスタ"に属しているだけの状態です。それぞれのサーバでメンバーを確認してみると自分自身しかいません。
root@debian01:~# serf members
debian01 192.168.0.101:7946 alive
root@debian02:~# serf members
debian02 192.168.0.102:7946 alive
debian01 192.168.0.101:7946 alive
root@debian02:~# serf members
debian02 192.168.0.102:7946 alive
どちらかのノードをもう片方のクラスタに参加させることにより同じクラスタに属して通信が可能な状態になります。debian02をdebian01のクラスタに参加させてみます。このことはdebian01をdebian02のクラスタに参加させることと同じです。debian02には自分のクラスタにdebian01が参加したというイベントが通知されます。
root@debian02:~# serf join 192.168.0.101
Successfully joined cluster by contacting 1 nodes.
root@debian02:~# serf members
debian02 192.168.0.102:7946 alive
debian01 192.168.0.101:7946 alive
Successfully joined cluster by contacting 1 nodes.
root@debian02:~# serf members
debian02 192.168.0.102:7946 alive
debian01 192.168.0.101:7946 alive
debian01上で確認してみてもdebian02が参加していることがわかります。
root@debian01:~# serf members
debian01 192.168.0.101:7946 alive
debian02 192.168.0.102:7946 alive
debian01 192.168.0.101:7946 alive
debian02 192.168.0.102:7946 alive
またそれぞれのノードにノードが追加されたことが通知されています。
debian01側
2015/12/02 10:43:49 [INFO] serf: EventMemberJoin: debian02 192.168.0.102
2015/12/02 10:43:50 [INFO] agent: Received event: member-join
debian02側
2015/12/02 10:39:16 [INFO] serf: EventMemberJoin: debian01 192.168.0.101
2015/12/02 10:39:16 [INFO] agent: joined: 1 nodes
2015/12/02 10:39:17 [INFO] agent: Received event: member-join
さらにクラスタにノードを追加する場合にはノードのいずれかのメンバのクラスタに追加すればOKです。例えば3番目のノードdebian03立ち上げてをdebian02のクラスタに参加させてみましょう。次のようにserf agentの起動時にノードを指定して同時にjoinすることも可能です。2015/12/02 10:43:49 [INFO] serf: EventMemberJoin: debian02 192.168.0.102
2015/12/02 10:43:50 [INFO] agent: Received event: member-join
debian02側
2015/12/02 10:39:16 [INFO] serf: EventMemberJoin: debian01 192.168.0.101
2015/12/02 10:39:16 [INFO] agent: joined: 1 nodes
2015/12/02 10:39:17 [INFO] agent: Received event: member-join
debian03上で
root@debian03:~# serf agent --node=debian03 --bind=192.168.0.103 --join=192.168.0.102
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
Node name: 'debian03'
Bind addr: '192.168.0.103:7946'
RPC addr: '127.0.0.1:7373'
Encrypted: false
Snapshot: false
Profile: lan
==> Joining cluster...(replay: false)
Join completed. Synced with 1 initial agents
==> Log data will now stream in as it occurs:
2015/12/02 10:50:11 [INFO] agent: Serf agent starting
2015/12/02 10:50:11 [INFO] serf: EventMemberJoin: debian03 192.168.0.103
2015/12/02 10:50:11 [INFO] agent: joining: [192.168.0.102] replay: false
2015/12/02 10:50:11 [INFO] serf: EventMemberJoin: debian01 192.168.0.101
2015/12/02 10:50:11 [INFO] serf: EventMemberJoin: debian02 192.168.0.102
2015/12/02 10:50:11 [INFO] agent: joined: 1 nodes
2015/12/02 10:50:12 [INFO] agent: Received event: member-join
root@debian03:~# serf agent --node=debian03 --bind=192.168.0.103 --join=192.168.0.102
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
Node name: 'debian03'
Bind addr: '192.168.0.103:7946'
RPC addr: '127.0.0.1:7373'
Encrypted: false
Snapshot: false
Profile: lan
==> Joining cluster...(replay: false)
Join completed. Synced with 1 initial agents
==> Log data will now stream in as it occurs:
2015/12/02 10:50:11 [INFO] agent: Serf agent starting
2015/12/02 10:50:11 [INFO] serf: EventMemberJoin: debian03 192.168.0.103
2015/12/02 10:50:11 [INFO] agent: joining: [192.168.0.102] replay: false
2015/12/02 10:50:11 [INFO] serf: EventMemberJoin: debian01 192.168.0.101
2015/12/02 10:50:11 [INFO] serf: EventMemberJoin: debian02 192.168.0.102
2015/12/02 10:50:11 [INFO] agent: joined: 1 nodes
2015/12/02 10:50:12 [INFO] agent: Received event: member-join
debian03はdebian01とdebian02が追加されたというイベントを受け取ります。またdebian03が追加されたというイベントはdebian02だけでなく、debian01にも伝播して通知され、3台のノードが同じクラスタに参加している状態になります。
root@debian01:~# serf members
debian01 192.168.33.101:7946 alive
debian02 192.168.33.102:7946 alive
debian03 192.168.33.103:7946 alive
debian01のログ
2015/12/02 10:55:33 [INFO] serf: EventMemberJoin: debian03 192.168.0.103
2015/12/02 10:55:34 [INFO] agent: Received event: member-join
debian01 192.168.33.101:7946 alive
debian02 192.168.33.102:7946 alive
debian03 192.168.33.103:7946 alive
debian01のログ
2015/12/02 10:55:33 [INFO] serf: EventMemberJoin: debian03 192.168.0.103
2015/12/02 10:55:34 [INFO] agent: Received event: member-join
ノードのクラスタからの離脱
ノードをクラスタから離脱させるためにはそのノードのagentを停止させればOKです。正常終了した場合と、異常終了した場合とではこのときに他のサーバに通知されるイベントが異なります。正常終了
正常終了するには以下方法があります。
debian03でCtrl-C
^C==> Caught signal: interrupt
==> Gracefully shutting down agent...
2015/12/02 10:58:49 [INFO] agent: requesting graceful leave from Serf
2015/12/02 10:58:49 [INFO] serf: EventMemberLeave: debian03 192.168.0.103
2015/12/02 10:58:49 [INFO] agent: requesting serf shutdown
2015/12/02 10:58:49 [INFO] agent: shutdown complete
^C==> Caught signal: interrupt
==> Gracefully shutting down agent...
2015/12/02 10:58:49 [INFO] agent: requesting graceful leave from Serf
2015/12/02 10:58:49 [INFO] serf: EventMemberLeave: debian03 192.168.0.103
2015/12/02 10:58:49 [INFO] agent: requesting serf shutdown
2015/12/02 10:58:49 [INFO] agent: shutdown complete
debian01,debian02にはそれぞれmember-leaveのイベントが通知されているのが分かります。
debian01
2015/12/02 11:04:51 [INFO] serf: EventMemberLeave: debian03 192.168.0.103
2015/12/02 11:04:52 [INFO] agent: Received event: member-leave
debian02
2015/12/02 10:58:49 [INFO] serf: EventMemberLeave: debian03 192.168.0.103
2015/12/02 10:58:50 [INFO] agent: Received event: member-leave
2015/12/02 11:04:51 [INFO] serf: EventMemberLeave: debian03 192.168.0.103
2015/12/02 11:04:52 [INFO] agent: Received event: member-leave
debian02
2015/12/02 10:58:49 [INFO] serf: EventMemberLeave: debian03 192.168.0.103
2015/12/02 10:58:50 [INFO] agent: Received event: member-leave
この場合、メンバーの確認すると 正常終了したサーバはleftと表示されます。
root@debian01:~# serf members
debian01 192.168.33.101:7946 alive
debian02 192.168.33.102:7946 alive
debian03 192.168.33.103:7946 left
debian01 192.168.33.101:7946 alive
debian02 192.168.33.102:7946 alive
debian03 192.168.33.103:7946 left
異常終了
SIGTERMでプロセスを停止した場合やサーバの電源OFFなど、強制的にagentが停止された場合は他のノードがそのことを感知してイベントとして通知されます。debian03のagentをSIGTERM(9)で停止してみます。
root@debian03:~# ps -ef | grep -i serf
root 3607 3592 0 19:48 pts/0 00:00:00 serf agent -node=debian03 -bind=192.168.33.103 -join=192.168.0.102
root@debian03:~# kill -9 3607
この場合は他のメンバーがdebian03がアクセス不可になっていることを検出する形になります。root 3607 3592 0 19:48 pts/0 00:00:00 serf agent -node=debian03 -bind=192.168.33.103 -join=192.168.0.102
root@debian03:~# kill -9 3607
debian01
2015/12/02 11:19:28 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:19:30 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:19:31 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:19:33 [INFO] memberlist: Marking debian03 as failed, suspect timeout reached
2015/12/02 11:19:33 [INFO] serf: EventMemberFailed: debian03 192.168.0.103
2015/12/02 11:19:34 [INFO] agent: Received event: member-failed
2015/12/02 11:19:42 [INFO] serf: attempting reconnect to debian03 192.168.0.103:7946
2015/12/02 11:21:12 [INFO] serf: attempting reconnect to debian03 192.168.0.103:7946
...
...
debian02
2015/12/02 11:12:24 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:12:27 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:12:28 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:12:29 [INFO] serf: EventMemberFailed: debian03 192.168.0.103
2015/12/02 11:12:30 [INFO] agent: Received event: member-failed
2015/12/02 11:14:05 [INFO] serf: attempting reconnect to debian03 192.168.0.103:7946
.....
2015/12/02 11:19:28 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:19:30 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:19:31 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:19:33 [INFO] memberlist: Marking debian03 as failed, suspect timeout reached
2015/12/02 11:19:33 [INFO] serf: EventMemberFailed: debian03 192.168.0.103
2015/12/02 11:19:34 [INFO] agent: Received event: member-failed
2015/12/02 11:19:42 [INFO] serf: attempting reconnect to debian03 192.168.0.103:7946
2015/12/02 11:21:12 [INFO] serf: attempting reconnect to debian03 192.168.0.103:7946
...
...
debian02
2015/12/02 11:12:24 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:12:27 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:12:28 [INFO] memberlist: Suspect debian03 has failed, no acks received
2015/12/02 11:12:29 [INFO] serf: EventMemberFailed: debian03 192.168.0.103
2015/12/02 11:12:30 [INFO] agent: Received event: member-failed
2015/12/02 11:14:05 [INFO] serf: attempting reconnect to debian03 192.168.0.103:7946
.....
debian01,debian02にはmember-failedのイベントが通知されているのが分かります。またイベントを受け取ったあとも一定間隔でdebian03へのアクセスを試み続けます。
この場合にクラスタのメンバをチェックするとfailedと表示されます。
root@debian01:~# serf members
debian02 192.168.0.102:7946 alive
debian03 192.168.0.103:7946 failed
debian01 192.168.0.101:7946 alive
コメント
コメントを投稿