LoginSignup
62

More than 5 years have passed since last update.

Consulを使ってDockerの名前解決を簡単に実現する

Last updated at Posted at 2014-12-06

Dockerでサービス群をまとめて立ち上げる時はIPは毎回変わっちゃうので、名前解決が重要になるわけですが、これが結構面倒。
元々、figを使ってたので、linksに書いてればその名前でhost名を書き換えてくれてたので重宝してたんですが、これ起動順も制御してるっぽいので、双方向通信にすると循環参照でエラーに成って起動しません><

なので、手軽にやる方法を色々調べてみたのですが、Consulを使うのが簡単そうなので、そちらを試してみました。

追記:
CentOS7で動かす環境も作ってみたので、読むのメンドいから、取りあえず動かしたいって人はこっちをどうぞ。

Consulって何?

まず、そもそもConsulって何? ってとこなのですが、

  • Service Discovery
  • Health Check
  • Key/Value Store

を提供してくれるオーケストラレーションの一種です。私もまだしっかりとは理解できてないのですが、今回この"Service Discovery"が最初からDNSインタフェースを提供しているということで採用しました。

コンテナ上のresolved.confの参照を変更

Consulを準備する前に、Dockerコンテナ上の名前解決の設定を変更します。これを変更することで、後述する方法で、docekr0にバインドしたDNSをすべてのDockerコンテナから利用出来るようになります。
Linux(RH7系)とMacOSでboot2dockerを使った場合で、設定方法に差分があるので両方記載。
ちなみに、RH7系だといくつかのサイトで説明してある/etc/default/dockerじゃなくて、/etc/sysconfig/dockerを見るようなので要注意。
※ どうもRH7だと、セキュリティの設定が違うのか、Docker0にforwardしたサーバを探せないようなのでRUNした時点でresolve.confを変更しないと動きません。この辺、詳しい方居ましたらアドバイス頂ければと...

Linux(CentOS 7)の場合

$ echo "OPTIONS=--selinux-enabled --dns 172.17.42.1 --dns `grep nameserver /etc/resolv.conf|head -1|awk '{print $2}'` --dns-search service.consul" > /etc/sysconfig/docker
$ 
$ # 上記設定を変更するために再起動
$ sudo systemctl stop docker
$ sudo systemctl start docker

MacOSでboot2dockerを使ってる場合

$ boot2docker ssh sudo "ash -c \"echo EXTRA_ARGS=\'--dns 172.17.42.1 --dns $(scutil --dns | awk -F ': ' '/nameserver/{print $2}' | head -1) --dns-search service.consul\' > /var/lib/boot2docker/profile\""
$
$ # 上記設定を変更するために再起動
$ boot2docker stop    
$ boot2docker up

これでDockerコンテナのresolve.confにdocker0が追加されるようになる。

Consulサービスを起動

つづいて、Consulのサービスをクラスタとして起動する。
まずは、Consul組込み済みのコンテナを取得。

$ docker pull progrium/consul

取得が終わったら、1台目のノードを立ち上げ。管理用ポート(HTTP)はlocalhostに、DNSはdocker0にバインドする。

$ docker run -d -p 8400:8400 -p 8500:8500 -p 172.17.42.1:53:53/udp --name node1 -h node1 progrium/consul -server -bootstrap-expect 3

2台目のノードからは、この1台目のノードに接続する形になるので、IPアドレスを取得。

$ JOIN_IP="$(docker inspect -f '{{.NetworkSettings.IPAddress}}' node1)"
$ echo $JOIN_IP

2台目以降のノードをConsulサービスのクラスタに追加。1つのクラスタに対して推奨は3から5くらいのノードらしいので、とりあえず3つ追加。

$ docker run -d -h node2 progrium/consul -server -join $JOIN_IP
$ docker run -d -h node3 progrium/consul -server -join $JOIN_IP

下記の通り、HTTPベースでノードの状態が確認できる。

$ curl localhost:8500/v1/catalog/nodes
[{"Node":"node1","Address":"172.17.0.2"},{"Node":"node2","Address":"172.17.0.3"},{"Node":"node3","Address":"172.17.0.4"}]

