Consulクラスタ内でファイル共有する Fileconsul というツールをつくってみた
追記(2014/09/23) しました。
はじめに
Consul使ってますか?
最近は 0.4 がリリースされ、大幅な機能追加によってサービスディスカバリとしてでなく、オーケストレーションツールとして注目を集めて来ています。
また、プロダクションでの使用事例やSoftware Designに掲載されるなど(http://gihyo.jp/magazine/SD)、国内でも勢いをみせています。
個人的にはオーケストレーションツールとして利用したいと思っていますが、また検証段階といったところです(個人で遊んでいるレベル)。
Consul + Capistrano でオーケストレーションさせてみた - log.fstn
オーケストレーションツールとしてのConsulの使い方 - Qiita
そんなConsulですが、利用にあたって下記のようなファイルを各ノードに設置する必要があります。
- Configuration(http://www.consul.io/docs/agent/options.html) のファイル
- Watches(http://www.consul.io/docs/agent/watches.html) のハンドラースクリプト
- Service Definitions(http://www.consul.io/docs/agent/services.html) のファイル
- Check Definitions(http://www.consul.io/docs/agent/checks.html) のファイル
- Service Definitions/Check Definitionsのチェックスクリプト
ファイルの配布方法に関する考察
Consulに必要なファイルは何かしらの方法で各ノードに配布する必要があります。 また、これらのファイルは運用中にアップデートされることが容易に考えられるので、クラスタの各ノードにファイルを配布するような仕組みも必要です。
既存のツールを利用する場合は、Capistranoなどのデプロイツールを利用して各ノードにファイルを配布する方法が考えられますが、配布用のタスクを書く必要がありますし、ノード数が多いと配布時間も気になってきます。
なお先日のRubyKaigi 2014 で Serf(http://www.serfdom.io/) を利用したデプロイツール Mamiya (https://github.com/sorah/mamiya) の紹介がありました。
RubyKaigi 2014 | Scalable deployments - How we deploy Rails app to 100+ hosts in a minute
配布対象のノードが多い場合は、Capistranoのようにデプロイするためのマシンを用意してそこから配布するのではなく、オーケストレーションツールでイベントを発行して、各ノードがそれぞれダウンロードするような仕組みの方が効率が良さそうです。
Fileconsul の紹介
既存のツールを利用して各種ファイルを配布するのもいいのですが、どうせなら
- Consulの機能を利用したい
- 配布対象を意識したくない(Capistarnoのように対象を指定して配布するようなことはしたくない)
- 複雑な設定やCapistranoのタスクのようなものを作成したくない
- ノードが増えても配布時間がなるべくかからないようにしたい
- 対象ノードの環境は変えたくない(特定の言語のバージョンやパッケージに依存しないようにしたい)
など考えて、Fileconsul というものを作りました。
FileconsulはConsulクラスタ内でファイル共有するためのツールであり、以下の様な特徴があります
- ConsulのK/V Storeを用いてファイルを共有する(ファイルのデータをvalueとして保持する)
- 共有できるファイルは1つあたり512KBの制限がある(ConsulのK/V Storeの限界値)
- cliでファイルのアップロード(pushコマンド)、ダウンロード(pullコマンド)が簡単に行える
- アップロードされたファイルは即座にクラスタ内で共有される
- Goで出来ているためバイナリひとつで動き、対象ノードの環境に左右されない
ファイルの容量制限があるため、あまり大きなファイルは共有できませんが、512KBなら設定ファイルや簡単なスクリプト程度なら十分許容できると思います。 またK/V Storeを利用することでConsulの恩恵が受けられます。
Fileconsul の使い方
ほぼREADME.md(https://github.com/foostan/fileconsul/blob/master/README.md) の再掲ですが使い方を紹介します。
Demo環境の用意
Fileconsulのレポジトリにデモ環境用のDockerfileがありますので、これを利用します。
$ git clone https://github.com/foostan/fileconsul.git $ cd fileconsul/demo $ docker build -t fileconsul .
Dockerの環境がない場合は Docker Documentation を参照して下さい。 Mac/Windows なら boot2docker で簡単に環境が整います。
コンテナとConsul agentの起動
Consulではクラスタ内でserver agentが必要なのでデモ環境でもserverとclientを起動しています。 ですが、Fileconsulの挙動はserver側もclient側も特に変わりません。
Consul server 側
$ docker run -h server -i -t fileconsul root@server:/# consul agent -data-dir=/tmp/consul -server -bootstrap-expect 1 & ==> WARNING: BootstrapExpect Mode is specified as 1; this is the same as Bootstrap mode. ==> WARNING: Bootstrap mode enabled! Do not enable unless necessary ==> WARNING: It is highly recommended to set GOMAXPROCS higher than 1 ==> Starting Consul agent... ==> Starting Consul agent RPC... ==> Consul agent running! Node name: 'server' Datacenter: 'dc1' Server: true (bootstrap: true) Client Addr: 127.0.0.1 (HTTP: 8500, DNS: 8600, RPC: 8400) Cluster Addr: 172.17.0.6 (LAN: 8301, WAN: 8302) Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false --- omitted below ---
Consul client 側
$ docker run -h client -i -t fileconsul root@client:/# consul agent -data-dir=/tmp/consul -join 172.17.0.6 & ==> WARNING: It is highly recommended to set GOMAXPROCS higher than 1 ==> Starting Consul agent... ==> Starting Consul agent RPC... ==> Joining cluster... Join completed. Synced with 1 initial agents ==> Consul agent running! Node name: 'client' Datacenter: 'dc1' Server: false (bootstrap: false) Client Addr: 127.0.0.1 (HTTP: 8500, DNS: 8600, RPC: 8400) Cluster Addr: 172.17.0.5 (LAN: 8301, WAN: 8302) Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false --- omitted below ---
Fileconsul を使ってみる
サーバ側でstatusコマンドとpushコマンドを使用する
fileconsul status
で local file(手元のファイル)とremote file(K/V Store上のファイル)との差分を表示します。
Consul clusterの初回構築時はK/V Storeが空なので、fileconsul push
でファイルをアップロード(K/V Storeに保存)します。
root@server:/# cd /consul/share/ root@server:/consul/share# fileconsul status Changes to be pushed: (use "fileconsul push [command options]" to synchronize local files) add remote file: bin/ntp add remote file: bin/apache2 add remote file: bin/loadavg add remote file: config/service/apache2.json add remote file: config/service/ntp.json add remote file: config/template/server/check_loadavg.json add remote file: config/template/server/service_apache2.json add remote file: config/template/server/agent_server.json add remote file: config/template/server/service_ntp.json add remote file: config/template/client/check_loadavg.json add remote file: config/template/client/agent_client.json add remote file: config/template/client/service_ntp.json add remote file: config/check/loadavg.json root@server:/consul/share# fileconsul push push new file: bin/ntp push new file: bin/apache2 push new file: bin/loadavg push new file: config/service/apache2.json push new file: config/service/ntp.json push new file: config/template/server/check_loadavg.json push new file: config/template/server/service_apache2.json push new file: config/template/server/agent_server.json push new file: config/template/server/service_ntp.json push new file: config/template/client/check_loadavg.json push new file: config/template/client/agent_client.json push new file: config/template/client/service_ntp.json push new file: config/check/loadavg.json
client側でファイルを編集してpushする
共有されているファイルを編集してfileconsul status
すると、編集されているファイルが確認できます。
この状態でfileconsul push
すると編集されたファイルの内容がK/V Storeに反映されます。
root@server:/# cd /consul/share/ root@client:/consul/share# vi bin/apache2 # edit a file root@client:/consul/share# fileconsul status Changes to be pushed: (use "fileconsul push [command options]" to synchronize local files) modify remote file: bin/apache2 Changes to be pulled: (use "fileconsul pull [command options]" to synchronize remote files) modify local file: bin/apache2 root@client:/consul/share# fileconsul push push modified file: bin/apache2
server側でpullする
client側で編集したファイルをpushしたため、server側でfileconsul status
すると、編集されたファイルが確認できます。
この状態でfileconsul pull
すると、編集されたファイルが同期されます。
root@server:/consul/share# fileconsul status Changes to be pushed: (use "fileconsul push [command options]" to synchronize local files) modify remote file: bin/apache2 Changes to be pulled: (use "fileconsul pull [command options]" to synchronize remote files) modify local file: bin/apache2 root@server:/consul/share# fileconsul pull Synchronize remote files: modified: bin/apache2 Already up-to-date.
さいごに
Fileconsulを利用することでConsulクラスタ内でファイルを共有することができます。
Consulを利用していると様々なファイルを各ノードで共有したくなりますが、Fileconsulを利用すると既存のツールに比べて簡単に共有できるようになると思います。
また、Consul 0.4 で追加されたwatch機能を利用すれば、いちいち fileconsul pull
をすることなくファイルの同期が出来るようになります。
今後はFileconsulを含めたConsulの有益な使い方を考えていければと思います。
ちなみにFileconsulはGoの勉強がてら作り始めたものなので、この書き方おかしいよとか、こんな風に書くとGoっぽいよ、といったご指摘も頂けるとありがたいです。
追記(2014/09/23)
Consul Google Group にて Fileconsul を紹介したところ、早速フィードバックを頂けたので追記します。
やりとりの内容はこちら
Consul Google Group: Released the tool of sharing small files in a Consul cluster
@armon からのフィードバック
似たようなプロジェクトがあるから見てみてとのこと。
fsconsulはファイルをダウンロードすることしか出来ないらしく、その点Fileconsulはアップロードも出来る点が有益とのこと。
メインのコミッターからカジュアルに意見を頂けるコミュニティがあるのはありがたいし、フィードバックもらえて素直にうれしいです。
あとConsulの中の人はfsconsulのような小さなツールまで把握してるんですね。フィードバックも10分程度で貰えたし、スピード感あります。
Alvaro からの質問
Alvaro Miranda Aguilera - 基本情報 - Google+
各コマンドの終了ステータスを教えてほしいとのこと。
終了ステータスを見て次のアクションに繋げたいらしいので、この辺りも実装でフォローしていくべきなのかな?
実際、終了ステータスを明確に返すツールってどれぐらいあるんだろうか。