Consulで遊ぶ環境を簡単に作る方法、もしくはConsul 0.6 で追加された新機能の紹介
この記事は HashiCorp Advent Calendar 2015 18日目の記事です。 すでに穴が4つもできてしまったので埋めたい…(ちょっと無理)
はじめに
新しく出たツールを検証する場合、皆さんはどのような環境で行いますか? 手元のMacでは動かないツール、もしくはMacに検証用のファイルを置いたりパッケージをインストールしたりして汚したくない場合、検証用のVMを立ち上げてその中で行うのが一般的でしょうか。
では、Consulの場合はどうでしょうか。 Consulは複数のノードでクラスタを組んで動作します。 よって検証する場合は複数のマシンが必要であり、必要な分だけVMを立ち上げなければなりません。 VMを複数立ち上げるのは結構スペックを必要とするため、すぐに頭打ちになってしまいます。
本エントリーでは、Consulを 検証するための環境 遊ぶ環境を手軽に作る方法を紹介し、それを利用して先日出たばかりの 0.6 の新機能を紹介します。
なお、別の方法として 検証用に 1 台のサーバで consul を複数起動する - tkuchikiの日記 もあるので、好みの方法で構築すると良いかと思います。
遊ぶ環境を作る
$ docker run -d -p 8500:8500 --name node01 -h node01 gliderlabs/consul-server:0.6 -server -bootstrap-expect 3 $ JOIN_IP="$(docker inspect -f '{{.NetworkSettings.IPAddress}}' node01)" $ docker run -d --name node02 -h node02 gliderlabs/consul-server:0.6 -server -join $JOIN_IP $ docker run -d --name node03 -h node03 gliderlabs/consul-server:0.6 -server -join $JOIN_IP $ for i in {4..30}; do docker run -d --name node`printf %02d $i` -h node`printf %02d $i` gliderlabs/consul-agent:0.6 -join $JOIN_IP; done
できた。
Server 3台 + Client 27台、合計30台のクラスタが一瞬で出来上がりました(最初調子にのって100台とかで作ろうとしたけど、流石にベースのVMが耐えられなかった)。
$ docker exec -it node01 consul members Node Address Status Type Build Protocol DC node01 172.17.0.2:8301 alive server 0.6.0 2 dc1 node02 172.17.0.3:8301 alive server 0.6.0 2 dc1 node03 172.17.0.4:8301 alive server 0.6.0 2 dc1 node04 172.17.0.5:8301 alive client 0.6.0 2 dc1 node05 172.17.0.6:8301 alive client 0.6.0 2 dc1 node06 172.17.0.7:8301 alive client 0.6.0 2 dc1 node07 172.17.0.8:8301 alive client 0.6.0 2 dc1 node08 172.17.0.9:8301 alive client 0.6.0 2 dc1 node09 172.17.0.10:8301 alive client 0.6.0 2 dc1 node10 172.17.0.11:8301 alive client 0.6.0 2 dc1 node11 172.17.0.12:8301 alive client 0.6.0 2 dc1 node12 172.17.0.13:8301 alive client 0.6.0 2 dc1 node13 172.17.0.14:8301 alive client 0.6.0 2 dc1 node14 172.17.0.15:8301 alive client 0.6.0 2 dc1 node15 172.17.0.16:8301 alive client 0.6.0 2 dc1 node16 172.17.0.17:8301 alive client 0.6.0 2 dc1 node17 172.17.0.18:8301 alive client 0.6.0 2 dc1 node18 172.17.0.19:8301 alive client 0.6.0 2 dc1 node19 172.17.0.20:8301 alive client 0.6.0 2 dc1 node20 172.17.0.21:8301 alive client 0.6.0 2 dc1 node21 172.17.0.22:8301 alive client 0.6.0 2 dc1 node22 172.17.0.23:8301 alive client 0.6.0 2 dc1 node23 172.17.0.24:8301 alive client 0.6.0 2 dc1 node24 172.17.0.25:8301 alive client 0.6.0 2 dc1 node25 172.17.0.26:8301 alive client 0.6.0 2 dc1 node26 172.17.0.27:8301 alive client 0.6.0 2 dc1 node27 172.17.0.28:8301 alive client 0.6.0 2 dc1 node28 172.17.0.29:8301 alive client 0.6.0 2 dc1 node29 172.17.0.30:8301 alive client 0.6.0 2 dc1 node30 172.17.0.31:8301 alive client 0.6.0 2 dc1
ちゃんと出来上がってます。
ちょっとだけ解説
見ればわかりますが、Docker使ってます。 ServerとClient(Agent)はそれぞれ以下のイメージを利用しています。
- gliderlabs/consul-server
- gliderlabs/consul-agent
それぞれ gliderlabs/consul をベースにし、consul-server はサーバ用の設定とwebuiのインストール、 consul-agent はクライアントの設定がされます。
詳細はこちら docker-consul/0.6 at master · gliderlabs/docker-consul · GitHub
先日まで0.6用のイメージはなかったのですが、昨日あたりに追加されていました。
Docker本体の環境についても Docker Toolbox などを利用すれば簡単に作れます。
Consul 0.6 で追加された新機能の紹介
先ほど作った環境で、0.6 の機能を試してみます。 なお、30台だと流石に多いので、9台で検証しています。
リリースの詳細については本家のブログ Consul 0.6 - HashiCorp または、 前佛さんの翻訳記事 【参考訳】Consul 0.6 | Pocketstudio.jp log3 が参考になります。
Network Tomography
Vivaldi アルゴリズムを利用した、 Network Tomography subsystem が組み込まれた(コアの部分が置き換えられたの方が表現としてはあってる?)そうで、 ノード間のRTTの計算が容易になりました。
これにともなって、サービスディスカバリの領域においてRTTを基準としたサーバ検索が行えるようになっています。
consul rtt
は新しく追加されたコマンドです。
各ノード間のRTTが簡単に調べられます。
新しくノードを追加した時など手軽にRTTを知りたい時に重宝しそうです。
# Get the estimated RTT from current node to another / # consul rtt node1 Estimated node1 <-> node9 rtt: 0.107 ms (using LAN coordinates) # Get the estimated RTT between two other nodes from a third node / # consul rtt node1 node2 Estimated node1 <-> node2 rtt: 0.042 ms (using LAN coordinates)
?near=
query はHTTP API(Catalog endpoints および Health endpoints) で利用できるクエリです。
任意のAPIコールの結果をRTTの昇順にソートして返すようになります。
/ # consul rtt node2 node1 Estimated node2 <-> node1 rtt: 0.066 ms (using LAN coordinates) / # consul rtt node2 node2 Estimated node2 <-> node2 rtt: 0.020 ms (using LAN coordinates) / # consul rtt node2 node3 Estimated node2 <-> node3 rtt: 0.218 ms (using LAN coordinates) # Get a list of healthy nodes providing the "consul" service sorted # relative to a specific node by RTT / # curl localhost:8500/v1/health/service/consul?passing&near=node2 | jq -r '.[].Node.Node' node2 node1 node3 # Get the full list of nodes sorted relative to a specific node by RTT / # curl localhost:8500/v1/catalog/nodes?near=node5 | jq -r '.[].Node' node5 node1 node9 node2 node8 node7 node6 node4 node3
Coordinate endpoint(/v1/coordinate/nodes?pretty
) では、ネットワーク座標を取得できます。
各ノードのベクトル(Vec) からノード間の距離を求めることができます。
詳細はこちら Network Coordinates - Consul by HashiCorp (RTTの求め方も載ってます)
[ { "Node": "node1", "Coord": { "Vec": [ 0.0008308362555119787, 3.8834696349342976e-05, -7.330295628680596e-05, 4.8062527310734514e-05, -0.0005581071597177744, -0.0003221936982394534, -6.971672661372596e-05, -0.0004306435811588809 ], "Error": 1.5, "Adjustment": -0.00011494860634112172, "Height": 1e-05 } }, { "Node": "node2", "Coord": { "Vec": [ 0.0009838237474445097, -8.948185219298897e-05, -0.0001975770907099398, -0.00010850758409038799, -0.00047155927265006775, -0.0003061645607253343, -0.00010680739481578534, -0.00038532602975600936 ], "Error": 0.3718403628578162, "Adjustment": -7.270959866839972e-05, "Height": 1.3393634886322704e-05 } }, { "Node": "node3", "Coord": { "Vec": [ 0.0007790221967808862, 6.914188380807579e-05, 7.062968132664298e-05, 0.00032544947802519176, -0.0006541842810516811, -0.0005631915374662459, -8.950215112117045e-05, -0.0006292580762066054 ], "Error": 0.7817148091744002, "Adjustment": -2.1750939565216435e-05, "Height": 1.7306613773018416e-05 } }, { "Node": "node4", "Coord": { "Vec": [ 0.0007750088234166339, -6.648183921543096e-05, 6.595850650451458e-05, 4.476915104072036e-05, -0.0005330333440500301, -0.0003396976765792745, -0.00018009025741683393, -0.0003354371244755442 ], "Error": 0.4662724272241323, "Adjustment": -8.246895358696942e-05, "Height": 1.3124720777974974e-05 } }, { "Node": "node5", "Coord": { "Vec": [ 0.0008756082448597619, 0.0001451495962603484, -0.00016348329520411183, -7.421255884312142e-06, -0.0006111789589409528, -0.00022696220959236607, -4.21740756687009e-05, -0.00037307546522279556 ], "Error": 0.6239200064902178, "Adjustment": -8.412713268872293e-05, "Height": 3.4543520155739374e-05 } }, { "Node": "node6", "Coord": { "Vec": [ 0.0007933796817663052, 4.983046470566237e-05, -9.702838552304187e-05, 3.040296448700226e-05, -0.0005264474847280151, -0.0002941232682663392, -6.820691953143878e-05, -0.0003872869858185183 ], "Error": 0.1887715382026358, "Adjustment": -6.819567824840735e-05, "Height": 5.0365606598955985e-05 } }, { "Node": "node7", "Coord": { "Vec": [ 0.0009350777191959045, 4.499505796461562e-05, 3.915480990138882e-05, -1.1579372878324448e-05, -0.0007258365876150744, -0.0003179427728042287, -7.793465386253961e-05, -0.0004676110246087647 ], "Error": 0.5423866972713568, "Adjustment": -5.6858658839466216e-05, "Height": 3.005228399338976e-05 } }, { "Node": "node8", "Coord": { "Vec": [ 0.0008241239131583833, 1.998265731794065e-05, -0.00011906286207585868, 1.960936999867024e-05, -0.0005031235742582041, -0.00031863387772168057, 9.233626644673831e-05, -0.0006058093090722743 ], "Error": 0.6215351125132542, "Adjustment": -7.72737362166153e-05, "Height": 4.3466618805655724e-05 } }, { "Node": "node9", "Coord": { "Vec": [ 0.0009366983301109099, 4.9953759736052004e-05, -0.0001549760502726523, 9.353780837133608e-05, -0.0005210341425697293, -0.00020805724862674042, -6.315174348245893e-05, -0.0004353838903282064 ], "Error": 0.35291220381539484, "Adjustment": -6.71410964055522e-05, "Height": 1.019578519702038e-05 } } ]
Prepared Queries
Prepared Queries を利用するとDNSインターフェースにおいても、Network Tomography の恩恵が受けられるようになります。
まずは対象となるサービスを適当に登録しておきます(一つだけ v0.0.1)。
/ # curl -X PUT localhost:8500/v1/agent/service/register -d '{ > "ID": "app1", > "Name": "hoge-api", > "Tags": [ > "api", > "v0.1.0" > ] > }' / # curl -X PUT 172.17.0.3:8500/v1/agent/service/register -d '{ > "ID": "app1", > "Name": "hoge-api", > "Tags": [ > "api", > "v0.1.0" > ] > }' / # curl -X PUT 172.17.0.5:8500/v1/agent/service/register -d '{ > "ID": "app1", > "Name": "hoge-api", > "Tags": [ > "api", > "v0.0.1" > ] > }'
サービスが登録されていることを確認します。
/ # curl localhost:8500/v1/catalog/service/hoge-api | jq -r '.[].Node' node2 node4 node9
Prepared Queryを登録します。 ここでは以下の設定を指定しています。
- Failoverの設定(ローカルのDCになければ、RTT的に近場の3つのDCから探す)
- Tagsの設定(タグが api かつ v0.1.0 のものでフィルタリングする)
/ # curl -X POST -d \ > '{ > "Name": "hoge-api-with-failover", > "Service": { > "Service": "hoge-api", > "Failover": { > "NearestN": 3 > }, > "Tags": ["api", "v0.1.0"] > }, > "DNS": { > "TTL": "10s" > } > }' localhost:8500/v1/query {"ID":"cc72300b-946c-68a0-e744-e6f203719dd5"}
下準備はここまで。 まずはいつもどおりに問い合わせてみると
/ # dig @127.0.0.1 -p 8600 hoge-api.service.consul. ANY ; <<>> DiG 9.10.3-P2 <<>> @127.0.0.1 -p 8600 hoge-api.service.consul. ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 401 ;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;hoge-api.service.consul. IN ANY ;; ANSWER SECTION: hoge-api.service.consul. 0 IN A 172.17.0.10 hoge-api.service.consul. 0 IN A 172.17.0.3 hoge-api.service.consul. 0 IN A 172.17.0.5 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Thu Dec 17 11:24:48 UTC 2015 ;; MSG SIZE rcvd: 158
期待通りの結果が返ってきました。
Prepared Queryで設定したエンドポイントで問い合わせて見ると、
/ # dig @127.0.0.1 -p 8600 hoge-api-with-failover.query.consul. ANY ; <<>> DiG 9.10.3-P2 <<>> @127.0.0.1 -p 8600 hoge-api-with-failover.query.consul. ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7875 ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;hoge-api-with-failover.query.consul. IN ANY ;; ANSWER SECTION: hoge-api-with-failover.query.consul. 10 IN A 172.17.0.10 hoge-api-with-failover.query.consul. 10 IN A 172.17.0.3 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Thu Dec 17 11:34:23 UTC 2015 ;; MSG SIZE rcvd: 155
フィルタリングされて返ってきました。
また HTTP API も用意されていて、こちらでは ?near=
クエリが利用できるので、RTTの昇順でノードを取得できます。
詳細はこちら Prepared Queries (HTTP) - Consul by HashiCorp
最後に
Consul 0.6 で追加された機能はまだまだあって、Network Tomography だけでなく、New In-Memory Database(脱LMDB) などかなり大きな変更が入っています。 これだけ大きな変更がありつつも、バイナリ一つで提供でき、前バージョンからのアップデートもしっかりサポートされてさすがです。 今後の動向にも注目ですね(遊んでばかりいないでそろそろ業務で使おう…)。
ここで紹介した内容はこちらにもまとめてあります。