また 'http://localhost:8500/ui/' にアクセスすることで、Web画面でも確認ができる。結構便利。

ss01.png

登録されたDNSの確認

続いて、Dockerコンテナ上からconsulに登録されたホスト名が引けることを確認。

$ docker run --rm -it koduki/centos7 /bin/bash

まずはノード単位。{host name}.node.consulの形式で引ける。

docker% ping node1.node.consul
PING node1.node.consul (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.055 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.091 ms
^C
--- node1.node.consul ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.055/0.073/0.091/0.018 ms
docker%  ping node2.node.consul
PING node2.node.consul (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.096 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.076 ms
^C
--- node2.node.consul ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.076/0.086/0.096/0.010 msl

次はサービス名。{service name}.service.consulの形式で引ける。

docker% ping consul.service.consul
PING consul.service.consul (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.090 ms
64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.213 ms
^C
--- consul.service.consul ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.076/0.087/0.098/0.011 ms

docker%  ping consul.service.consul
PING consul.service.consul (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.105 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.181 ms
^C
--- consul.service.consul ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.105/0.143/0.181/0.038 ms 

こんな感じで、ラウンドロビンで複数のIPが引けてることが分かる。サービス用のDNSを毎回建てる必要無し! すばらっ!

サービスを登録

Consulサービスのクラスタは出来たので、新規にHTTPDなど独自のサービスも登録してみる。

まずは、クラスタに追加したいコンテナにconsulをインストール。

$ docker run --rm -it koduki/centos7 /bin/bash
docker# wget https://dl.bintray.com/mitchellh/consul/0.4.1_linux_amd64.zip && \
unzip 0.4.1_linux_amd64.zip && \
mv consul /usr/local/bin && \
rm -f 0.4.1_linux_amd64.zip 

続いて、サービスの定義ファイルを書くディレクトリを作成。

docker# mkdir -p /etc/consul/conf.d

サービスは下記の用にJSONで指定する。

/etc/consul/conf.d/httpd.json

{"service": {"name": "tinyweb",  "tags": ["tinyweb", "web"],  "port": 8000}} 

ここまでで、準備は完了。
最後に対象のサービスを起動して、consulのクライアントとして登録する。

docker# python -m SimpleHTTPServer &
docker# consul agent -data-dir=tmp/consul -config-dir=/etc/consul/conf.d -join=consul.service.consul

これで、tinywebが新規にサービスとしてクラスタに登録された。
新規にDockerコンテナを立ち上げて適切に登録されているかを確認する。

$ docker run --rm -it koduki/centos7 /bin/bash
docker# curl consul.service.consul:8500/v1/catalog/nodes
[{"Node":"a3fcf553511f","Address":"172.17.0.5"},{"Node":"node1","Address":"172.17.0.2"},{"Node":"node2","Address":"172.17.0.3"},{"Node":"node3","Address":"172.17.0.4"}]
docker# curl consul.service.consul:8500/v1/catalog/services
{"consul":[],"tinyweb":["tinyweb","web"]}[root@538fbef09ddf /]# 

新規ノードとして"a3fcf553511f"、新規サービスとして"tinyweb"が登録されてることが分かる。
もちろん、この状態でサービスのDNSは適切に登録されているので、下記のようにアクセスが出来る。

docker# curl -LI tinyweb.service.consul:8000  -o /dev/null -w '%{http_code}\n' -s
200

こんな感じで、Dockerコンテナの起動時にconsul agentを起動するように設定すれば、DNS管理は特に何もしなくてもOK! すばらっ!

まとめ

今回は、名前解決が目的だったので他のConsulの機能は基本調べてないけど、クラスタ参加時に特定の処理をしたり、サービスに対して一括してコマンド送ったりも出来たり、内蔵のKVSでデータ管理及び変更に起因するイベント管理をしたりできるので、クラウド環境でサーバが増減する環境では必須の機能かも。
オーケストレーションは、初めて触ったけど、思ったより簡単だったし、ちょっとしたUIもあるので、かなり良さ気。色々使い方を研究しないと。

それでは、Happy Hacking!

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
62