Consul Template + Registrator で、コンテナ上のWebサーバをHAProxyへリアルタイムに登録してみる
はじめに
先日、Consul Templateという便利そうなツールがHashiCorpから発表されました。 Introducing Consul Template - HashiCorp
何かおもしろいこと出来ないかなっと思ってちょっと考えていたら、Registrator(progrium/registrator · GitHub)と相性が良さそうだったので組み合わせて使ってみた、というはなしを本エントリでまとめました。
Consul Template について
Consul Templateは、Consulに登録されているサービスやK/Vの内容を元に、ミドルウェア等の設定ファイルを生成するためのツールです。 また、Consulを常に監視し、内容が変化するとリアルタイムに設定ファイルを更新して指定したコマンドを発行することができます。
ユースケースとして、HAProxy配下にWebサーバを配置する構成での利用が挙げられています。
この構成をとる場合、HAProxyの設定ファイルには対象のWebサーバを全て記述する必要があり、
Webサーバを追加するときや削除するときはその度に設定ファイルを更新して、リロードしてやる必要があります。
しかしConsul Template を利用すると、
- WebサーバのConsulのクラスタへのJoinやLeaveを検知
- HAProxyの設定ファイルを更新
- リロードして設定を反映
これらを全て簡単に自動で行えるようになります。
なおテンプレートは、template - The Go Programming Language の記述に従って柔軟に書くことが出来ます。
詳しい使い方や仕様に関しては、上記の記事かレポジトリを直接参照してください(相変わらずREADMEがしっかりしてる)。
hashicorp/consul-template · GitHub
Registrator について
Registratorは、Dockerで立ち上げたコンテナに関する情報を、Consul や etcd、SkyDNS 2へ登録するためのツールです。
詳しい使い方や仕様に関しては、レポジトリを直接参照してください(こちらのREADMEもかなり丁寧です)。
概要
今回はタイトルにあるように、Consul TemplateとRegistratorを組み合わせて、コンテナ上のWebサーバをHAProxyへリアルタイムに登録してみます。
1台のマシン上で
- Docker
- Consul
- Consul Template
- Registrator
- HAProxy
を動かし、その上にWebサーバを提供するコンテナを立ち上げます。 サービスへのエンドポイントはこのサーバ(今回の場合192.168.33.11)の80ポートとなります。 なお通常だと、コンテナでサービスを提供する場合はコンテナ側のポートを意識する必要がありますが、Registratorを利用することで意識しないで済みます。
環境構築
上図の環境を構築していきます。
VMの準備
- Docker
- Consul
- Consul Template
- Registrator
をインストールします。
$ git clone https://github.com/foostan/consul-with-docker.git $ cd consul-with-docker $ vagrant up
十数分待つとできあがり。
※ ansibleの実行環境が必要
以降はこのVM内で作業します。
$ vagrant ssh vagrant@node-1:~$
Consul agent 起動
今回は1台しか使わないので、-server
と -bootstrap
オプションを付けておきます。
vagrant@node-1:~$ consul agent -data-dir=/tmp/consul -server -bootstrap ==> 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: 'node-1' Datacenter: 'dc1' Server: true (bootstrap: true) Client Addr: 127.0.0.1 (HTTP: 8500, DNS: 8600, RPC: 8400) Cluster Addr: 10.0.2.15 (LAN: 8301, WAN: 8302) Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
Consul template 起動
vagrant@node-1:~$ sudo consul-template\ -consul=localhost:8500\ -template=/vagrant/haproxy.ctmpl:/etc/haproxy/haproxy.cfg:"/etc/init.d/haproxy reload"
template.ctmpl の内容はこちら
global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy user haproxy group haproxy daemon defaults log global mode http option httplog option dontlognull contimeout 5000 clitimeout 50000 srvtimeout 50000 errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http frontend main *:80 default_backend tinyweb backend tinyweb balance roundrobin{{range service "tinyweb"}} server {{.ID}} {{.Address}}:{{.Port}} check{{end}}
デフォルトのhaproxy.cfgにfrontend
とbackend
を追記しています。
Registrator 起動
vagrant@node-1:~$ registrator consul:
以上で準備完了です。
Webサーバイメージの作成とコンテナの起動
HAProxy で振り分ける先となるWebを構築していきます。
イメージ作成
これ用のDockerfileを用意したので、ビルドしてイメージを作成します。
vagrant@node-1:~$ docker build -t tinyweb /vagrant/tinyweb/
Dockerfileの中身はこちら
FROM ubuntu:trusty MAINTAINER foostan ks@fstn.jp EXPOSE 80 CMD while true; do ( echo "HTTP/1.0 200 Ok"; echo; echo `hostname` ) | nc -l 80; done
trustyをベースにして、ncコマンドで hostname
を返すWebサーバを80ポートに立ちあげています。
コンテナの起動
docker run -p 80 -d tinyweb c437b2717b76dde8c31211fea09bc5bb60b8c16892161db24cb31a1b49543ae1 vagrant@node-1:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c437b2717b76 foostan/tinyweb:latest "\"/bin/sh -c 'while 5 minutes ago Up 5 minutes 0.0.0.0:49178->80/tcp romantic_carson
動作確認
コンテナを立ち上げた時点で、RegistratorによってConsulにserviceが追加され、Consul Templateによって、HAProxyの設定ファイルが更新されています。
Consulのserviceを見てみます。
$ curl -s localhost:8500/v1/catalog/services | jq . { "consul": [], "tinyweb": [] } vagrant@node-1:~$ curl -s localhost:8500/v1/catalog/service/tinyweb | jq . [ { "Node": "node-1", "Address": "10.0.2.15", "ServiceID": "node-1:romantic_carson:80", "ServiceName": "tinyweb", "ServiceTags": null, "ServicePort": 49178 } ]
tinyweb
サービスが新たに追加され、ノードのIPやPortが登録されていることが確認できます。
続いて、HAProxyの設定ファイルを見てみます。
vagrant@node-1:~$ tail -n 7 /etc/haproxy/haproxy.cfg frontend main *:80 default_backend tinyweb backend tinyweb balance roundrobin server node-1:romantic_carson:80 10.0.2.15:49178 check
登録されていることがわかります。
実際にアクセスしてみます。
vagrant@node-1:~$ curl localhost c437b2717b76
VM外からでももちろんOK
$ curl 192.168.33.11 c437b2717b76
複数のコンテナを立てたり消したりしてみる
5台追加してみる。
vagrant@node-1:~$ docker run -d -p 80 foostan/tinyweb df9d19738e7610c448478c94ec10ab63259a2c78cfbe6437de2d3e7a8870b63e vagrant@node-1:~$ docker run -d -p 80 foostan/tinyweb b7ddc05c645490c21c18b98161bef0994b9c2ad366ff6e85a0b45652ff204e6d vagrant@node-1:~$ docker run -d -p 80 foostan/tinyweb 0c31735035d4da4519ebbe7a6957ddb9bc1f865e5448c9ab838a742bff3178d3 vagrant@node-1:~$ docker run -d -p 80 foostan/tinyweb 8be6547a4a418faf34be1727b40386c149dd34d41ce5f8efb8c37d37050849ee vagrant@node-1:~$ docker run -d -p 80 foostan/tinyweb a7969a2dfa63d137d77369b5e9c519b5565ec0bc2b14126c300b24c11c25deb5
HAProxyの設定に反映されていることが確認できます。
vagrant@node-1:~$ tail -n 12 /etc/haproxy/haproxy.cfg frontend main *:80 default_backend tinyweb backend tinyweb balance roundrobin server node-1:hopeful_newton:80 10.0.2.15:49181 check server node-1:hopeful_torvalds:80 10.0.2.15:49179 check server node-1:naughty_elion:80 10.0.2.15:49182 check server node-1:romantic_carson:80 10.0.2.15:49178 check server node-1:sad_darwin:80 10.0.2.15:49180 check server node-1:thirsty_kowalevski:80 10.0.2.15:49183 check
各コンテナにアクセスしていることがわかります
$ curl 192.168.33.11 0c31735035d4 $ curl 192.168.33.11 df9d19738e76 $ curl 192.168.33.11 8be6547a4a41 $ curl 192.168.33.11 c437b2717b76 $ curl 192.168.33.11 b7ddc05c6454 $ curl 192.168.33.11 a7969a2dfa63
削除も問題ないです
vagrant@node-1:~$ docker kill a7969a2dfa63 b7ddc05c6454 c437b2717b76 a7969a2dfa63 b7ddc05c6454 c437b2717b76 vagrant@node-1:~$ tail -n 9 /etc/haproxy/haproxy.cfg frontend main *:80 default_backend tinyweb backend tinyweb balance roundrobin server node-1:hopeful_newton:80 10.0.2.15:49181 check server node-1:hopeful_torvalds:80 10.0.2.15:49179 check server node-1:naughty_elion:80 10.0.2.15:49182 check
おわりに
Consul TemplateとRegistratorの相性が予想以上によく検証もすんなり出来ました。 今回はConsul Templateの一例を載せましたが、汎用性が高いため、まだまだ色々できそうです。
本エントリがConsulやDockerを使用する上で、何かの参考になれば幸いです。