メモしてたやつを忘れてたのでポストしておく。
Dockerでnodeを3つ起動
$ sudo docker run -i -t --name node1 tsuyukimakoto/consul2 /bin/bash
$ sudo docker run -i -t --name node2 tsuyukimakoto/consul2 /bin/bash
$ sudo docker run -i -t --name node3 tsuyukimakoto/consul2 /bin/bash
それぞれ、/etc/supervisord/conf.d/supervisord.confのnodaemonをtrueにしてバックグラウンドで実行するようにしてconsoleを使えるようにしてsupervisordを起動
sudo /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
全部サーバで起動する
少なくとも3つはサーバが無いと耐障害性がゼロっぽいので、3つのノードを全部サーバであげてみる。
各nodeのIPはたまたま以下だったと仮定する。
node1: 172.17.0.156
node2: 172.17.0.157
node3: 172.17.0.158
1つめだけは -bootstrap をつけて起動する。投票せずにリーダーになれる。
# IPADDR=$(ip addr show eth0 | egrep -o '[0-9]+(\.[0-9]+){3}')
# consul agent -server -bootstrap -data-dir=/tmp/consul_data -bind=$IPADDR
残りの2つはサーバだけどbootstrapなしで起動する。
# IPADDR=$(ip addr show eth0 | egrep -o '[0-9]+(\.[0-9]+){3}')
# consul agent -server -data-dir=/tmp/consul_data -bind=$IPADDR
node1からnode2,3のconsulをメンバーとして登録する。node2,3からnode1に対してjoinしても良い
# consul join 172.17.0.157 172.17.0.158
node1で状態を確認
# consul members
Node Address Status Type Build Protocol
80cf209a4c63 172.17.0.157:8301 alive server 0.3.0 2
92b0477469ce 172.17.0.158:8301 alive server 0.3.0 2
e98aff1f6684 172.17.0.156:8301 alive server 0.3.0 2
サービスを登録する
jsonで定義して、定義ファイルを適当なフォルダに置く。フォルダは agent 起動時に -config-dir で指定する。
nginx.json
{"service": {"name": "web", "tags": ["nginx"], "port": 80}}
angentを一旦落として起動し直す(通常の設定変更ならSIGHUPで良いらしい)。
// node1
# consul agent -server -bootstrap -data-dir=/tmp/consul_data -bind=$IPADDR -config-dir=/etc/consul/conf.d
// node2,3
# consul agent -server -data-dir=/tmp/consul_data -bind=$IPADDR -config-dir=/etc/consul/conf.d
起動したらnode1からnode2,3のconsulをメンバーとして登録しなおしておく。
サービスを持っているnodeの一覧を出力する
DNSサービスのように探せる
# dig @127.0.0.1 -p 8600 web.service.consul
; <<>> DiG 9.9.5-3-Ubuntu <<>> @127.0.0.1 -p 8600 web.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21835
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;web.service.consul. IN A
;; ANSWER SECTION:
web.service.consul. 0 IN A 172.17.0.157
web.service.consul. 0 IN A 172.17.0.156
web.service.consul. 0 IN A 172.17.0.158
;; Query time: 1 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Sat Jul 12 04:42:05 UTC 2014
;; MSG SIZE rcvd: 138
HTTP経由でも
curlでもいいけど結局Pythonから使うと思うので(さらに実際は requests を使うけど)、
# python3
>>> import http.client
>>> import json
>>> from pprint import pprint
>>> con = http.client.HTTPConnection("localhost", 8500)
>>> con.request('GET', '/v1/catalog/service/web')
>>> res = con.getresponse()
>>> result = json.loads(res.readall().decode('UTF-8'))
>>> pprint(result)
[{'Address': '172.17.0.156',
'Node': 'e98aff1f6684',
'ServiceID': 'web',
'ServiceName': 'web',
'ServicePort': 80,
'ServiceTags': ['nginx']},
{'Address': '172.17.0.158',
'Node': '92b0477469ce',
'ServiceID': 'web',
'ServiceName': 'web',
'ServicePort': 80,
'ServiceTags': ['nginx']},
{'Address': '172.17.0.157',
'Node': '80cf209a4c63',
'ServiceID': 'web',
'ServiceName': 'web',
'ServicePort': 80,
'ServiceTags': ['nginx']}]
クライアントnodeを追加してみる
serverにやったのと同じようにnginxのjsonとか作った後に。
// node4
# IPADDR=$(ip addr show eth0 | egrep -o '[0-9]+(\.[0-9]+){3}')
# consul agent -data-dir=/tmp/consul_data -bind=$IPADDR -config-dir=/etc/consul/conf.d
せっかくなのでクライアント側からサーバに自分が追加されたことを通知する(node4は172.17.0.159だったとする)。
# consul join 172.17.0.156
クライアント側でもサーバ側でもサーバとクライアントが同期される。
# consul members
Node Address Status Type Build Protocol
a82f70504c03 172.17.0.159:8301 alive client 0.3.0 2
e98aff1f6684 172.17.0.156:8301 alive server 0.3.0 2
80cf209a4c63 172.17.0.157:8301 alive server 0.3.0 2
92b0477469ce 172.17.0.158:8301 alive server 0.3.0 2
試しにサーバnodeのconsulを1つ落としてみる
即座にクライアントやサーバにイベントが通知されて…
2014/07/12 05:10:24 [INFO] serf: EventMemberLeave: 80cf209a4c63 172.17.0.157
2014/07/12 05:10:24 [INFO] consul: removing server 80cf209a4c63 (Addr: 172.17.0.157:8300) (DC: dc1)
状態も変わる(leftになってる)。
# consul members
Node Address Status Type Build Protocol
80cf209a4c63 172.17.0.157:8301 left server 0.3.0 2
92b0477469ce 172.17.0.158:8301 alive server 0.3.0 2
a82f70504c03 172.17.0.159:8301 alive client 0.3.0 2
e98aff1f6684 172.17.0.156:8301 alive server 0.3.0 2
落としたnodeのconsulを起動し直しても状態は復帰しない。再度joinしてあげないといけない。
サービス監視
サービス監視は、任意のスクリプトを指定間隔で実行してexit codeを確認するタイプと、定期的な通知をもって生存とするタイプの2種類。
いずれもサービスの定義jsonと同じ場所にjsonで定義しておいておけば良い。
多分、任意のスクリプトを指定間隔で実行ってのが通常な気がする。サービスだけじゃなくって、リソース監視にも使えそう。
{
"check": {
"id": "nginx_alive",
"name": "Check nginx status",
"script": "/usr/local/bin/is_nginx_alive.py",
"interval": "30s"
}
}
WebUI
htmlとjavascriptでできたやつがあるらしい。ダウンロードして展開したディレクトリをagent起動時に -ui-dir にしていすれば/uiで見られる。