tkuchikiの日記

新ブログ https://blog.tkuchiki.net

fluentd の out forward の secondary を S3 にして信頼性を向上する

オートスケールするサーバ(web、アプリ)に立てている fluentd(以下、sender) から、
ログ集約用の fluentd(以下、aggregator) にデータを送るとき、
aggregator がデータを受け付けられないと sender で buffer すると思います。
この状態でスケールイン(ディスクごとサーバを削除)すると、
buffer していてもデータをロストしてしまいます。
そこで、sendor から aggregator に送れない場合は Amazon S3 に送ることができたのなら、
信頼性を向上できるのではないかと考え実験しました。

検証環境

  • fluentd 0.12.22
  • fluent-plugin-s3 0.6.6
  • ruby 2.3.0

注意点

sender から aggregator にデータを送れない状況を再現するために、
server には fluentd を起動していないホストを指定します。
存在しないホストを指定すると fluentd の起動に失敗するので、存在するホストを指定してください。

file buffer

buffer したデータを比較するため、まず file buffer の実験を行います。
以下の様な設定ファイルで fluentd を起動します。

以下の様に fluent-cat でデータを送ります。

$ echo '{"foo": "bar"}' | fluent-cat debug.test

buffer は msgpack なようなので decode するスクリプトを用意しました。

decode すると以下の様になります。

$ ruby unpack.rb /path/to/forward.debug.test.xxx.log
[1459155557, {"foo"=>"bar"}]

s3 buffer

次は S3 に buffer できるかの実験です。
以下の様な設定ファイルで fluentd を起動します。
実験のため、retry_limitmax_retry_wait を非常に短くしています。

起動できたら file buffer の時と同じようにデータを送ります。

$ echo '{"foo": "bar"}' | fluent-cat debug.test

S3 を見るとデータが保存されていました。
送れていることが確認できたのならば、file buffer のときと同じく復元できるか確認します。

$ aws s3 cp s3://path/to/buffer/forward_debug.test.gz .
$ gunzip forward_debug.test.gz
$ ruby unpack.rb /path/to/forward.debug.test
[1459155737, {"foo"=>"bar"}]

復元できました。
タイムスタンプ以外は同じ結果になったので、
aggregator を復旧すれば buffer からデータを再送できると思います。

まとめ

out forward の secondary を S3 にすることができるか検証しました。
検証に使った設定ファイルのままでは使えないと思いますので調整する必要はあると思いますが、
buffer をロストしにくくできそうですね。
実際に使用する場合は、S3 の buffer からデータを送り直す手順を確認しておくと良いと思います。
primary と secondary の type が違うのは推奨していないようで、
type of secondary output should be same as primary output primary="Fluent::ForwardOutput" secondary="Fluent::S3Output" のような warn が出力されます。
secondary を S3 にした場合は問題なさそうな挙動でしたが、
他の plugin ではどうなるかわかりませんのでご注意ください。

プロセスのメモリ使用量とCPU使用率などが取れる mackerel-plugin-linux-proc-stats をリリースしました

プロセスのメモリ使用量と CPU 使用率などのメトリクスが取れる、
mackerel-plugin-linux-proc-stats をリリースしました。

Installation

https://github.com/tkuchiki/mackerel-plugin-linux-proc-stats/releases
からバイナリをダウンロードして解凍してください。

Usage

$ ./mackerel-plugin-linux-proc-stats --help
Usage of ./mackerel-plugin-linux-proc-stats:
  -follow-child-processes
        Follow child processes
  -metric-key-prefix string
        Metric key prefix
  -pid string
        PID
  -pidfile string
        PID file
  -tempfile string
        Temp file name
  -version
        Version

このプラグイン独自のオプションを説明すると、

  • pid : PID を指定
  • pidfile: PIDファイルの path
  • follow-child-processes: 子プロセスまで集計するか

となっています。
follow-child-processes について説明するために実行例を示します。
nginx の master と worker プロセスが各1つずつ起動しているとします。
その状態で master プロセスの情報だけ取得する場合は、以下のように実行します。

$ ./mackerel-plugin-linux-proc-stats -pidfile /var/run/nginx.pid
nginx_process.cpu.usage 0.000000        1458808477
nginx_process.memory.vsize      107450368.000000        1458808477
nginx_process.memory.rss        3399680.000000  1458808477
nginx_process.num.running       0.000000        1458808477
nginx_process.num.processes     1.000000        1458808477
nginx_process.num.threads       1.000000        1458808477

master と worker プロセス両方の情報を合算して取得する場合は、以下のように実行します。

$ ./mackerel-plugin-linux-proc-stats -pidfile /var/run/nginx.pid -follow-child-processes
nginx_process.num.running       0.000000        1458808496
nginx_process.num.processes     2.000000        1458808496
nginx_process.num.threads       2.000000        1458808496
nginx_process.cpu.usage 0.000095        1458808496
nginx_process.memory.vsize      215269376.000000        1458808496
nginx_process.memory.rss        7966720.000000  1458808496

