Dockerネイティブでマルチホストネットワーキングを実現する

Jul 14, 2015   #docker  #network 

前回の記事で、ネイティブのネットワーク機能を試すためにDockerをソースからビルドしました。 本記事ではDocker1.8.0-devを使って、ネイティブ(libnetwork)のマルチホスト間通信を試します。

前回作ったFedora22@EC2をコピーして2台にしました。

手順はlibnetwork/docs/overlay.mdに沿っています。

KVS(consul)を入れる

マルチホストを組むためにKVSを入れます。 裏側でlibkvという物が動いているらしく、consuletcdzookeeperをサポートしているようです。

今回は参考手順にならって、consulを入れます。

インストール手順はどちらのホストも同様です。

curl -OL https://dl.bintray.com/mitchellh/consul/0.5.2_linux_amd64.zip
unzip 0.5.2_linux_amd64.zip
mv consul /usr/local/bin/

起動時はホストの役割がserveragentなのかによって違います。

ホスト1を、下記のコマンドでbootstrapにして起動します。 末尾のIPはホスト1自身のIPを指定します。

consul agent -server -bootstrap -data-dir /tmp/consul -bind=<host-1-ip-address>

ホスト2をagentで起動します。 consul agentではホスト2自身のIPを、joinではホスト1のIPを指定します。

consul agent -data-dir /tmp/consul -bind <host-2-ip-address>
consul join <host-1-ip-address>

上手くJoinするとconsul membersで確認できます。

ホスト1:

consul members
Node                                              Address             Status  Type    Build  Protocol  DC
ip-172-31-15-233.ap-northeast-1.compute.internal  172.31.15.233:8301  alive   server  0.5.2  2         dc1
ip-172-31-14-206.ap-northeast-1.compute.internal  172.31.14.206:8301  alive   client  0.5.2  2         dc1

ホスト2:

consul members
Node                                              Address             Status  Type    Build  Protocol  DC
ip-172-31-14-206.ap-northeast-1.compute.internal  172.31.14.206:8301  alive   client  0.5.2  2         dc1
ip-172-31-15-233.ap-northeast-1.compute.internal  172.31.15.233:8301  alive   server  0.5.2  2         dc1

Dockerを起動する

Dockerは普通に起動するだけではNGで、オプションを付けて起動します。

ホスト1:

docker -d --kv-store=consul:localhost:8500 --label=com.docker.network.driver.overlay.bind_interface=eth0

ホスト2:

docker -d --kv-store=consul:localhost:8500 --label=com.docker.network.driver.overlay.bind_interface=eth0 --label=com.docker.network.driver.overlay.neighbor_ip=<host-1-ip-address>

ホスト1でネットワークを作る

docker network createでネットワークを作ります。 ドライバをoverlayにしないとbridgeで作られてしまって、ホスト間で同期しないので注意です。

ホスト1:

docker network create -d overlay netA

docker network ls | grep netA
1670f98747c8        netA                overlay

ホスト2:

docker network ls | grep netA
1670f98747c8        netA                overlay

コンテナを起動する

各ホストでコンテナを起動します。 コンテナ起動時にどのネットワークに乗せるかを指定します。

ホスト1:

docker run -i -t --publish-service=c1.netA.overlay centos

ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    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
9: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:c5:5a:65:0c brd ff:ff:ff:ff:ff:ff
    inet 172.21.0.5/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c5ff:fe5a:650c/64 scope link
       valid_lft forever preferred_lft forever

ip route
default via 172.21.255.254 dev eth0
172.21.0.0/16 dev eth0  proto kernel  scope link  src 172.21.0.5

ホスト2:

docker run -i -t --publish-service=c2.netA.overlay centos

ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    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
8: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:93:f6:b7:92 brd ff:ff:ff:ff:ff:ff
    inet 172.21.0.6/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:93ff:fef6:b792/64 scope link
       valid_lft forever preferred_lft forever

ip route
default via 172.21.255.254 dev eth0
172.21.0.0/16 dev eth0  proto kernel  scope link  src 172.21.0.6

コンテナのeth0に設定されるIPもホスト間で同調してくれて、うまくアサインされています。 また、docker0に繋がるインターフェースは存在しません。

疎通確認

コンテナ間でPingしてみます。

c1@ホスト1→c2@ホスト2:

ping -c 5 c2
PING c2 (172.21.0.6) 56(84) bytes of data.
64 bytes from c2 (172.21.0.6): icmp_seq=1 ttl=64 time=0.573 ms
64 bytes from c2 (172.21.0.6): icmp_seq=2 ttl=64 time=0.601 ms
64 bytes from c2 (172.21.0.6): icmp_seq=3 ttl=64 time=0.483 ms
64 bytes from c2 (172.21.0.6): icmp_seq=4 ttl=64 time=0.460 ms
64 bytes from c2 (172.21.0.6): icmp_seq=5 ttl=64 time=0.608 ms

--- c2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 0.460/0.545/0.608/0.061 ms

c2@ホスト2→c1@ホスト1:

ping -c 5 c1
PING c1 (172.21.0.5) 56(84) bytes of data.
64 bytes from c1 (172.21.0.5): icmp_seq=1 ttl=64 time=0.568 ms
64 bytes from c1 (172.21.0.5): icmp_seq=2 ttl=64 time=0.700 ms
64 bytes from c1 (172.21.0.5): icmp_seq=3 ttl=64 time=0.654 ms
64 bytes from c1 (172.21.0.5): icmp_seq=4 ttl=64 time=0.631 ms
64 bytes from c1 (172.21.0.5): icmp_seq=5 ttl=64 time=0.658 ms

--- c1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 0.568/0.642/0.700/0.046 ms

ホストを超えて通信できましたね。

深掘りについてはまた今度で。 片方のホストを落としたらどうなるのかとか、複数のネットワークを作ってみたいですね。