52
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Docker マルチホストネットワーキング: swarm, consul, overlay network(VXLAN) を使用した構築手順

Last updated at Posted at 2016-02-09

Docker multi host ネットワーク

今までDocker の--link 機能を使うことで、同一ホスト内のコンテナの名前解決をして同一ネットワークのコンテナに対してアクセスすることは可能でしたが、それが複数の異なるDocker ホストになると--link 機能では実現することができませんでした。
そこでDocker のmulti ホストネットワーク及びDocker overlay ネットワークの機能を使用することで異なるホスト上にあるコンテナに対して、あたかも同じネットワーク上に存在しているコンテナのように、便利にアクセスすることができるようになります。
この機能を使うことにより今まで以上に大規模なDocker コンテナ環境を構築することができるようになります。

また、今回構築するDocker multi ホストネットワーク環境では、overlay network 及びDocker ホストのディスカバリにkey value ストアを使用するため、Docker ホストが異なるL3 ネットワーク上及び異なる拠点やデータセンタにある場合でも、それぞれのDocker ホスト上のコンテナは同じネットワーク上に存在するものとして容易にアクセスすることができるようになります。

  • --link によるコンテナの名前解決
    Docker_MultiHostNetwork0000.png

  • Multi host ネットワークによるコンテナの名前解決
    Docker_MultiHostNetwork0001.png

ネットワークの構成

今回構築するDocker multi host ネットワーク環境は次のようになります。
今回はそれぞれのDocker ホストが同じネットワーク上(192.168.1.0/24) にありますが、もちろんこれらは異なるネットワーク上に属していても問題ありません。

  • Docker マルチホスト構成
    ホスト名 Docker ホスト側のIP OS Docker ホストのDocker version 備考
    client 192.168.1.121 Ubuntu 15.10 - Docker 管理用ワークステーション(兼Swarm マネージャ)
    consul01 192.168.1.140 Debian strech 1.10.1 Docker クラスタの管理情報を扱うkey value ストア
    swmgr01 192.168.1.121 Debian strech 1.10.1 Docker Swarm cluster のマネージャ(兼管理用ワークステーション)
    swagt01 192.168.1.141 Debian strech 1.10.1 Docker Swarm cluster のエージェント1 号機
    swagt02 192.168.1.142 Debian strech 1.10.1 Docker Swarm cluster のエージェント2 号機
    swagt03 192.168.1.143 Debian strech 1.10.1 Docker Swarm cluster のエージェント3 号機

Key-value ストア(consul)の作成

Docker ホストのメタ情報を格納する格納するために、key-value データストアのconsul を準備します。
このkey-value データストアにはディスカバリ情報、エンドポイント、IP アドレスなどの情報が格納され、クラスタに参加しているDocker ホストが同じクラスタ内の他Docker ホストを検索するのに利用されます。
Docker ではConsul, Etcd, ZooKeeper といったkey-value データストアをサポートしていますが、今回はConsul を使用していきます。

Consul はDocker イメージが幾つか既に用意されているので、その中の一つであるprogrium/consul 利用することにします。

consul01
consul01~# docker run -d -p 8500:8500 --name consul01 -h consul01 progrium/consul -server -bootstrap

上記コマンドを実行することで、consul が8500 番ポートでListen するようになります。
docker ps コマンドでconsul コンテナが起動していることを確認します。

consul01
consul01~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                            NAMES
463ad77b47ce        progrium/consul     "/bin/start -server -"   11 minutes ago      Up 11 minutes       53/tcp, 53/udp, 8300-8302/tcp, 8400/tcp, 8301-8302/udp, 0.0.0.0:8500->8500/tcp   consul01

Swarm cluster を構築する

次に、Docker Swarm manager コンテナをswmgr01 ホストに作成します。
ここではmanager を作成するときにディスカバリサービスとしてconsul を使うように指定します。
consul をディスカバリサービスとして指定するには、swarm コンテナを起動するときにconsul://<consul ip>:8500 と指定するようにします。

swmgr01
$ docker run -d -p 2375:2375 --name swmgr01 swarm manage consul://192.168.1.140:8500/my_cluster

$ docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
ff1fe5e04017        swarm               "/swarm manage consul"   3 seconds ago       Up 2 seconds        0.0.0.0:2375->2375/tcp   swmgr01

Docker Swarm agent のDocker daemon の設定

各agent のDocker daemon が外部からのDocker コマンドを受け付けるようにするために、daemon 起動時に-H オプションでtcp://0.0.0.0:2375 を指定するようにします。
また--cluster-store でconsul を指定し、--cluster-advertise でagent のDocker daemon のInterface (もしくはIP) とport を指定します。
起動時のオプションを変更するには/lib/systemd/system/docker.service ファイルを編集します。

