読者です 読者をやめる 読者になる 読者になる

tkuchikiの日記

Linux やプログラミングについて書きます。

Consul Multiple Datacenters 検証結果 +α

consul

この記事は、HashiCorp Advent Calendar 2015 17日目の記事です。

検証環境の Consul は、

$ consul --version
Consul v0.6.0
Consul Protocol: 3 (Understands back to: 1)

です。
検証環境は v0.6.0 ですが、v0.6.0 に依存した話しはほとんどないと思います。

筆者は、Consul を Multiple Datacenters(以降、Multi-DC) で運用しております。
Multi-DC で Consul を導入する際に検証した結果を記します。
トピックは以下のとおりです。

  • WAN
  • DC をまたいで DNS を引く
  • DC をまたいで KV のデータを取得する
  • DC をまたいで KV にデータを入れる
  • Consul Event は複数の DC に一斉に送れない
  • DNS forward に Unbound を使う
  • External Services

準備

Consul のバイナリを入手します。

$ curl -LO https://releases.hashicorp.com/consul/0.6.0/consul_0.6.0_linux_amd64.zip
$ unzip consul_0.6.0_linux_amd64.zip

実験のために何台もサーバを立てるのは大変なので、
検証用に 1 台のサーバで consul を複数起動する - tkuchikiの日記 のような手順で、
1 台のサーバに Server x 3, Client x 1 のクラスタを 2セット作ります。

dc01

$ ./consul members
Node           Address         Status  Type    Build  Protocol  DC
consul01-dc01  10.0.2.15:8301  alive   server  0.6.0  2         dc01
consul02-dc01  10.0.2.15:8311  alive   server  0.6.0  2         dc01
consul03-dc01  10.0.2.15:8321  alive   server  0.6.0  2         dc01
consul04-dc01  10.0.2.15:8331  alive   client  0.6.0  2         dc01
$ curl http://127.0.0.1:8500/v1/status/leader
"10.0.2.15:8300"

dc02

$ ./consul members -rpc-addr=127.0.0.1:18400
Node           Address          Status  Type    Build  Protocol  DC
consul01-dc02  10.0.2.15:18301  alive   server  0.6.0  2         dc02
consul02-dc02  10.0.2.15:18311  alive   server  0.6.0  2         dc02
consul03-dc02  10.0.2.15:18321  alive   server  0.6.0  2         dc02
consul04-dc02  10.0.2.15:18331  alive   client  0.6.0  2         dc02
$ curl http://127.0.0.1:18500/v1/status/leader
"10.0.2.15:18300"

WAN

WAN は、すべての DC を含めた Consul クラスタ全体のことです。
consul members -wan は Multi-DC の Consul Server のみを返します。

$ ./consul members -wan
Node                Address          Status  Type    Build  Protocol  DC
consul01-dc01.dc01  10.0.2.15:8302   alive   server  0.6.0  2         dc01
consul01-dc02.dc02  10.0.2.15:18302  alive   server  0.6.0  2         dc02
consul02-dc01.dc01  10.0.2.15:8312   alive   server  0.6.0  2         dc01
consul02-dc02.dc02  10.0.2.15:18312  alive   server  0.6.0  2         dc02
consul03-dc01.dc01  10.0.2.15:8322   alive   server  0.6.0  2         dc01
consul03-dc02.dc02  10.0.2.15:18322  alive   server  0.6.0  2         dc02

client に向けて consul members -wan を実行すると、
何も出力せず、status code 2 を返します。

$ ./consul members -rpc-addr=127.0.0.1:8430 -wan
$ echo $?
2

DC をまたいで DNS を引く

dc01 の Consul に対して、dc02 の node を問い合わせます。

$ dig @127.0.0.1 -p 8630 consul04-dc02.node.dc02.consul A

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.2 <<>> @127.0.0.1 -p 8630 consul04-dc02.node.dc02.consul A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19552
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;consul04-dc02.node.dc02.consul.        IN      A

;; ANSWER SECTION:
consul04-dc02.node.dc02.consul. 60 IN   A       10.0.2.15

;; Query time: 1 msec
;; SERVER: 127.0.0.1#8630(127.0.0.1)
;; WHEN: Tue Dec 15 17:58:09 2015
;; MSG SIZE  rcvd: 94

A レコードが返ってきます。
DNS Interface - Consul by HashiCorp に書いてありますが、

<node>.node[.datacenter].<domain> なので、
同一 DC にいる場合は、 [.datacenter] を省略することができます。

$ dig @127.0.0.1 -p 8630 consul04-dc01.node.consul A

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.2 <<>> @127.0.0.1 -p 8630 consul04-dc01.node.consul A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46271
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;consul04-dc01.node.consul.     IN      A

