Carpe Diem

備忘録

マルチホスト上にoverlay networkを構築してコンテナ間で疎通

概要

以前はWeaveというツールを使ってマルチホストをまたいだコンテナ間通信ができるように構築しました。
Docker 1.9.0からVXLANという仮想でL2ネットワークを構築する技術を用い、Docker自身がマルチホストネットワークに対応したので、今度はそちらで構築してみます。
overlay networkのkernel supportが3.16以下も対応したのでkernelのアップデートなども不要になっています。

環境

  • Ubuntu 14.04
  • Docker 1.11.1
  • etcd 2.3.4
IP 役割
192.168.33.10 Dockerホスト1
192.168.33.11 Dockerホスト2
192.168.33.12 etcd

各マシンにDockerをインストールした状態から始めます。

事前準備

etcd

etcdを使えるようにします。Github Releasesにインストール方法が書いてあります。

$ curl -L  https://github.com/coreos/etcd/releases/download/v2.3.4/etcd-v2.3.4-linux-amd64.tar.gz -o etcd-v2.3.4-linux-amd64.tar.gz
$ tar xzvf etcd-v2.3.4-linux-amd64.tar.gz
$ cd etcd-v2.3.4-linux-amd64

ポート

以下のポートを解放する必要があります。FWなどを設定している場合は解放しておいてください。

ポート プロトコル 役割
2379 TCP etcdで使用。クライアントからのリクエスト用
2380 TCP etcdで使用。peerとのコミュニケーション用
4789 UDP overlayドライバ
7946 UDPTCP overlayドライバ
2376 TCP Docker間通信

動作確認

etcd側のサーバを起動します。クライアントから疎通できるよう、オプションを設定します。

$ ./etcd -listen-client-urls "http://192.168.33.12:2379" -advertise-client-urls "http://192.168.33.12:2379"

クライアントから疎通できるか確認します。

$ curl -L http://192.168.33.12:2379/version
{"etcdserver":"2.3.4","etcdcluster":"2.3.0"}

大丈夫ですね。

マルチホストネットワークの作成

overlayネットワークを作成します。

/etc/default/docker

各Dockerホストで以下を追記

DOCKER_OPTS="--cluster-store=etcd://192.168.33.12:2379 --cluster-advertise=eth1:2376"

パラメータの説明は以下。

項目 説明
--cluster-store backing datastoreの指定。etcdのホストを指定 etcd://192.168.33.12:2379
--cluster-advertise Docker間通信用に公開。自ホストのIP eth1:2376

追記したら再起動

$ sudo service docker restart

作成

$ docker network create -d overlay overlay01
342e00d95e404003567a85a56dff6475cc5fdd2b48bc58bb2b64a5dc552d4c4f

作成されたネットワークは、すべてのDockerホスト内で共有されるため、1つのホストだけで実行すればOKです。

確認

$ docker network ls
NETWORK ID          NAME                DRIVER
5139aed8a8ec        bridge              bridge              
0422a42ed7a2        host                host                
35c2fe210767        none                null                
342e00d95e40        overlay01           overlay 

別のDockerホストからみてます。

$ docker network ls
NETWORK ID          NAME                DRIVER
ae25358877fa        bridge              bridge              
50ef65cf8246        host                host                
50ff46338a47        none                null                
342e00d95e40        overlay01           overlay  

overlayネットワークのみ同じIDになっている事がわかります。

疎通確認

各Dockerホスト上にコンテナを立てます。

ホスト1

$ docker run -d --name nginx01 nginx

スト2

$ docker run -d --name nginx02 nginx

先ほどのネットワークに接続します。

ホスト1

$ docker network connect overlay01 nginx01

スト2

$ docker network connect overlay01 nginx02

docker network inspectで確認します。

$ docker network inspect overlay01
[
    {
        "Name": "overlay01",
        "Id": "342e00d95e404003567a85a56dff6475cc5fdd2b48bc58bb2b64a5dc552d4c4f",
        "Scope": "global",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1/24"
                }
            ]
        },
        "Internal": false,
        "Containers": {
            "a486799d5bac7863a5b16770a090ae12afc55e1070455b643be9cae896531f27": {
                "Name": "nginx02",
                "EndpointID": "f36f818f92b583eed4f856407cc98a18880cc6f6d3b864e5612b0555e9d33795",
                "MacAddress": "02:42:0a:00:00:03",
                "IPv4Address": "10.0.0.3/24",
                "IPv6Address": ""
            },
            "ep-b8e39fc8b636b66e8efdab5ae28b679c6e7c19d2be0888c2863db36c8dff3ab5": {
                "Name": "nginx01",
                "EndpointID": "b8e39fc8b636b66e8efdab5ae28b679c6e7c19d2be0888c2863db36c8dff3ab5",
                "MacAddress": "02:42:0a:00:00:02",
                "IPv4Address": "10.0.0.2/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

2つとも接続されていますね。

コンテナの中に入って疎通できるか確認します。

$ docker exec -it nginx01 bash
root@8711a2328e22:/# ping nginx02                                                                                                                                                                            
PING nginx02 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: icmp_seq=0 ttl=64 time=0.426 ms
64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=0.614 ms

大丈夫でした。お疲れ様でした。

その他

failed to parse pool request for address space

Error response from daemon: failed to parse pool request for address space "GlobalDefault" pool "" subpool "": cannot find address space GlobalDefault (most likely the backing datastore is not configured)

というエラーが出る場合、kvsとの疎通がうまく行っていないです。

Destination Host Unreachable

pingした時に

92 bytes from b9eba6d2bba0 (10.0.0.3): Destination Host Unreachable
92 bytes from b9eba6d2bba0 (10.0.0.3): Destination Host Unreachable
92 bytes from b9eba6d2bba0 (10.0.0.3): Destination Host Unreachable

となってしまう場合、僕の場合はVagrantで構築していてマシンのホスト名が被っていたためこの問題が起きました。
/var/log/upstart/docker.logに以下の様なログが出ています。

ime="2016-05-16T01:37:18.887050874Z" level=error msg="2016/05/16 01:37:18 [ERR] memberlist: Conflicting address for vagrant-ubuntu-trusty-64. Mine: 192.168.33.10:7946 Theirs: 192.168.33.11:7946\n" 
time="2016-05-16T01:37:18.887163246Z" level=error msg="2016/05/16 01:37:18 [ERR] serf: Node name conflicts with another node at 192.168.33.11:7946. Names must be unique! (Resolution enabled: true)\n" 

Dockerでクラスタを構築する場合、ホスト名は必ずユニークにしましょう。

ソース