/lib/systemd/system/docker.serviceatswagt01-03
ExecStart=/usr/bin/docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=consul://192.168.1.140:8500/my_cluster --cluster-advertise=eno16777736:2375

systemctl ファイルを書き換えたら、daemon-reload を実行して修正を反映し、Docker daemon を再起動させます。

swagt01-03
# systemctl daemon-reload
# systemctl restart docker

Docker Swarm agent をクラスタに参加させる

Docker Swarm manager を構築したら、次にDocker Swarm agent をクラスタに参加させて行きます。
こちらもDocker Swarm manager コンテナを起動した時と同様にディスカバリサービスとしてconsul を使うように指定します。

swagt01
swagt01~# docker run --name swagt01 -d swarm join --addr=192.168.1.141:2375 consul://192.168.1.140:8500/my_cluster
swagt02
swagt02~# docker run --name swagt02 -d swarm join --addr=192.168.1.142:2375 consul://192.168.1.140:8500/my_cluster
swagt03
swagt03~# docker run --name swagt03 -d swarm join --addr=192.168.1.143:2375 consul://192.168.1.140:8500/my_cluster

Docker ID が重複することによるエラー

今回、Swarm agent の各ノードを、VM のコピー/クローンを使って作成した場合、Docker Swarm manager コンテナに次のようなエラーが出ることがあります。

dockerlogsswmgr01
time="2016-02-06T06:00:15Z" level=error msg="ID duplicated. XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXXshared by 192.168.1.141:2375 and 192.168.1.142:2375"

Docker daemon は初回起動時にID を作成しますが、そのID が他のDocker daemon のID と重複しまうことによるエラーです。
もしこのようなエラーが出てしまった場合は、それぞれのDocker ID ファイル(~/.docker/key.json もしくは/root/.docker/key.json もしくは/etc/docker/key.json)を削除してからDocker daemon を再起動するようにしてください。

DockerIDが重複した場合の対応
# rm -f /etc/docker/key.json
# systemctl restart docker
# docker info
...
ID: YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY
...

cluster ノードの検索

各agent をDocker Swarm cluster へ参加させたら、consul から各Docker Swarm agent が検索できることを確認してみましょう。

swmgr01
swmgr01~$ docker run --rm swarm list consul://192.168.1.140:8500/my_cluster
192.168.1.141:2375
192.168.1.142:2375
192.168.1.143:2375

次にDocker Swarm manager コンテナにdocker info コマンドを実行してDocker Swarm agent がcluster に参加しているコンテナを確認します。
docker info コマンドを実行するときは、-H オプションの接続先としてDocker Swarm manager を指定するようにします。

dockerinfo
$ docker -H tcp://192.168.1.121:2375 info
...
Nodes: 3
 swagt01: 192.168.1.141:2375
  └ Status: Healthy
  └ Containers: 1
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 2.038 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=4.3.0-1-amd64, operatingsystem=Debian GNU/Linux stretch/sid (containerized), storagedriver=devicemapper
 swagt02: 192.168.1.142:2375
  └ Status: Healthy
  └ Containers: 1
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 2.038 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=4.3.0-1-amd64, operatingsystem=Debian GNU/Linux stretch/sid (containerized), storagedriver=devicemapper
 swagt03: 192.168.1.143:2375
  └ Status: Healthy
  └ Containers: 1
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 2.038 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=4.3.0-1-amd64, operatingsystem=Debian GNU/Linux stretch/sid (containerized), storagedriver=devicemapper
...

上記のように検索できれば成功です。

overlay network の作成

docker network コマンドを使ってswmgr01 コンテナにoverlay ネットワークを作成します。
overlay ネットワークを作成するコンテナは、cluster に参加しているいずれか1 つののコンテナで構いません。
今回は、manager コンテナにoverlay network を作成します。

dockernetwork
$ docker -H tcp://192.168.1.121:2375 network create --driver overlay --subnet=10.0.9.0/24 my_network

Docker overlay network を作成したら、docker network ls コマンドを使ってクラスタ上のネットワークドライバの一覧を確認してみましょう。

dockernetworkls
$ docker -H tcp://192.168.1.121:2375 network ls
NETWORK ID          NAME                DRIVER
474350b5f95f        swagt01/bridge      bridge              
f018be332b12        swagt02/none        null                
2279a690f4e6        swagt02/host        host                
4bebe4cbca4a        swagt03/host        host                
c93572ec1940        swagt03/bridge      bridge              
7aa32976023f        swagt01/host        host                
5ec158206a76        swagt01/none        null                
0050af5c7580        my_network          overlay             
139094363b1e        swagt02/bridge      bridge              
d3f2a409061e        swagt03/none        null

出力された結果を見ると、全agent 上のネットワークドライバが表示されます。
しかしoverlay network については全cluster 上で1 つのみ存在していることが確認できます。

次にそれぞれのagent に個々に接続してdocker network ls コマンドを実行してみましょう。

swagt01
$ docker -H tcp://192.168.1.141:2375 network ls
NETWORK ID          NAME                DRIVER
0050af5c7580        my_network          overlay             
9e68da7fa173        bridge              bridge              
97d2a09b9fbb        none                null                
22c27ff26d8b        host                host  
swagt02
$ docker -H tcp://192.168.1.142:2375 network ls
NETWORK ID          NAME                DRIVER
0050af5c7580        my_network          overlay             
33276c8c59b6        bridge              bridge              
1d54daad8fce        none                null                
90768ae10d86        host                host 
swagt03
$ docker -H tcp://192.168.1.143:2375 network ls
NETWORK ID          NAME                DRIVER
0050af5c7580        my_network          overlay             
2e5fff12a678        host                host                
80caae61efdd        bridge              bridge              
6e5b95a64480        none                null 

そうするとそれぞれのagent にoverlay network が同じID 表示されることが確認できるはずです
このような状態になっていればoverlay network の作成は成功です。
以上でDocker multi host networking 環境の構築は完了です。

--subnet でサブネットを指定する必要性について

--subnet オプションでoverlay network のネットワークアドレスを指定していますが、この指定を無くすとDocker daemon が自動的にネットワークアドレスを割り当ててくれます。
しかし、これは場合によってはDocker によって管理されていないネットワークアドレスをoverlay network に割り当てることもあるので、特に理由がない限りは明示的に安全なネットワークアドレスを指定するようにしてください。

動作確認

では実際にcluster 上にコンテナを作成し、異なるDocker host 上のコンテナにコンテナ名を指定することでアクセスできることを確認してみましょう。
コンテナを起動するときは、--net オプションでoverlay network ドライバmy_network を指定する点に注意してください。
まずは1 つ目のコンテナを作成してみます。

1つ目のコンテナの作成
$ docker -H tcp://192.168.1.121:2375 run --name=busybox01 --net=my_network -d -ti busybox /bin/sh

1 つ目のコンテナを作成したらどのDocker ホスト上で作成されたかを確認してみましょう。

dockerps
$ docker -H tcp://192.168.1.121:2375 ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
be748478527d        busybox             "/bin/sh"           4 seconds ago       Up 2 seconds                            swagt02/busybox01

1 つ目のコンテナはswagt02 上に作成されました。
それでは2 つ目のコンテナをcluster 上に作成してみましょう。

2つ目のコンテナの作成
$ docker -H tcp://192.168.1.121:2375 run --name=busybox02 --net=my_network -d -ti busybox /bin/sh

$ docker -H tcp://192.168.1.121:2375 ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
03c2ff579a90        busybox             "/bin/sh"           3 seconds ago       Up 2 seconds                            swagt03/busybox02
be748478527d        busybox             "/bin/sh"           52 seconds ago      Up 50 seconds                           swagt02/busybox01

2 つ目のコンテナはswagt03 上に作成されました。
次にbusybox02(on swagt03) にattach してbusybox01(on swagt02) を名前解決できてアクセスできることを確認してみましょう。

dockerattach
$ docker -H tcp://192.168.1.121:2375 attach busybox02

/ # ping busybox01
PING busybox01 (10.0.9.2): 56 data bytes
64 bytes from 10.0.9.2: seq=0 ttl=64 time=0.526 ms
64 bytes from 10.0.9.2: seq=1 ttl=64 time=0.792 ms
64 bytes from 10.0.9.2: seq=2 ttl=64 time=0.801 ms
^C
--- busybox01 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.526/0.706/0.801 ms

ping コマンドを実行するとbusybox01 が名前解決されて異なるDocker ホスト上にあるコンテナから応答があることがわかります。

参考

Get started with multi-host networking
https://docs.docker.com/engine/userguide/networking/get-started-overlay/
マルチホストDockerネットワーキング(native overlay)
http://qiita.com/nmatsui/items/3ed2f21f7ee61d0827ea
Virtual Ethernet Tunnel (veth) の組を知りたい
http://thatsdone-j.blogspot.jp/2013/05/linux-veth-pairs.html
Linux Switching – Interconnecting Namespaces
http://www.opencloudblog.com/?p=66
Docker Swarm Discovery
https://docs.docker.com/swarm/discovery/
Build a Swarm cluster for production
https://docs.docker.com/swarm/install-manual/
Swarm Manager errors seen #380
https://github.com/docker/swarm/issues/380
Failed to create the network with overlay driver type #17647
https://github.com/docker/docker/issues/17647
52
52
3

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
52
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?