;; ANSWER SECTION:
consul04-dc01.node.consul. 60   IN      A       10.0.2.15

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8630(127.0.0.1)
;; WHEN: Tue Dec 15 18:05:00 2015
;; MSG SIZE  rcvd: 84

DC をまたいで KV のデータを取得する

まず、通常の KV にデータを PUT して取り出す場合です。
dc01 に PUT します。

$ curl -X PUT -d "dc01-test" http://127.0.0.1:8500/v1/kv/dc01
true
$ curl http://127.0.0.1:8500/v1/kv/dc01?raw
dc01-test
$ curl http://127.0.0.1:8510/v1/kv/dc01?raw
dc01-test
$ curl http://127.0.0.1:8520/v1/kv/dc01?raw
dc01-test
$ curl http://127.0.0.1:8530/v1/kv/dc01?raw
dc01-test

dc01 内で KV のデータが共有されていますね。
この状態で、dc02 の KV を参照すると、

$ curl http://127.0.0.1:18500/v1/kv/dc01?raw

データが入っていませんね。
これは、仕様なのでおかしい挙動ではありません。

追記: 2016-08-23 19:30

KV をまたいでデータを取得するためには、以下のように dc= をつければ OK です。訂正致します。

curl -s 'data' http://127.0.0.1:18500/v1/kv/data?dc=dc02&raw"

ちなみに、consul-replicate というものがあるので、
これを使えば KV のデータをレプリケーションすることができます。
しかし、

  • consul-replicate をどのサーバで動かすか
  • consul-replicate の HA構成はどうするか
  • consul-replicate のレプリケーションが一方向なので、DC 間での同期はどうするのか

といった問題があるので、使いどころが難しそうです。

DC をまたいで KV にデータを入れる

追記: 2016-08-23 19:30

curl -s -X PUT -d 'data' http://127.0.0.1:18500/v1/kv/data?dc=dc02"

のように、dc= をつければ datacenter をまたいで KV にデータをいれることができました。
間違ってた情報を書いていたので、そちらは削除します。

Consul Event は複数の DC に一斉に送れない

consul event には、-datacenter というオプションがありますが、
指定できる DC は一つだけです。
複数の DC に Event を送りたい場合は、DC ごとに実行するようです。

Unbound で DNS forward する

Dnsmasq で Consul DNS に forward して内部 DNS に使っている方が多いと思いますが、
Unbound でも forward できます。

# unbound.conf

server:
    access-control: 127.0.0.0/8 allow
    do-not-query-localhost: no

forward-zone:
    name: "consul"
    forward-addr: 127.0.0.1@8600

Unbound の設定に明るくなくて、
デフォルトの設定に上記設定を追加したらうまく forward できませんでした...
設定が最低限すぎるので、適宜設定を追加してお使いください。

External Services

Consul Service は、Consul クラスタ内のサービスを監視しますが、
External Services を使うと、外部のサービスを監視することができます。

$ curl -X PUT -d '{"Datacenter": "dc01", "Node": "google", "Address": "www.google.com", "Service": {"Service": "search", "Port": 80}}' http://127.0.0.1:8500/v1/catalog/register
true

External Services を使うためには、recursor または recursorsDNS サーバを指定しなくてはなりません。
consul01-dc01(port 8600) は recursor を設定せず、
consul02-dc01(port 8610) は設定しているとします。
その場合、以下の様な実行結果になります。

$ dig @127.0.0.1 -p 8600 search.service.consul

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.2 <<>> @127.0.0.1 -p 8600 search.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56306
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;search.service.consul.         IN      A

;; ANSWER SECTION:
search.service.consul.  15      IN      CNAME   www.google.com.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Tue Dec 15 19:41:34 2015
;; MSG SIZE  rcvd: 88
$ dig @127.0.0.1 -p 8610 search.service.consul

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.2 <<>> @127.0.0.1 -p 8610 search.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26004
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;search.service.consul.         IN      A

;; ANSWER SECTION:
search.service.consul.  15      IN      CNAME   www.google.com.
www.google.com.         149     IN      A       216.58.220.196

;; Query time: 11 msec
;; SERVER: 127.0.0.1#8610(127.0.0.1)
;; WHEN: Tue Dec 15 19:42:01 2015
;; MSG SIZE  rcvd: 118

recursor を設定した consul02-dc01 は、A レコードが返ってきます。
recursor の反映は consul reload ではできませんので、再起動する必要があります。

※追記
recursor を設定していない状態からの反映は consul reload ではできませんが、
recursor を設定している状態からは consul reload で変更を反映することができます。

まとめ

Consul の Multi-DC について検証した結果 +α を紹介しました。
使った設定ファイルは https://gist.github.com/tkuchiki/c4ea89df94c8e2a51b83 に置いてあります。

明日は、Multiple DNS recursors の対応ありがとうございます!(http://fstn.hateblo.jp/entry/2015/02/21/024400)
な、@foostan さんです!