マルチホストDockerネットワーキング（weave）

マルチホストで動作するDockerネットワーキングツールについてのまとめ第三段。
（第一弾：[pipework＋GRE](http://qiita.com/nmatsui/items/fb7fc01dbba16b0ecb8e)）
（第二弾：[etcd+flannel](http://qiita.com/nmatsui/items/317213cd921e3b2e35d4)）
今回は[weaveworks/weave](https://github.com/weaveworks/weave)（旧zettio/weave）を取り上げる。

# 検証環境
SoftLayerに以下のVirtual Serverを立ち上げて検証した。

||DC|hostname|private IP(eth0)|public IP(eth1)|
|:--|:--|:--|:--|:--|:--|
|ホスト1|Dallas 9|weave01|10.142.130.16|X.X.X.X|
|ホスト2|Dallas 9|weave02|10.142.130.17|Y.Y.Y.Y|
|ホスト3|Dallas 6|weave03|10.107.153.153|Z.Z.Z.Z|

ホスト1とホスト2は同一VLAN上にあり、ホスト3は別VLAN上でホスト1,2とL3で接続されている。

各種バージョンは以下の通り。

| |version|
|:--|:--|
|distribution|Ubuntu 14.04.2 LTS|
|kernel|3.13.0-48-generic|
|docker|1.6.0|
|weave|0.10.0|

# 準備
すべてのホストで以下の作業を実施する。

```text:必要パッケージのインストール
root@weave01:~# apt-get update
root@weave01:~# apt-get upgrade -y
root@weave01:~# apt-get install build-essential bridge-utils curl -y
```

```text:golangとdockerインストール
root@weave01:~# wget -O - https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz | tar -C /usr/local -vxzf -
root@weave01:~# echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile
root@weave01:~# source /etc/profile
root@weave01:~# wget -qO- https://get.docker.com/ | sh
```

```text:weaveのインストール
root@weave01:~# wget -O /usr/local/bin/weave   https://github.com/zettio/weave/releases/download/latest_release/weave
root@weave01:~# chmod a+x /usr/local/bin/weave
```

# weaveクラスタの起動
weaveクラスタに参加するある一つのノード（今回はホスト１）でweaveを起動する。

## ホスト１

```text:weave起動
root@weave01:~# weave launch
```

この段階でweaveというブリッジが作成される。
またweave用dockerコンテナが自動で立ち上がり、docker0とweaveにvethペアが差し込まれる。weave用dockerコンテナでは、weaverプロセスが起動している。

```text:ホスト１のネットワークの状態
root@weave01:~# ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::5484:7aff:fefe:9799/64 scope link 
       valid_lft forever preferred_lft forever
root@weave01:~# ip addr show weave
5: weave: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc noqueue state UP group default 
    link/ether 7a:60:b4:e2:ae:fb brd ff:ff:ff:ff:ff:ff
    inet6 fe80::7860:b4ff:fee2:aefb/64 scope link 
       valid_lft forever preferred_lft forever
root@weave01:~# brctl show docker0
bridge name	bridge id		STP enabled	interfaces
docker0		8000.56847afe9799	no		vethb6e32e5
root@weave01:~# brctl show weave
bridge name	bridge id		STP enabled	interfaces
weave		8000.7a60b4e2aefb	no		vethwepl26957
```

```text:ホスト１で立ち上がったweave用コンテナ
root@weave01:~# docker ps -a
CONTAINER ID        IMAGE                COMMAND                CREATED             STATUS              PORTS                                            NAMES
a55aea3661a5        zettio/weave:0.9.0   "/home/weave/weaver    3 minutes ago       Up 3 minutes        0.0.0.0:6783->6783/tcp, 0.0.0.0:6783->6783/udp   weave               
```

## ホスト２
次にホスト２でweaveを起動する。この際、最初にweaveを立ち上げたホストのIPアドレスを指定することで、weaveクラスタに参加することができる。

```text:クラスタメンバーのIPアドレスを指定してweave起動
root@weave02:~# weave launch 10.142.130.16
```

ホスト１と同様にweaveブリッジが作成され、weaveコンテナが立ち上がる。

```text:ホスト２のネットワークの状態
root@weave02:~# ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::5484:7aff:fefe:9799/64 scope link 
       valid_lft forever preferred_lft forever
root@weave02:~# ip addr show weave
5: weave: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc noqueue state UP group default 
    link/ether 7a:d7:1b:d6:cf:9a brd ff:ff:ff:ff:ff:ff
    inet6 fe80::78d7:1bff:fed6:cf9a/64 scope link 
       valid_lft forever preferred_lft forever
root@weave02:~# brctl show docker0
bridge name	bridge id		STP enabled	interfaces
docker0		8000.56847afe9799	no		veth2a878ba
root@weave02:~# brctl show weave
bridge name	bridge id		STP enabled	interfaces
weave		8000.7ad71bd6cf9a	no		vethwepl25319
```

```text:ホスト２で立ち上がったweave用コンテナ
root@weave02:~# docker ps -a
CONTAINER ID        IMAGE                COMMAND                CREATED              STATUS              PORTS                                            NAMES
e595908080b2        zettio/weave:0.9.0   "/home/weave/weaver    About a minute ago   Up About a minute   0.0.0.0:6783->6783/tcp, 0.0.0.0:6783->6783/udp   weave               
```

## ホスト３
ホスト２と同様に、最初にweaveを立ち上げたホストのIPアドレスを指定してweaveを起動する。

```text:クラスタメンバーのIPアドレスを指定してweave起動
root@weave03:~# weave launch 10.142.130.16
```

```text:ホスト３のネットワークの状態
root@weave03:~# ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::5484:7aff:fefe:9799/64 scope link 
       valid_lft forever preferred_lft forever
root@weave03:~# ip addr show weave
5: weave: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc noqueue state UP group default 
    link/ether 7a:d5:dc:61:1f:74 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::78d5:dcff:fe61:1f74/64 scope link 
       valid_lft forever preferred_lft forever
root@weave03:~# brctl show docker0
bridge name	bridge id		STP enabled	interfaces
docker0		8000.56847afe9799	no		veth26a361d
root@weave03:~# brctl show weave
bridge name	bridge id		STP enabled	interfaces
weave		8000.7ad5dc611f74	no		vethwepl25227
```

```text:ホスト３で立ち上がったweave用コンテナ
root@weave03:~# docker ps -a
CONTAINER ID        IMAGE                COMMAND                CREATED              STATUS              PORTS                                            NAMES
426cca848351        zettio/weave:0.9.0   "/home/weave/weaver    About a minute ago   Up About a minute   0.0.0.0:6783->6783/udp, 0.0.0.0:6783->6783/tcp   weave
```

# weaveクラスタの状態
`weave status`でweaveクラスタの状態が確認できる。

クラスタへ参加した３つのホストがフルメッシュで接続されていることがわかる。
そのため一度クラスタが形成された後であれば、クラスタを起動したホスト（今回はホスト１）がダウンしても、他のホスト間での通信は切断されない。

```text:weaveクラスタの状態
root@weave01:~# weave status
weave router 0.9.0
Encryption off
Our name is 7a:d1:0c:86:12:d0
Sniffing traffic on &{10 65535 ethwe 0a:ca:5d:fc:c3:fe up|broadcast|multicast}
MACs:
0a:ca:5d:fc:c3:fe -> 7a:d1:0c:86:12:d0 (2015-04-21 13:10:47.608415492 +0000 UTC)
7a:d1:0c:86:12:d0 -> 7a:d1:0c:86:12:d0 (2015-04-21 13:10:47.956494651 +0000 UTC)
5a:ea:51:ec:57:ee -> 7a:d1:0c:86:12:d0 (2015-04-21 13:10:48.428398186 +0000 UTC)
7a:ac:3d:eb:25:2c -> 7a:ac:3d:eb:25:2c (2015-04-21 13:10:51.060356771 +0000 UTC)
2a:1f:06:09:57:ba -> 7a:ac:3d:eb:25:2c (2015-04-21 13:10:51.840353754 +0000 UTC)
b2:a7:8d:79:a2:b9 -> 7a:78:e7:a3:4b:ff (2015-04-21 13:10:53.929977949 +0000 UTC)
7a:78:e7:a3:4b:ff -> 7a:78:e7:a3:4b:ff (2015-04-21 13:10:54.55779784 +0000 UTC)
Peers:
Peer 7a:d1:0c:86:12:d0 (v4) (UID 11543907229160235537)
   -> 7a:ac:3d:eb:25:2c [10.142.130.17:46487]
   -> 7a:78:e7:a3:4b:ff [10.107.153.153:42041]
Peer 7a:ac:3d:eb:25:2c (v6) (UID 1084955225696332657)
   -> 7a:78:e7:a3:4b:ff [10.107.153.153:60251]
   -> 7a:d1:0c:86:12:d0 [10.142.130.16:6783]
Peer 7a:78:e7:a3:4b:ff (v6) (UID 17540410102682683533)
   -> 7a:d1:0c:86:12:d0 [10.142.130.16:6783]
   -> 7a:ac:3d:eb:25:2c [10.142.130.17:6783]
Routes:
unicast:
7a:d1:0c:86:12:d0 -> 00:00:00:00:00:00
7a:ac:3d:eb:25:2c -> 7a:ac:3d:eb:25:2c
7a:78:e7:a3:4b:ff -> 7a:78:e7:a3:4b:ff
broadcast:
7a:78:e7:a3:4b:ff -> []
7a:d1:0c:86:12:d0 -> [7a:78:e7:a3:4b:ff 7a:ac:3d:eb:25:2c]
7a:ac:3d:eb:25:2c -> []
Reconnects:
```

![docker_networking_4_01.png](https://qiita-image-store.s3.amazonaws.com/0/37648/130a8746-84ab-b02e-ea1a-1b9dea37a569.png)

# Dockerコンテナ起動
weaveコマンドを用い、以下のようなコンテナを立ち上げる。

|ホスト|コンテナ名|IPアドレス||
|:--|:--|:--|:--|	
|ホスト1|httpd|192.168.99.10/24|apache2を起動|
|ホスト1|client1|192.168.99.11/24||
|ホスト2|client2|192.168.99.21/24	||
|ホスト3|client3|192.168.99.31/24||

## ホスト１

`weave run`した後に`weave expose`することで、静的routeとNATルールが追加される。

ただし外部からコンテナ上のサービスにアクセスする場合、**-pオプション**でポートフォワードしなければならないが、docker0に紐付けられたIPアドレスに関する設定がiptablesに書かれているとパケットが届かないため、iptablesから当該ルールを削除する。
> これは非常に煩雑な手順なので、本来もっと良い方法があるのかもしれない。。。

```text:httpdコンテナ起動
root@weave01:~# HTTPD=$(weave run 192.168.99.10/24 -d -i -p 80:80 -t ubuntu:latest /bin/bash)
root@weave01:~# weave expose 192.168.99.10/24
```

```text:client1コンテナ起動
root@weave01:~# CLIENT1=$(weave run 192.168.99.11/24 -d -i -t ubuntu:latest /bin/bash)
root@weave01:~# weave expose 192.168.99.11/24
```

```text:iptablesのルール削除
root@weave01:~# iptables-save | grep `docker inspect --format="{{.NetworkSettings.IPAddress}}" $HTTPD`
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT

root@weave01:~# iptables -t nat -D POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
root@weave01:~# iptables -t nat -D DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80
root@weave01:~# iptables -D DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
```

```text:ホスト１のネットワーク状態
root@weave01:~# brctl show docker0
bridge name	bridge id		STP enabled	interfaces
docker0		8000.56847afe9799	no		veth14ed963
							veth41e3535
							vethce4f9e5
root@weave01:~# brctl show weave 
bridge name	bridge id		STP enabled	interfaces
weave		8000.7a4b8b125c68	no		vethwepl1426
							vethwepl1778
							vethwepl2171

root@weave01:~# ip route show
default via X.X.X.X dev eth1 
10.0.0.0/8 via 10.142.130.1 dev eth0 
10.142.130.0/26 dev eth0  proto kernel  scope link  src 10.142.130.16 
X.X.X.x/28 dev eth1  proto kernel  scope link  src X.X.X.X
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.42.1 
192.168.99.0/24 dev weave  proto kernel  scope link  src 192.168.99.10

root@weave01:~# iptables-save
# Generated by iptables-save v1.4.21 on Tue Apr 21 08:19:34 2015
*nat
:PREROUTING ACCEPT [5:372]
:INPUT ACCEPT [1:52]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:DOCKER - [0:0]
:WEAVE - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -j WEAVE
-A POSTROUTING -s 172.17.0.1/32 -d 172.17.0.1/32 -p tcp -m tcp --dport 6783 -j MASQUERADE
-A POSTROUTING -s 172.17.0.1/32 -d 172.17.0.1/32 -p udp -m udp --dport 6783 -j MASQUERADE
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 6783 -j DNAT --to-destination 172.17.0.1:6783
-A DOCKER ! -i docker0 -p udp -m udp --dport 6783 -j DNAT --to-destination 172.17.0.1:6783
-A WEAVE ! -s 192.168.99.0/24 -o weave -j MASQUERADE
-A WEAVE -s 192.168.99.0/24 ! -o weave -j MASQUERADE
COMMIT
# Completed on Tue Apr 21 08:19:34 2015
# Generated by iptables-save v1.4.21 on Tue Apr 21 08:19:34 2015
*filter
:INPUT ACCEPT [55:4300]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [40:5176]
:DOCKER - [0:0]
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -i weave -o weave -j ACCEPT
-A DOCKER -d 172.17.0.1/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 6783 -j ACCEPT
-A DOCKER -d 172.17.0.1/32 ! -i docker0 -o docker0 -p udp -m udp --dport 6783 -j ACCEPT
COMMIT
# Completed on Tue Apr 21 08:19:34 2015
```

### httpdコンテナ
各コンテナには、docker0ブリッジにつながっているeth0インタフェースとweaveブリッジにつながっているethweインタフェースが差し込まれている。
また**192.168.99.0/24**のパケットとマルチキャストパケットがethwe経由で送信されるように静的routeが設定されている。

```text:httpdコンテナのネットワーク
root@weave01:~# docker attach $HTTPD
root@35807546ca81:/# 
root@35807546ca81:/# ip addr show eth0
12: eth0: <BROADCAST,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
root@35807546ca81:/# ip addr show ethwe
14: ethwe: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 06:3a:fa:4e:c3:c2 brd ff:ff:ff:ff:ff:ff
    inet 192.168.99.10/24 scope global ethwe
       valid_lft forever preferred_lft forever
    inet6 fe80::43a:faff:fe4e:c3c2/64 scope link 
       valid_lft forever preferred_lft forever
root@35807546ca81:/# ip route show
default via 172.17.42.1 dev eth0 
172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.2 
192.168.99.0/24 dev ethwe  proto kernel  scope link  src 192.168.99.10 
224.0.0.0/4 dev ethwe  scope link 
```

```text:apache2のインストール
root@35807546ca81:/# apt-get install apache2 -y
root@35807546ca81:/# apachectl start
```

### client1コンテナ

```text:client1コンテナのネットワーク
root@weave01:~# docker attach $CLIENT1
root@b9ff8bd12dc3:/# 
root@b9ff8bd12dc3:/# ip addr show eth0
16: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:3/64 scope link 
       valid_lft forever preferred_lft forever
root@b9ff8bd12dc3:/# ip addr show ethwe
18: ethwe: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc pfifo_fast state UP group default qlen 1000
    link/ether e6:c7:9e:ff:35:3d brd ff:ff:ff:ff:ff:ff
    inet 192.168.99.11/24 scope global ethwe
       valid_lft forever preferred_lft forever
    inet6 fe80::e4c7:9eff:feff:353d/64 scope link 
       valid_lft forever preferred_lft forever
root@b9ff8bd12dc3:/# ip route show
default via 172.17.42.1 dev eth0 
172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.3 
192.168.99.0/24 dev ethwe  proto kernel  scope link  src 192.168.99.11 
224.0.0.0/4 dev ethwe  scope link 
```

```text:curlのインストール
root@b9ff8bd12dc3:/# apt-get install curl -y
```

## ホスト２

```text:client2コンテナ起動
root@weave02:~# CLIENT2=$(weave run 192.168.99.21/24 -d -i -t ubuntu:latest /bin/bash)
root@weave02:~# weave expose 192.168.99.21/24
```

```text:ホスト２のネットワーク状態
root@weave02:~# brctl show docker0
bridge name	bridge id		STP enabled	interfaces
docker0		8000.56847afe9799	no		veth7030f9c
							vethfd645c6
root@weave02:~# brctl show weave
bridge name	bridge id		STP enabled	interfaces
weave		8000.7ab6719c9174	no		vethwepl1429
							vethwepl2409

root@weave02:~# ip route show
default via Y.Y.Y.Y dev eth1 
10.0.0.0/8 via 10.142.130.1 dev eth0 
10.142.130.0/26 dev eth0  proto kernel  scope link  src 10.142.130.17 
Y.Y.Y.y/28 dev eth1  proto kernel  scope link  src Y.Y.Y.Y 
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.42.1 
192.168.99.0/24 dev weave  proto kernel  scope link  src 192.168.99.21 
```

### client2コンテナ

```text:clent2コンテナのネットワーク
root@weave02:~# docker attach $CLIENT2
root@55f46f368032:/# 
root@55f46f368032:/# ip addr show eth0
12: eth0: <BROADCAST,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
root@55f46f368032:/# ip addr show ethwe
14: ethwe: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 1a:05:55:2c:d6:73 brd ff:ff:ff:ff:ff:ff
    inet 192.168.99.21/24 scope global ethwe
       valid_lft forever preferred_lft forever
    inet6 fe80::1805:55ff:fe2c:d673/64 scope link 
       valid_lft forever preferred_lft forever
root@55f46f368032:/# ip route show
default via 172.17.42.1 dev eth0 
172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.2 
192.168.99.0/24 dev ethwe  proto kernel  scope link  src 192.168.99.21 
224.0.0.0/4 dev ethwe  scope link 
```

```text:curlのインストール
root@55f46f368032:/# apt-get install curl -y
```

## ホスト３

```text:client3コンテナ起動
root@weave03:~# CLIENT3=$(weave run 192.168.99.31/24 -d -i -t ubuntu:latest /bin/bash)
root@weave03:~# weave expose 192.168.99.31/24
```

```text:ホスト３のネットワーク状態
root@weave03:~# brctl show docker0
bridge name	bridge id		STP enabled	interfaces
docker0		8000.56847afe9799	no		veth1c116a5
							veth58c3a13
root@weave03:~# brctl show weave
bridge name	bridge id		STP enabled	interfaces
weave		8000.7aeda598c629	no		vethwepl1457
							vethwepl2273

root@weave03:~# ip route show
default via Z.Z.Z.Z dev eth1 
10.0.0.0/8 via 10.107.153.129 dev eth0 
10.107.153.128/26 dev eth0  proto kernel  scope link  src 10.107.153.153 
Z.Z.Z.z/28 dev eth1  proto kernel  scope link  src Z.Z.Z.Z 
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.42.1 
192.168.99.0/24 dev weave  proto kernel  scope link  src 192.168.99.31 
```

### client3コンテナ

```text:clent2コンテナのネットワーク
root@weave03:~# docker attach $CLIENT3
root@b6cd774525a3:/# 
root@b6cd774525a3:/# ip addr show eth0
12: eth0: <BROADCAST,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
root@b6cd774525a3:/# ip addr show ethwe
14: ethwe: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 8e:4b:c6:d7:de:40 brd ff:ff:ff:ff:ff:ff
    inet 192.168.99.31/24 scope global ethwe
       valid_lft forever preferred_lft forever
    inet6 fe80::8c4b:c6ff:fed7:de40/64 scope link 
       valid_lft forever preferred_lft forever
root@b6cd774525a3:/# ip route show
default via 172.17.42.1 dev eth0 
172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.2 
192.168.99.0/24 dev ethwe  proto kernel  scope link  src 192.168.99.31 
224.0.0.0/4 dev ethwe  scope link 
```

```text:curlのインストール
root@b6cd774525a3:/# apt-get install curl -y
```

![docker_networking_4_02.png](https://qiita-image-store.s3.amazonaws.com/0/37648/ddb80086-3a8b-7c26-95fb-77908d346491.png)

# 疎通確認
ここまでで、複数ホストをまたがって敷設された192.168.99.0/24という仮想ネットワーク上に4つのコンテナが起動した。ホスト1のeth0にtcpdumpを仕掛け、コンテナやホストから疎通確認を行う。

## ホスト1 → httpdコンテナ
httpdコンテナはホスト1上の仮想ブリッジdocker0, weaveに直接つながっているため、eth0を経由せずに通信が行われる。

```text:ping(ホスト1→httpdコンテナ)
root@weave01:~# ping 192.168.99.10
PING 192.168.99.10 (192.168.99.10) 56(84) bytes of data.
64 bytes from 192.168.99.10: icmp_seq=1 ttl=64 time=0.045 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=0.019 ms
...
```

```text:HTTP(ホスト1→httpdコンテナ)
root@weave01:~# curl 192.168.99.10

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
...
```

## client1コンテナ → httpdコンテナ
client1コンテナとhttpdコンテナは同じ仮想ブリッジdocker0, weaveにつながっているため、eth0を経由せずに通信が行われる。

```text:ping(client1コンテナ→httpdコンテナ)
root@b9ff8bd12dc3:/# ping 192.168.99.10
PING 192.168.99.10 (192.168.99.10) 56(84) bytes of data.
64 bytes from 192.168.99.10: icmp_seq=1 ttl=64 time=0.086 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=0.026 ms
...
```

```text:HTTP(client1コンテナ→httpdコンテナ)
root@b9ff8bd12dc3:/# curl 192.168.99.10

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
...
```

## ホスト2 → httpdコンテナ
同一VLAN上にあるホスト2からのパケットをweaverプロセスがラップしてホスト1のeth0に到達し、ホスト1のweaverプロセスを経由してhttpdコンテナと通信されている。

tcpdumpを見る限りUDPでラップされており、GRE等の知られているプロトコルは使われていない。

```text:ping(ホスト2→httpdコンテナ)
root@weave02:~# ping 192.168.99.10
PING 192.168.99.10 (192.168.99.10) 56(84) bytes of data.
64 bytes from 192.168.99.10: icmp_seq=1 ttl=64 time=0.674 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=0.432 ms
```

```text:この時のtcpdump
root@weave01:~# tcpdump -v -i eth0 dst host 10.142.130.16 and src host 10.142.130.17
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
08:32:03.357123 IP (tos 0x0, ttl 63, id 2865, offset 0, flags [DF], proto UDP (17), length 146)
    10.142.130.17.6783 > 10.142.130.16.6783: UDP, length 118
08:32:04.356099 IP (tos 0x0, ttl 63, id 2866, offset 0, flags [DF], proto UDP (17), length 146)
    10.142.130.17.6783 > 10.142.130.16.6783: UDP, length 118
...
```

```text:HTTP(ホスト2→httpdコンテナ)
root@weave02:~# curl 192.168.99.10

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
...
```

## client2コンテナ → httpdコンテナ
ホスト2上にあるclient2コンテナからのパケットをweaverプロセスがラップしてホスト1のeth0に到達し、ホスト1のweaverプロセスを経由してhttpdコンテナと通信されている。

```text:ping(client2コンテナ→httpdコンテナ)
root@55f46f368032:/# ping 192.168.99.10
PING 192.168.99.10 (192.168.99.10) 56(84) bytes of data.
64 bytes from 192.168.99.10: icmp_seq=1 ttl=64 time=0.872 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=0.446 ms
...
```

```text:この時のtcpdump
root@weave01:~# tcpdump -v -i eth0 dst host 10.142.130.16 and src host 10.142.130.17
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
08:35:26.990308 IP (tos 0x0, ttl 63, id 2900, offset 0, flags [DF], proto UDP (17), length 146)
    10.142.130.17.6783 > 10.142.130.16.6783: UDP, length 118
08:35:27.991215 IP (tos 0x0, ttl 63, id 2901, offset 0, flags [DF], proto UDP (17), length 146)
    10.142.130.17.6783 > 10.142.130.16.6783: UDP, length 118
...
```

```text:HTTP(client2コンテナ→httpdコンテナ)
root@55f46f368032:/# curl 192.168.99.10

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
...
```

## ホスト3 → httpdコンテナ
異なるVLAN上にあるホスト３からのパケットをweaverプロセスがラップしてホスト1のeth0に到達し、ホスト1のweaverプロセスを経由してhttpdコンテナと通信されている。

```text:ping(ホスト3→httpdコンテナ)
root@weave03:~# ping 192.168.99.10
PING 192.168.99.10 (192.168.99.10) 56(84) bytes of data.
64 bytes from 192.168.99.10: icmp_seq=1 ttl=64 time=1.79 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=1.78 ms
...
```

```text:この時のtcpdump
root@weave01:~# tcpdump -v -i eth0 dst host 10.142.130.16 and src host 10.107.153.153
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
08:39:03.481022 IP (tos 0x0, ttl 56, id 65008, offset 0, flags [DF], proto UDP (17), length 70)
    10.107.153.153.6783 > 10.142.130.16.6783: UDP, length 42
08:39:04.147393 IP (tos 0x0, ttl 56, id 65009, offset 0, flags [DF], proto UDP (17), length 146)
    10.107.153.153.6783 > 10.142.130.16.6783: UDP, length 118
08:39:05.148527 IP (tos 0x0, ttl 56, id 65010, offset 0, flags [DF], proto UDP (17), length 146)
    10.107.153.153.6783 > 10.142.130.16.6783: UDP, length 118
...
```

```text:HTTP(ホスト3→httpdコンテナ)
root@weave03:~# curl 192.168.99.10

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
...
```

## clien3コンテナ → httpdコンテナ
ホスト３上にあるclient3コンテナからのパケットをweaverプロセスがラップしてホスト1のeth0に到達し、ホスト1のweaverプロセスを経由してhttpdコンテナと通信されている。

```text:ping(client3コンテナ→httpdコンテナ)
root@b6cd774525a3:/# ping 192.168.99.10
PING 192.168.99.10 (192.168.99.10) 56(84) bytes of data.
64 bytes from 192.168.99.10: icmp_seq=1 ttl=64 time=4.15 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=21.1 ms
...
```

```text:この時のtcpdump
root@weave01:~# tcpdump -v -i eth0 dst host 10.142.130.16 and src host 10.107.153.153
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
08:42:06.700001 IP (tos 0x0, ttl 56, id 65037, offset 0, flags [DF], proto UDP (17), length 146)
    10.107.153.153.6783 > 10.142.130.16.6783: UDP, length 118
08:42:07.701352 IP (tos 0x0, ttl 56, id 65038, offset 0, flags [DF], proto UDP (17), length 146)
    10.107.153.153.6783 > 10.142.130.16.6783: UDP, length 118
...
```

```text:HTTP(client3コンテナ→httpdコンテナ)
root@b6cd774525a3:/# curl 192.168.99.10

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
...
```

# まとめ
weaveworks/weaveを使うことで、L2 & L3で接続された複数ホスト間に仮想ネットワークを敷設してDockerコンテナを所属させ、相互に通信させることができた。

ただしコンテナ内のサービスを外部ネットワークに公開する際のより良い手順の検証が必要。