子プロセスまでしか追わないので、孫プロセスは対象外です(実装するか検討中)。

メトリクスについて

このプラグインは、/proc/PID/stat を parse しています。

  • num.running: 3番目が R かどうか
  • num.processes: 指定したプロセスのプロセス数(follow-child-processes をつけた場合は子プロセス含む)
  • num.threads: 20番目の値
  • cpu.usage: 15, 16 , 17, 22番目の値 とプロセスの起動時間、uptimegetconf CLK_TCK の値を使って計算
  • memory.vsize: 23番目の値
  • memory.rss: 24番目の値

num.running については、実行時間が長い処理を行わない限りは R にならないので、0 の場合がほとんどです。

/proc/PID/stat の例を載せておきます。

10440 (nginx) S 1 10440 10440 0 -1 4202816 71 0 0 0 0 0 0 0 20 0 1 0 364149088 107450368 830 18446744073709551615 1 1 0 0 0 0 0 1073746048 402745863 18446744073709551615 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0

IAM の Switch Role を捗らせる

AWS のクロスアカウントアクセスを利用すると、
IAM ユーザを AWS アカウントごとに作成しなくても良くなり管理が容易になるのですが、
Switch Role する アカウントが多いと、履歴が 5 件しかないのでアカウントとロールを再入力しなくてはならないことが増えてきます。

ロールを切り替えるユーザーアクセス権限の付与 を見ると、

https://signin.aws.amazon.com/switchrole?account=YourAccountIDorAliasHere&roleName=pathIfAny/YourRoleNameHere

とあります。
Alias は以下を例にすると Your_AWS_Account_ID です(参考: AWS アカウント ID とその別名)。

https://Your_AWS_Account_ID.signin.aws.amazon.com/console/

https://signin.aws.amazon.com/switchrole?YourAccount=hogehoge&roleName=YourRole にアクセスすると、
アカウントとロールが入力された状態でアクセスすることができます。

f:id:tkuchiki:20160222121321p:plain

また、ロールの切り替え(AWS マネジメントコンソール) を見ると、

https://signin.aws.amazon.com/switchrole?account=account_id_number&roleName=role_name&displayName=text_to_display

とあり、 displayName を指定すると表示名も入力した状態にできます。
また、color=カラーコード で色を指定することもできます。
指定できる色は左から順に、

  • F2B0A9 (何も指定しなくてもこれになります)
  • FBBF93
  • FAD791
  • B7CA9D
  • 99BCE3

です(右端の黒は指定方法がわかりませんでした)。
color についてはドキュメントに書いていないようでしたので、 変更される可能性があります。

最後に、account, roleName, displayName, color を全部指定した場合の例を示します。

https://signin.aws.amazon.com/switchrole?account=YourAccount&roleName=YourRole&displayName=YourDisplayName&color=99BCE3 にアクセスすると、

f:id:tkuchiki:20160222121332p:plain

すべて入力済みになります。
この URL をブックマークしておくと、各項目を入力しなおさなくても良くなるので便利です。

まとめ

Switch Role の URL の query string に、

  • account = alias または account ID
  • roleName = ロール名
  • displayName = 表示名
  • color = カラーコード

を指定すると、各項目を入力済みの状態にできるので便利です。

setusergroups の RPM spec ファイル

setusergroups については、作者の tokuhirom さんのブログを御覧ください。

supplementary groups をサポートする setuidgid であるところの setusergroups.c 書いた

supplementary groups をサポートした setuidgid が欲しいケースがある。

これを相談されたので RPM の spec ファイルを書きました。
以下を ~/rpmbuild/SPECS/setusergroups.spec として保存して、

curl -L https://github.com/tokuhirom/setusergroups/archive/master.zip > ~/rpmbuild/SOURCES/master.zip
rpmbuild -ba ~/rpmbuild/SPECS/setusergroups.spec

RPM を作成できます。
autoconf のバージョンが 2.68 以上でないと build できないので、
CentOS 6 で build する場合は base repo 以外のものを使う必要があります。

norikra-listener-zabbix 0.2.0 をリリースしました

norikra-listener-zabbix (rubygems) 0.2.0 をリリースしました。

変更点

group の記述を変更

port を廃止し、ZABBIX_SERVER:[PORT] と記述するようになりました。
-- group ZABBIX(localhost:10051, zabbix host) のように記述します。

IPv6 サポート

IPv6 に対応しました。
-- group ZABBIX([::1]:10051, zabbix host) のように、[ ]IPアドレスをくくらないとエラーなります。

groupprefix_item_key を省略可能に

prefix の指定が必須ではなくなりました。
指定しない場合は、列名がそのままアイテムキーとして使用されます。
列の別名に . を使いたい場合、$ を指定すると . に置き換えてアイテムキーとして使用します。 なぜこのような仕様になっているかというと、

