最近Serfというツールも気になっていたので、とりあえずクラスタを組んでイベントハンドラの設定をしてみるところまでやってみました。
Serfとは
Serf is a decentralized solution for service discovery and orchestration that is lightweight, highly available, and fault tolerant.
Orchestrationという層を支援する軽いツールみたいですね。これをうまく使うことで、クラスタにjoinしたweb serverを自動的に配下に加えるHAProxyとかを実装したり出来ます。参考: Serf+HAProxyで作るAutomatic Load Balancer - Glide Note
今回やること
とりあえずlocalだけでもクラスタを組めますが、最近こういう記事も書いたので、Dockerを利用しながらクラスタを組んでみます。
- vagrant内でserf agentを立て、event handlerを設定
- vagrant内でDockerコンテナを何個も起動して、Vagrant内で起動しているクラスタにjoin
- joinしたらvagrant内に直接立てたserf agentが現在のmemberを出力
くらいのことをしてみます。
イメージ図
インストール
golangで書かれてるので、バイナリを一つ落としてくるだけです。http://www.serfdom.io/intro/getting-started/install.html
まずvagrantにいれます。
$ wget https://dl.bintray.com/mitchellh/serf/0.3.0_linux_amd64.zip $ unzip 0.3.0_linux_amd64.zip $ cp serf /usr/local/bin/
あとserfの入ったdocker imageを作っておきます。
$ docker run -i -t ubuntu /bin/bash # ここからdockerコンテナ内 $ apt-get install -y unzip $ apt-get install -y wget $ wget https://dl.bintray.com/mitchellh/serf/0.3.0_linux_amd64.zip $ unzip 0.3.0_linux_amd64.zip $ cp serf /usr/local/bin/ $ exit # ここからvagrant側 $ docker ps -a $ docker commit 467e607d9733 serf # psで出てきたCONTAINER ID指定
これで準備が出来ました。
クラスタを組む
準備ができたので、クラスタを組みます。Serf by HashiCorp, Serf by HashiCorpあたりを参考に。
まずvagrant側のserfを起動します。
$ serf agent ==> Starting Serf agent... ==> Starting Serf agent RPC... ==> Serf agent running! Node name: 'precise64' Bind addr: '0.0.0.0:7946' RPC addr: '127.0.0.1:7373' ...
これで7946ポートでjoinを受け付けるようになりました。ここにjoinすればこのクラスタに入れます。ではDockerコンテナでここに入ってみます。
vagrant側でifconfigするとdocker0というnetwork interfaceがあるので、Docker側からはここにつなげば良いのでしょうか(ここきちんとは理解できてないです)。
$ ifconfig docker0 Link encap:Ethernet HWaddr 00:00:00:00:00:00 inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::9c67:53ff:fe5f:5da9/64 Scope:Link
なのでこのIPの7946 portにつなぐコンテナを立ちあげてみます。
$ docker run -t -d serf serf agent -join 172.17.42.1:7946 7e82c0ccd2df997bbfa0cd9c483d27bdcee31b1cd215a8ed8e28fc03f8ab5d31 $ serf members precise64 10.0.2.15:7946 alive 7e82c0ccd2df 172.17.0.14:7946 alive
繋げました。この調子でどんどん立ちあげます。
$ docker run -t -d serf serf agent -join 172.17.42.1:7946 $ docker run -t -d serf serf agent -join 172.17.42.1:7946 $ docker run -t -d serf serf agent -join 172.17.42.1:7946 $ docker run -t -d serf serf agent -join 172.17.42.1:7946 $ docker run -t -d serf serf agent -join 172.17.42.1:7946 $ serf members precise64 10.0.2.15:7946 alive 7e82c0ccd2df 172.17.0.14:7946 alive 7bde1fc5768a 172.17.0.15:7946 alive 8bb05f9040ee 172.17.0.16:7946 alive d37508949955 172.17.0.17:7946 alive 2c86f6b745a7 172.17.0.18:7946 alive 2bbdfce351a4 172.17.0.19:7946 alive
これでとりあえずDockerの外と複数Dockerコンテナでクラスタを作ることが出来たっぽいです。簡単ですね。
vagrant側にイベントハンドラを作る
今はとりあえずクラスタを組んだだけですが、今度はvagrant側にイベントハンドラを設置して、イベントが来たらmember一覧を表示するというだけをやってみます。Serf by HashiCorpあたりを参考に。
serf agentにはscriptを一つだけ渡せて、SERF_EVENT環境変数にイベント名、標準入力にデータが入っているっぽいです。なので以下の様なスクリプトを作っておきます。単にイベント名とデータを出力した後、serf membersを表示するだけです。
#!/bin/bash echo echo "New event: ${SERF_EVENT}. Data follows..." while read line; do printf "${line}\n" done echo "current members..." serf members
ではこのイベントハンドラを設定して、vagrant側のserfを起動します。
$ serf agent -log-level=debug -event-handler=./handler.sh
ここにDockerコンテナのserfを接続してみます。
$ docker run -t -d serf serf agent -join 172.17.42.1:7946
するとvagrant側に以下の出力が流れます。joinしたということと、現在のmemberが出力されました。
2013/12/08 07:56:48 [DEBUG] Event 'member-join' script output: New event: member-join. Data follows... c1fbbfe7c9ea 172.17.0.20 current members... precise64 10.0.2.15:7946 alive c1fbbfe7c9ea 172.17.0.20:7946 alive
もう一つjoinさせます。
$ docker run -t -d serf serf agent -join 172.17.42.1:7946
するとvagrant側でまた出力が出ます。
2013/12/08 07:58:03 [DEBUG] Event 'member-join' script output: New event: member-join. Data follows... 0a479cdc6f47 172.17.0.21 current members... precise64 10.0.2.15:7946 alive c1fbbfe7c9ea 172.17.0.20:7946 alive 0a479cdc6f47 172.17.0.21:7946 alive
このあとDockerコンテナを突然止めてみます。
$ docker stop 0a479cdc6f47a2e128d71678fd1955db2187f707612dbe86d806dda9c0ce9353
するとvagrant側で出力が出ます。なるほど、突然止めてみるとfailedという状態になるんですね。
2013/12/08 07:59:15 [DEBUG] Event 'member-failed' script output: New event: member-failed. Data follows... 0a479cdc6f47 172.17.0.21 current members... precise64 10.0.2.15:7946 alive c1fbbfe7c9ea 172.17.0.20:7946 alive 0a479cdc6f47 172.17.0.21:7946 failed
というわけでとりあえずハンドラを設定するというところまでやってみました。