Consul ( http://www.consul.io/ ) という新しいツールが4月17日(日本時間18日)に発表されました。Vagrant や Serf の作者さんが所属している Hashicorp 社としての新しいプロダクトです。
サイトによると、Consul は、’solution for service discovery and configuration’ とあり、サービス検出と設定のためのソリューションであり、具体的には、サービス(データベースやメール等々)を監視し、問題発生時にはトラフィックを迂回させるなどといった情報を、KVS を通して提供するもの、と書かれています。
また、複数のデータセンタにまたがる非常に大きなインフラ(基盤)上で、既に数ヶ月間利用されてきた実績もあるようですね。
4/19追記:背景やアーキテクチャのドキュメントは、別途本厄翻訳しました
Consul関連文書の参考訳、Serfとの違い等
http://pocketstudio.jp/log3/2014/04/19/translation_consul_related_documents/
Consul関連ドキュメント(参考訳)Part2 (4/23追記分)
http://pocketstudio.jp/log3/2014/04/23/consul_docs_part2/
■Consulとは
- サーバとクライアントという2つのコンポーネントで構成され、クラスタを形成する
- サーバはデータを格納し、複製することが出来る
- 登録されたサーバとノードは、DNS か HTTP インターフェースを通して取得可能
主要な機能は、
- サービス検出 ( Service Discovery ) … Consul クライアントは、api や mysql 等の ‘service’ を提供し、他のクライアントはこれらサービスを検出するために Consul を用いることが出来る。
- 障害検知 ( Failure Detection ) … サービス検出とヘルスチェックを用いることで、障害発生時に何かの動作を起こすことができるようになる。
- キーバリューストレージ ( Key/Value Storage ) … Consul はシンプルな HTTP API を兼ね備えており、様々な目的に利用出来る。
- 複数データセンタ ( Multi Datacenter ) … 複数のデータをサポートする機能を持つため、複数のデータセンタにまたがるように成長しても、Consul はスケールできる。
とりあえず触ってみた感じとしては、
- Serf の仕組みも使っているが、別の仕組み(役割)で動くツールであると認識すべき
- 出来る事が多いので検証項目が多い(ヘルスチェックや、KVS )
- 実運用に使う場合、Consul + ‘何か’の部分は、自分で実装しなければいけない
このような印象を受けました。
以下、検証と自分向けの簡単なドキュメント整理です。
■とりあえずダウンロードして使ってみる( Getting Started の内容に準じます )
Consul は Serf と同じように、Go 言語で書かれており、バイナリで実行する事が出来ます。ただし、glibc のバージョンが 2.14 以上でないと動作しません。RHEL6/CentOS6 は、そのままだと環境が古いため動かないので要注意です。
$ ./consul consul: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by consul)
とりあえず、Fedora の新しめの環境が手許にあったので、そちらで試すことにしました。
例によって、consul というバイナリファイルが1個だけ必要です。
wget -O 0.1.0_linux_amd64.zip https://dl.bintray.com/mitchellh/consu/0.1.0_linux_amd64.zip unzip ./0.1.0_linux_amd64.zip mv ./consul /usr/bin/ mkdir /opt/consul/
とりあえず起動するときは、consul のサーバとしての起動を行います。以下は自ホストを 192.168.39.5 としている場合です。’-server -bootstrap’ のオプションを用います。
$ consul agent -server -bootstrap -client=192.168.39.5 -dc=local \ -node=consul1 -data-dir=/tmp/consul -bind=192.168.39.5
それから別の consul をクラスタに参加させるためには、join を使います。
$ consul agent -dc=local -node=consul2 -data-dir=/tmp/consul2 \ -bind=192.168.39.6 -join=192.168.39.5
ここでメンバ一覧をチェックしたい場合は【 consul members 】を使います。
$ consul members -rpc-addr=192.168.39.5:8400 consul1.pocketstudio.net 192.168.39.5:8301 alive role=consul,dc=local,vsn=1,vsn_min=1,vsn_max=1,port=8300,bootstrap=1 consul2.pocketstudio.net 192.168.39.6:8301 alive role=node,dc=local,vsn=1,vsn_min=1,vsn_max=1
このように、consul1 と consul2 という2台でクラスタを構成していることがわかります。
■ HTTP API で KVS を試す
consul は KVS の機能を持っており、HTTP を通し JSON 形式のデータをやりとりすることができます。たとば、メンバ一覧を表示するには、次のようにします。
$ curl http://192.168.39.5:8500/v1/catalog/nodes
[{“Node”:”consul1.pocketstudio.net”,”Address”:”192.168.39.5″},{“Node”:”consul2.pocketstudio.net”,”Address”:”192.168.39.6″}]
ポート8500 が標準の HTTP 用のインターフェースです。実行結果は JSON なので、「jq」コマンドを使うと(JSON データを grep したり、awk するようなツールです)、結果が見やすくなります。
$ curl -s http://192.168.39.5:8500/v1/catalog/nodes | jq '.' [ { "Address": "192.168.39.5", "Node": "consul1.pocketstudio.net" }, { "Address": "192.168.39.6", "Node": "consul2.pocketstudio.net" } ]
では、次にデータを書き込んでみます。 key ‘/hello/key’ に value ‘hello, world!’ をセットしたい場合は、次のようにします。
$ curl -XPUT -d 'hello, world!' http://192.168.39.5:8500/v1/kv/hello/key true
調子に乗って、もう1つ送ってみます。
$ curl -XPUT -d 'open the next' http://192.168.39.5:8500/v1/kv/hello/key2 true
さて、ここで保管されたデータですが、取り出し時に要注意です。そのまま取得しようとしても、
# curl -s http://192.168.39.5:8500/v1/kv/hello/?recurse | jq '.' [ { "Value": "b3BlbiB0aGUgbmV4dA==", "Flags": 0, "Key": "hello/key2", "ModifyIndex": 16, "CreateIndex": 16 }, { "Value": "aGVsbG8sIHdvcmxkIQ==", "Flags": 0, "Key": "hello/key", "ModifyIndex": 14, "CreateIndex": 14 } ]
素のまま読む事はできません。データは、base64 でデコードする必要があります。
$ curl -s http://192.168.39.5:8500/v1/kv/hello/key | jq '.[].Value | .' -r | base64 -d hello, world!
■DNS API を試してみる
DNS インターフェースを兼ね備えているため、ホスト名の名前解決を行う事ができます。そのため、ホスト名さえ把握できれば、仕組み的に IP アドレスを知る必要がなくなります。なお、現時点では、逆引きを行う事はできないようです。
dig を使って名前解決する場合、「-p」でポート番号 8600 を指定します。FQDN の形式は、<consulホスト名>.node.consul になります。データセンタの指定がある場合は、<ホスト名>.node.<データセンタ名>.consul で名前解決をします。
$ dig @192.168.39.5 -p 8600 consul1.node.consul any ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.23.rc1.el6_5.1 <<>> @192.168.39.5 -p 8600 consul1.node.consul any ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8882 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;consul1.node.consul. IN ANY ;; ANSWER SECTION: consul1.node.consul. 0 IN A 192.168.39.5
このように ANY リクエストで対象ノードの IP アドレスが 192.168.39.5 であるとわかります。
■サービスの登録とヘルスチェック
curl で特定 URL の HTTP 状況を確認し、ヘルスチェックに用いることが出来ます。設定ファイルの置き場所を /etc/consul.d/ とすると、
# mkdir /etc/consul.d/
# echo ‘{“service”: {“name”: “web”, “tags”: [“rails”], “port”: 80, “check”: {“script”: “curl localhost:80 >/dev/null 2>&1”, “interval”: “10s”}}}’ >/etc/consul.d/web.json
このようにファイルを設置します。
consul 起動オプションに -config-dir=/etc/consul.d を付けて再起動すると、チェックが開始されます( Apache 等のログから、10秒おきにアクセスがあることがわかります)。
また、状況は HTTP API を使って確認することもできます。httpd を停止すると、consul のログには次のように表示されます。
2014/04/18 21:58:55 [WARN] Check ‘service:web’ is now critical
2014/04/18 21:58:55 [INFO] agent: Synced check ‘service:web’
この状態でリクエストを投げると、
$ curl http://192.168.39.5:8500/v1/health/state/critical
[{“Node”:”consul1″,”CheckID”:”service:web”,”Name”:”Service ‘web’ check”,”Status”:”critical”,”Notes”:””,”ServiceID”:”web”,”ServiceName”:”web”}]
このように、critical (致命的)なサービスの一覧に ‘web’ として情報が表示されます。
■その他の機能
Serf を使っていて、どこかにデータを保管したいなと思っていましたが、Serf それ自身には機能がありませんでした。そこで Etcd を使って何か実装しなくては、と思っていたのですが、Consul は、まさにそんな目的に合いそうでした。他にも、consul が出来る機能は様々です。色々触って、使いどころを探していきたいなと思っています。
Serf クラスタと Consul クラスタは直接接続できないようなので(バージョンの古いものであれば serf エージェントとして認識できるが、イベント処理はしないので、使いどころが限定される)、イベントやクエリのトリガとなるのは、HTTP API か DNS API と、Serf を組みあわせる部分は、何かしらの実装しがいがある所と思っています。