Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save shichi-at-nttr/2b42b60acacc0f1205148a6d591d7201 to your computer and use it in GitHub Desktop.
Save shichi-at-nttr/2b42b60acacc0f1205148a6d591d7201 to your computer and use it in GitHub Desktop.
Consulの名前解決機能(DNS機能)をDocker Swarm Modeのコンテナ内でも利用可能とするための設定方法

Docker Swarm ModeでConsulの名前解決を利用する

Ubuntu 16.04 LTS における解決方法のまとめは → こちら

前提

  • Docker Swarmのworkerノード(コンテナホスト)がConsulクラスタに組入れられている
  • workerノード上ではdnsmasqが動いていて、ノード上では「consul.service.consul」的な名前が解決可能である
  • Docker version 17.06.2-ce

目的

  • Docker Swarm Mode上のservice内で、「consul.service.consul」的な名前を使いたい
  • Swarm以外のコンテナ内でも「consul.service.consul」的な名前を使いたい
  • 例えば、自前のアプリケーションはSwarm上で動作させるが、cAdvisorはSwarm外で直接コンテナ起動することを想定
  • つまり、 レジストリは registry.service.consul でアクセスしたい。
    アプリ内からは、Redisに redis.service.consul でアクセスしたい。

なにも手を打たなければ

Dockerコンテナ内の /etc/resolv.conf はこのようになる

$ docker run -it --rm centos /bin/sh
sh# cat /etc/resolv.conf
search ****.jp  (プロバイダのドメイン)
nameserver 8.8.8.8
nameserver 8.8.4.4

自動的にGoogleのDNSが設定される。 (このページの末尾参照)   これにより、外部の名前は解決可能となるが、(当然ながら) Consulの名前は解決できない。

Dockerコンテナ(非Swarm)でConsulの名前解決を利用する

Dockerコンテナ起動時に、DNSとしてDockerホストを参照するように指定する。

$ docker run -it --rm --dns=172.17.0.1 centos /bin/sh
sh# cat /etc/resolv.conf
search ****.jp  (プロバイダのドメイン)
nameserver 172.17.0.1

あるいは、/etc/docker/daemon.json

{
    "dns": ["172.17.0.1"]
}

と記述したうえでDNS指定せずに起動する

$ docker run -it --rm  centos /bin/sh
sh# cat /etc/resolv.conf
search ****.jp  (プロバイダのドメイン)
nameserver 172.17.0.1

これにより、外部の名前だけでなく ping consul.service.consul も通るようになる。

ここで発生する不思議な挙動

常にConsulを利用するからといって、daemon.json にDNS記述を書いては いけない

Swarmで起動しているコンテナでは

sh# cat /etc/resolv.conf
search *****.jp (プロバイダのドメイン)
nameserver 127.0.0.11
options ndots:0

となっている。ここで 127.0.0.11 は「Docker内蔵DNSサーバ」。

Swarmのサービス(が動いているコンテナ)の名前は解決できるが、外部の名前も、Consulの名前も解決できない。 起動方法が生コンテナなのかSwarmコンテナなのか、また、DNS指定がdaemon.jsonなのかコマンドラインオプションなのか、で挙動が異なることがわかった。

調査結果

(A) daemon.jsonにDNS記述し、生コン起動時のdocker runに--dns=を記述しない

Swarmコンテナはdocker-compose.ymlでもDNSを指定しない

(A-1) 生コンテナ (A-2) Swarmコンテナ
/etc/resolv.conf search xxxxxxx.jp
nameserver 172.17.0.1
search xxxxxxx.jp
nameserver 127.0.0.11
options ndots:0
ping www.goo.ne.jp OK NG
ping consul.service.consul OK NG
ping (swarmサービス) NG OK

(B) daemon.jsonにDNS記述せず、生コン起動時のdocker runに--dns=172.17.0.1を記述する

Swarmコンテナはdocker-compose.ymlでもDNSを指定しない

(B-1) 生コンテナ (B-2) Swarmコンテナ
/etc/resolv.conf search xxxxxxx.jp
nameserver 172.17.0.1
search xxxxxxx.jp
nameserver 127.0.0.11
options ndots:0
ping www.goo.ne.jp OK OK
ping consul.service.consul OK OK
ping (swarmサービス) NG OK
  • 生コンテナの場合は、コマンドラインでのDNS指定とdaemon.jsonでのDN指定は同じ挙動
  • Swarmコンテナの場合は、DNS指定をコマンドラインで行うかdaemon.jsonで行うかで挙動が変わる

結論

次のようにDNS指定を扱うことで、Dockerコンテナ(通常コンテナ & Swarmサービスの両方)で ConsulのDNSを解決することができる。

  • daemon.jsonにDNSを記述してはいけない
  • docker run --dns= で記述する。(systemdで扱う場合にはUNITファイルで記述する)

未決事項

このような挙動の差異がなぜ生じるのか、さらに調査する。 (Swarm Modeでの内蔵DNSの挙動について明らかにする)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment