Docker 1.9とDocker Swarmのマルチホストネットワーク体験

 

Docker SwarmDocker 1.9からdocker networkコマンドがExperimentalでなくてもサポートされるようになり,Docker Swarmもv1.0となりnetworkコマンドに対応しました(参考).
公式ページにあるようにSwarmクラスタでマルチホストネットワークの構築が楽になりました.
早速標準サポートされたマルチホストネットワークを試してみようと思います.

準備

Kernel 3.16以上のlinux : Dockerでマルチホストネットワークを構築するためのlibnetworkのoverlayドライバはlinux kernel 3.16以上のみサポートなのでそれ以降のlinuxを用意します.
e.g. Ubuntu 14.04.1とか15.04など

ubuntu@awesome-song:~$ uname -a
Linux awesome-song 3.19.0-15-generic #15-Ubuntu SMP Thu Apr 16 23:32:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

Docker 1.9 : 以下でインストール

curl -sSL https://get.docker.com/ | sh

クラスタ構成

今回は以下の構成で行います

  • Manager : IP 192.168.100.1 ホスト名 MAAS-server
  • Node1 : IP 192.168.100.11 ホスト名 awesome-song
  • Node2 : IP 192.168.100.12 ホスト名 worthy-rule

ホスト名はMAASで自動生成されたものでなんでもいいのですがswarmのバックエンドやネットワーク情報の交換にconsulを使うため同一ホスト名だと怒られます.

ちなみにネットワークに関する情報を交換する仕組みについては簡単にですがここ(http://www.slideshare.net/Oshima0x3fd/docker-51844008)で書きました.

Swarmクラスタ構築

Manager, Nodeそれぞれで以下を行います.

@Manager

$docker run -d --net=host progrium/consul -server -bootstrap-expect=1 node=cumulus1 -data-dir=/tmp/consul -client=0.0.0.0 -ui-dir=/opt/consul/webui/
$docker run -d --net=host swarm manage -H tcp://0.0.0.0:2375 consul://127.0.0.1:8500/swarm

@Nodes

各ノードでまずtcp:2376でDocker APIを受け付けるようにし,ネットワーク情報をcunsulで交換すること及びホスト間通信をする際のvxlanデバイスが紐づくインターフェースを規定する必要があります.

/etc/default/dockerを編集してサービスを再起動するか,直接コマンドでデーモンを起動する貸してください.

ubuntu 15.04からは/etc/default/dockerが使えなくなったので(参考)今回は以下のコマンドで直接デーモンを起動しました.

$sudo service docker stop
$docker daemon -D -H unix:// -H tcp://0.0.0.0:2376 --cluster-store=consul://<Manager のIPアドレス>:8500 --cluster-advertise=<vxlanの紐づくデバイス名 例:eth0>:0

次にSwarmノードの登録を行います.

$sudo docker run -d --net=host --privileged --name consul progrium/consul -join <Manager のIPアドレス>
$sudo docker run -d --net=host -p 2376:2376 --name swarm swarm join --advertise=<Node のIPアドレス>:2376 consul://127.0.0.1:8500/swarm

確認

Managerで以下のように出力されれば成功です.

$docker -H 127.0.0.1:2375 info
Containers: 4
Images: 6
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 2
 awesome-song: 192.168.100.11:2376
  └ Containers: 2
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 513.6 MiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.19.0-15-generic, operatingsystem=Ubuntu 15.04, storagedriver=aufs
 worthy-rule: 192.168.100.12:2376
  └ Containers: 2
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 513.6 MiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.19.0-15-generic, operatingsystem=Ubuntu 15.04, storagedriver=aufs
CPUs: 2
Total Memory: 1.003 GiB
Name: MAAS-server

ちなみに

http:// Manager のIPアドレス :8500

でcunsulのノードや交換されている情報が覗けるのでここでもクラスタが組めているかが確認できます.

Screen Shot 2015-11-19 at 23.30.46

できてそうですね.

Swarmクラスタのマルチホストネットワーク

ではついにネットワークの作成です.
とは言え難しいことはほとんどありません.
まず現状のネットワーク状況の確認から

以下は全てMaster上での作業です.-H 127.0.0.1:2375で明示的にホストを指定していますが,export DOCKER_HOST=127.0.0.1:2375としておけば省略可能です.

$docker -H 127.0.0.1:2375 network ls
NETWORK ID          NAME                           DRIVER
a07a12ff3d7a        awesome-song/none              null
cb252e2f7d0a        awesome-song/host              host
2e6e98f302dd        awesome-song/bridge            bridge
56ea118e07ec        awesome-song/docker_gwbridge   bridge
d89042992a70        worthy-rule/none               null
32561a25f5fb        worthy-rule/host               host
84ff1cbe3e67        worthy-rule/bridge             bridge
f84f9b47cc09        worthy-rule/docker_gwbridge    bridge

順番は前後しますがだいたい同じはずです.

それぞれどのホストのネットワークなのかNAMEを見ればすぐわかると思います.

host, none, bridgeは昔ながらのdockerネットワークのホストモード,none,docker0ブリッジです.

ではここでマルチホストネットワークを作成します.

$docker -H 127.0.0.1:2375 network create backend
$docker -H 127.0.0.1:2375 network ls
NETWORK ID          NAME                           DRIVER
f84f9b47cc09        worthy-rule/docker_gwbridge    bridge
dede253b1863        worthy-rule/none               null
44d2707f300f        worthy-rule/host               host
563e8ac0486a        awesome-song/bridge            bridge
56ea118e07ec        awesome-song/docker_gwbridge   bridge
8322a02d1fd3        awesome-song/none              null
5a4c5085ca9a        backend                        overlay
6cb857289a36        worthy-rule/bridge             bridge
6a8851d55453        awesome-song/host              host

さて,新しいネットワークbackendができました.これはいずれのホストにも属していないネットワークになります.

Swarmマネージャに対してnetwork createを実行するとデフォルトでoverlayドライバが選択されます.

ドライバを指定したい場合にはnetwork create -d bridgeなどを行います.

次にbackendに属したコンテナを作成します.

$docker -H 127.0.0.1:2375 pull ubuntu
$docker -H 127.0.0.1:2375 run -itd --net=backend --name=app1 ubuntu /bin/bash
$docker -H 127.0.0.1:2375 exec -it app1 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
13: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
    link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.2/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:aff:fe00:2/64 scope link
       valid_lft forever preferred_lft forever
20: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:2/64 scope link
       valid_lft forever preferred_lft forever

2つのインターフェースを持ったコンテナが作成されます.

ここでeth0がコンテナ間通信用,eth1が外部との通信用です.

なのでこのままでも外とNATで通信することが可能です.

$docker -H 127.0.0.1:2375 exec -it app1 ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=9.45 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=59 time=6.46 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=59 time=6.69 ms
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 6.467/7.538/9.454/1.361 ms

更にもう一台コンテナを作成し,通信してみます

$docker -H 127.0.0.1:2375 run -itd --net=backend --name=app2 ubuntu /bin/bash
$docker -H 127.0.0.1:2375 ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED                  STATUS                  PORTS               NAMES
12047321581a        ubuntu              "/bin/bash"              Less than a second ago   Up Less than a second                       awesome-song/app1
374aeb62fa75        ubuntu              "/bin/bash"              Less than a second ago   Up Less than a second                       worthy-rule/app2
78f4bcfde082        swarm               "/swarm join --advert"   Less than a second ago   Up Less than a second                       worthy-rule/swarm
2f2dda9e7dcd        progrium/consul     "/bin/start -join 192"   Less than a second ago   Up Less than a second                       worthy-rule/consul
1547d49fe9a6        swarm               "/swarm join --advert"   Less than a second ago   Up Less than a second                       awesome-song/swarm
22b4cab4fa4b        progrium/consul     "/bin/start -join 192"   Less than a second ago   Up Less than a second                       awesome-song/consul
$docker -H 127.0.0.1:2375 exec -it app1 ping app2
PING app2 (10.0.0.3) 56(84) bytes of data.
64 bytes from app2 (10.0.0.3): icmp_seq=1 ttl=64 time=0.526 ms
64 bytes from app2 (10.0.0.3): icmp_seq=2 ttl=64 time=0.539 ms
64 bytes from app2 (10.0.0.3): icmp_seq=3 ttl=64 time=0.500 ms
64 bytes from app2 (10.0.0.3): icmp_seq=4 ttl=64 time=0.466 ms
^C
--- app2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.466/0.507/0.539/0.039 ms

異なるホスト間のコンテナ同士で疎通できていることが確認できました.

また同一ネットワークに属したコンテナならコンテナ名で疎通可能です.

これはコンテナ作成時にコンテナ内の/etc/hostsが更新されるためです.

$docker -H 127.0.0.1:2375 exec -it app1 cat /etc/hosts
10.0.0.2        12047321581a
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.0.0.3        app2
10.0.0.3        app2.backend

じゃあ今度は既存のNWに新しいコンテナを接続してみましょう.

まず新しいコンテナを作ります.

$docker -H 127.0.0.1:2375 run -itd --name=app3 ubuntu /bin/bash
$docker -H 127.0.0.1:2375 exec app3 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
22: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever

デフォルトのネットワーク(NATされるブリッジ)に接続されている事がわかりました.

ではbackendに接続します.

$docker -H 127.0.0.1:2375 network connect backend app3
$docker -H 127.0.0.1:2375 exec app3 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
22: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever
24: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
    link/ether 02:42:0a:00:00:04 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.4/24 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::42:aff:fe00:4/64 scope link
       valid_lft forever preferred_lft forever
$docker -H 127.0.0.1:2375 exec app3 ping app1
PING app1 (10.0.0.2) 56(84) bytes of data.
64 bytes from app1 (10.0.0.2): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from app1 (10.0.0.2): icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from app1 (10.0.0.2): icmp_seq=3 ttl=64 time=0.059 ms

最後に複数ネットワークに接続を試してみます.

まずbackend2ネットワークを作成してapp3コンテナを接続...

$docker -H 127.0.0.1:2375 network create --subnet=192.168.10.0/24 backend2
$docker -H 127.0.0.1:2375 run -itd --net=backend2 --name=app4 ubuntu /bin/bash
$docker -H 127.0.0.1:2375 network connect backend2 app3
Error response from daemon: invalid container <nil> : nosuchcontainer: no such id: app3

あれ?
ちなみにNode2のdockerデーモンのログ

ERRO[161920] Handler for POST /v1.21/networks/3f1df16f133f58d46e0c864ca6c7f9f95281ce61af6f864d6578e98ffeb787ec/connect returned error: invalid container <nil> : nosuchcontainer: no such id: app3
ERRO[161920] HTTP Error                                    err=invalid container <nil> : nosuchcontainer: no such id: app3 statusCode=404

うーん,複数ネットワークに所属可能なまずなんですが...

ちなみに交換されているネットワーク情報もconsulの中身を見ることで(http:// Manager のIPアドレス /ui/#/dc1/kv/docker/network/v1.0/)知ることができます.
consulnetwork
swarmにはweb UIはありませんが,そこはついこないだ発表されたDocker Universal Control Planeですね.

こちらについてはまた後日.

とりあず今回はここまで.

 

広告

Docker 1.9とDocker Swarmのマルチホストネットワーク体験」への1件のフィードバック

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中