Identifiers cannot contain the "." (dot) character, i.e. "vol.price" is not a valid identifier for the rename syntax.

とあるように、. が使えないので、Zabbix のアイテムキーとして使えない文字列かつ列の別名に使える記号として $ を採用しています(あまり美しくないですが...)。

例は以下のとおりです。

SELECT sum(foo) AS `bar$foo$sum`, avg(foo) AS `bar$foo$avg` FROM test_table.win:time_batch(1 min)

参考

Norikra の集計結果を直接 Zabbix に送る norikra-listener-zabbix をリリースしました

追記(2016/02/08 15:30):0.2.0 で group の記述方式を変更しましたので、
norikra-listener-zabbix 0.2.0 をリリースしました をご確認ください。

Norikra から直接 Zabbix にデータを送る norikra-listener-zabbix (rubygems) をリリースしました。

Zabbix へデータを送信するコードのほとんどは、
fujiwara/fluent-plugin-zabbix を使わせていただきました。ありがとうございます。

Installation

gem install norikra-listener-zabbix

Norikra をインストールした gem で gem install すれば自動で有効になります。

Usage

Group を以下のように設定します。

ZABBIX(zabbix_server, zabbix_host, preifx_item_key, [port=10051])
  • zabbix_server: localhost
  • zabbix_host: test server
  • prefix_item_key: nginx

の場合は、以下のとおりです。

ZABBIX(localhost, test server, nginx)

prefix_item_key については、アイテムキーの prefix です。
port は Zabbix Server デフォルトの 10051 を使っている場合は省略できます。

利用例

秒間のリクエスト数を HTTP ステータスコードごとに集計する場合を考えます。

SQL

ステータスコードごとに COUNT して秒間のデータにします。

SELECT
  COUNT(1, 200 <= status AND status <= 299) / 60 AS rate_2xx,
  COUNT(1, 300 <= status AND status <= 399) / 60 AS rate_3xx,
  COUNT(1, 400 <= status AND status <= 499) / 60 AS rate_4xx,
  COUNT(1, 500 <= status AND status <= 599) / 60 AS rate_5xx
FROM nginx_status.win:time_batch(1 min)

Zabbix

アイテム

prefix_item_key とSQL の列名(rate_2xx など) を . で連結したアイテムを作成します。 prefix_item_key は nginx、列名は rate_2xx, rate_3xx, rate_4xx, rate_5xx です。

作成するアイテムは以下のようになります。

  • タイプ: Zabbix トラッパー
  • キー: nginx.rate_2xx, nginx.rate_3xx, nginx.rate_4xx, nginx.rate_5xx
  • データ型: 数値 (浮動小数点)

1 つの SQL で複数のアイテムにデータを送信することができます。

グラフ

グラフは適宜作成してください。

f:id:tkuchiki:20160205011732p:plain

2xx のデータしかないのであまり良くない例ですが、
それぞれのステータスコードのリクエストが送られてくれば集計されます。

その他

Zabbix 周りのコードはほとんど fujiwara/fluent-plugin-zabbix を使わせていただきましたが、
一部変更した部分があります。
また、実装する上でハマったところがあったのでそのことに触れておきます。

Zabbix 周りの改良点

Zabbix Server にデータを送信すると、

{
  "response" => "success",
  "info" => "Processed 2 Failed 0 Total 2 Seconds spent 0.000103"
}

のようなレスポンスが返って来ます。
このとき、info の Failed が 1 以上だったり、Processed が 0 で全て Failed というケースでも response は success になります。
Processed が 0 でなければ 1 つ以上データが送れていることになるので良いのですが、
全て Failed した場合は失敗にしたほうがわかり易いと思い、 warn でログを出すようにしています
(実装している時、ログに何も出ないのにデータが送れていなくて理解するのに時間がかかりました)。
全て Failed になるケースは、以下の 2 つを確認しています。

  • Zabbix ホスト名が間違っている
  • アイテムキーが間違っている

split(",") だけだと空白が含まれる

Norikra::Listener::Zabbix.initializeargument, で split するときに、
ZABBIX(zabbix_server, zabbix_host, preifx_item_key)(わかりにくいですが , の後ろにスペースがあります)と書いて、
zabbix host とアイテムキーにスペースが含まれて正常に動作しない問題で1時間くらい嵌まりました...
そこで、スペースを気にしなくても良いように split したあとに strip しています。

def self.parse_argument(args)
  args.split(",").map(&:strip)
end

Listener Plugin を書く方は、この処理をしておくと変なところで嵌らなくて良いのでおすすめです。

まとめ

Norikra Listener Plugin の norikra-listener-zabbix をリリースしました。
是非お使いください!

Consul Multiple Datacenters 検証結果 +α

この記事は、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 さんです!