マルチホストで動作するDockerネットワーキングツールについてのまとめ第一段。
(第二弾:etcd+flannel)
(第三弾:weave)
今回はjpetazzo/pipeworkを取り上げる。
検証環境
SoftLayerに以下のVirtual Serverを立ち上げて検証した。
||DC|hostname|private IP(eth0)|public IP(eth1)|
|:--|:--|:--|:--|:--|:--|
|ホスト1|Dallas 9|pipework01|10.142.51.197|X.X.X.X|
|ホスト2|Dallas 9|pipework02|10.142.51.196|Y.Y.Y.Y|
|ホスト3|Dallas 6|pipework03|10.106.242.2|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.5.0 |
pipework | commit: 5a1ff19977df4e40f6b82c7b1b86a8d6633a5af9 |
準備
すべてのホストで以下の作業を実施する。
root@pipework01:~# apt-get update
root@pipework01:~# apt-get upgrade -y
root@pipework01:~# apt-get install build-essential bridge-utils curl -y
root@pipework01:~# wget -O - https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz | tar -C /usr/local -vxzf -
root@pipework01:~# echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile
root@pipework01:~# source /etc/profile
root@pipework01:~# wget -qO- https://get.docker.com/ | sh
root@pipework01:~# wget -O /usr/local/bin/pipework https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework
root@pipework01:~# chmod a+x /usr/local/bin/pipework
root@pipework01:~# lsmod | grep gre
root@pipework01:~# modprobe ip_gre
root@pipework01:~# lsmod | grep gre
ip_gre 18245 0
gre 13796 1 ip_gre
ip_tunnel 23768 1 ip_gre
GREトンネルの設定
ホスト間にIP/Ethernet/GREトンネルを設定する。
ただし全てのホスト間にフルメッシュでトンネルを設定するとパケットがループするため、ホスト1を中心点としてスター型にトンネルを設定する。
今回作成する仮想ネットワークは、192.168.99.0/24とするが、各ホストで生成する仮想ブリッジのIPアドレスは重複しないように注意して自力で設定する。
ホスト | 仮想ブリッジのIPアドレス |
---|---|
ホスト1 | 192.168.99.251/24 |
ホスト2 | 192.168.99.252/24 |
ホスト3 | 192.168.99.253/24 |
ホスト1
root@pipework01:~# brctl addbr br0
root@pipework01:~# ip addr add 192.168.99.251/24 dev br0
root@pipework01:~# ip link set br0 up
root@pipework01:~# ip addr show br0
8: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/ether f2:c7:9b:2d:20:49 brd ff:ff:ff:ff:ff:ff
inet 192.168.99.251/24 scope global br0
valid_lft forever preferred_lft forever
inet6 fe80::f0c7:9bff:fe2d:2049/64 scope link
valid_lft forever preferred_lft forever
root@pipework01:~# ip route show
default via X.X.X.x dev eth1
10.0.0.0/8 via 10.142.51.193 dev eth0
10.142.51.192/26 dev eth0 proto kernel scope link src 10.142.51.197
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.42.1
192.168.99.0/24 dev br0 proto kernel scope link src 192.168.99.251
X.X.X.x/28 dev eth1 proto kernel scope link src X.X.X.X
root@pipework01:~# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.000000000000 no
root@pipework01:~# ip link add gre_to_02 type gretap remote 10.142.51.196 local 10.142.51.197
root@pipework01:~# brctl addif br0 gre_to_02
root@pipework01:~# ip link set gre_to_02 up
root@pipework01:~# ip link add gre_to_03 type gretap remote 10.106.242.2 local 10.142.51.197
root@pipework01:~# brctl addif br0 gre_to_03
root@pipework01:~# ip link set gre_to_03 up
root@pipework01:~# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.8e284007d2bb no gre_to_02
gre_to_03
ホスト2
root@pipework02:~# brctl addbr br0
root@pipework02:~# ip addr add 192.168.99.252/24 dev br0
root@pipework02:~# ip link set br0 up
root@pipework02:~# ip addr show br0
8: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/ether 0a:35:5b:bd:28:b5 brd ff:ff:ff:ff:ff:ff
inet 192.168.99.252/24 scope global br0
valid_lft forever preferred_lft forever
inet6 fe80::835:5bff:febd:28b5/64 scope link
valid_lft forever preferred_lft forever
root@pipework02:~# ip route show
default via Y.Y.Y.y dev eth1
10.0.0.0/8 via 10.142.51.193 dev eth0
10.142.51.192/26 dev eth0 proto kernel scope link src 10.142.51.196
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.42.1
192.168.99.0/24 dev br0 proto kernel scope link src 192.168.99.252
Y.Y.Y.y/28 dev eth1 proto kernel scope link src Y.Y.Y.Y
root@pipework02:~# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.000000000000 no
root@pipework02:~# ip link add gre_to_01 type gretap remote 10.142.51.197 local 10.142.51.196
root@pipework02:~# brctl addif br0 gre_to_01
root@pipework02:~# ip link set gre_to_01 up
root@pipework02:~# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.7e9ccdb21a54 no gre_to_01
ホスト3
root@pipework03:~# brctl addbr br0
root@pipework03:~# ip addr add 192.168.99.253/24 dev br0
root@pipework03:~# ip link set br0 up
root@pipework03:~# ip addr show br0
7: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/ether 2a:85:7d:cb:9b:56 brd ff:ff:ff:ff:ff:ff
inet 192.168.99.253/24 scope global br0
valid_lft forever preferred_lft forever
inet6 fe80::2885:7dff:fecb:9b56/64 scope link
valid_lft forever preferred_lft forever
root@pipework03:~# ip route show
default via Z.Z.Z.Z dev eth1
10.0.0.0/8 via 10.106.242.1 dev eth0
10.106.242.0/26 dev eth0 proto kernel scope link src 10.106.242.2
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.42.1
192.168.99.0/24 dev br0 proto kernel scope link src 192.168.99.253
Z.Z.Z.z/28 dev eth1 proto kernel scope link src Z.Z.Z.Z
root@pipework03:~# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.000000000000 no
root@pipework03:~# ip link add gre_to_01 type gretap remote 10.142.51.197 local 10.106.242.2
root@pipework03:~# brctl addif br0 gre_to_01
root@pipework03:~# ip link set gre_to_01 up
root@pipework03:~# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.ae94d8d42c9e no gre_to_01
ここまでで、各ホストからGREトンネル経由で仮想ブリッジ全てに通信ができるようになる。
Dockerコンテナ起動
以下のようなコンテナを立ち上げる。
最新版のpipeworkはコンテナIDだけでなくコンテナ名でもIPアドレスを付与できるので、今回はコンテナ名を指定する。
ホスト | コンテナ名 | 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 |
ホスト1
root@pipework01:~# HTTPD=$(docker run --name httpd -d -i -t ubuntu:latest /bin/bash)
root@pipework01:~# pipework br0 httpd 192.168.99.10/24
root@pipework01:~# CLIENT1=$(docker run --name client1 -d -i -t ubuntu:latest /bin/bash)
root@pipework01:~# pipework br0 client1 192.168.99.11/24
root@pipework01:~# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.1ef07eef748e no gre_to_02
gre_to_03
veth1pl26396
veth1pl26738
httpdコンテナ
root@6f735daafef6:/# ip addr show eth0
11: 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@6f735daafef6:/# ip addr show eth1
13: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1462 qdisc pfifo_fast state UP group default qlen 1000
link/ether 76:73:7e:d5:58:55 brd ff:ff:ff:ff:ff:ff
inet 192.168.99.10/24 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::7473:7eff:fed5:5855/64 scope link
valid_lft forever preferred_lft forever
root@6f735daafef6:/# 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 eth1 proto kernel scope link src 192.168.99.10
root@6f735daafef6:/# apt-get install apache2 -y
root@6f735daafef6:/# apachectl start
client1コンテナ
root@4b4b513ccaf3:/# ip addr show eth0
15: 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@4b4b513ccaf3:/# ip addr show eth1
17: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1462 qdisc pfifo_fast state UP group default qlen 1000
link/ether ae:e6:bb:69:51:5b brd ff:ff:ff:ff:ff:ff
inet 192.168.99.11/24 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::ace6:bbff:fe69:515b/64 scope link
valid_lft forever preferred_lft forever
root@4b4b513ccaf3:/# 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 eth1 proto kernel scope link src 192.168.99.11
root@4b4b513ccaf3:/# apt-get install curl -y
ホスト2
root@pipework02:~# CLIENT2=$(docker run --name client2 -d -i -t ubuntu:latest /bin/bash)
root@pipework02:~# pipework br0 client2 192.168.99.21/24
root@pipework02:~# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.4ab07b385d05 no gre_to_01
veth1pl26981
client2コンテナ
root@26296693f6f3:/# ip addr show eth0
10: 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@26296693f6f3:/# ip addr show eth1
12: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1462 qdisc pfifo_fast state UP group default qlen 1000
link/ether c6:ea:e6:af:42:2e brd ff:ff:ff:ff:ff:ff
inet 192.168.99.21/24 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::c4ea:e6ff:feaf:422e/64 scope link
valid_lft forever preferred_lft forever
root@26296693f6f3:/# 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 eth1 proto kernel scope link src 192.168.99.21
root@26296693f6f3:/# apt-get install curl -y
ホスト3
root@pipework03:~# CLIENT3=$(docker run --name client3 -d -i -t ubuntu:latest /bin/bash)
root@pipework03:~# pipework br0 client3 192.168.99.31/24
root@pipework03:~# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.6ad48777397f no gre_to_01
veth1pl27601
client3コンテナ
root@d986d5cedb1a:/# ip addr show eth0
9: 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@d986d5cedb1a:/# ip addr show eth1
11: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1462 qdisc pfifo_fast state UP group default qlen 1000
link/ether 36:50:b8:f5:e0:93 brd ff:ff:ff:ff:ff:ff
inet 192.168.99.31/24 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::3450:b8ff:fef5:e093/64 scope link
valid_lft forever preferred_lft forever
root@d986d5cedb1a:/# 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 eth1 proto kernel scope link src 192.168.99.31
root@d986d5cedb1a:/# apt-get install curl -y
疎通確認
ここまでで、複数ホストをまたがって敷設された192.168.99.0/24という仮想ネットワーク上に4つのコンテナが起動した。ホスト1のeth0にtcpdumpを仕掛け、コンテナやホストから疎通確認を行う。
ホスト1 → httpdコンテナ
httpdコンテナはホスト1上の仮想ブリッジbr0に直接つながっているため、そのまま通信できる。
root@pipework01:~# 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.041 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=0.025 ms
...
root@pipework01:~# 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コンテナは同じ仮想ブリッジbr0につながっているため、そのまま通信できる。
root@4b4b513ccaf3:/# 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.039 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=0.027 ms
...
root@4b4b513ccaf3:/# 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からのパケットが、ホスト2のbr0を経由してGREでラップされてホスト1のeth0に到達し、ホスト1のbr0を経由してhttpdコンテナと通信できていることがわかる。
root@pipework02:~# 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.336 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=0.190 ms
...
root@pipework01:~# tcpdump -v -i eth0 src host 10.142.51.196
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
07:39:57.990802 IP (tos 0x0, ttl 64, id 61161, offset 0, flags [DF], proto GRE (47), length 122)
10.142.51.196 > 10.142.51.197: GREv0, Flags [none], length 102
IP (tos 0x0, ttl 64, id 50342, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.99.252 > 192.168.99.10: ICMP echo request, id 32387, seq 1, length 64
07:39:58.990174 IP (tos 0x0, ttl 64, id 61224, offset 0, flags [DF], proto GRE (47), length 122)
10.142.51.196 > 10.142.51.197: GREv0, Flags [none], length 102
IP (tos 0x0, ttl 64, id 50568, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.99.252 > 192.168.99.10: ICMP echo request, id 32387, seq 2, length 64
root@pipework02:~# 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">
...
root@pipework01:~# tcpdump -v -i eth0 src host 10.142.51.196
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
07:42:52.299503 IP (tos 0x0, ttl 64, id 30310, offset 0, flags [DF], proto GRE (47), length 98)
10.142.51.196 > 10.142.51.197: GREv0, Flags [none], length 78
IP (tos 0x0, ttl 64, id 52399, offset 0, flags [DF], proto TCP (6), length 60)
192.168.99.252.59501 > 192.168.99.10.http: Flags [S], cksum 0xa609 (correct), seq 4069927267, win 28440, options [mss 1422,sackOK,TS val 2680268 ecr 0,nop,wscale 7], length 0
07:42:52.299796 IP (tos 0x0, ttl 64, id 30311, offset 0, flags [DF], proto GRE (47), length 90)
10.142.51.196 > 10.142.51.197: GREv0, Flags [none], length 70
IP (tos 0x0, ttl 64, id 52400, offset 0, flags [DF], proto TCP (6), length 52)
192.168.99.252.59501 > 192.168.99.10.http: Flags [.], cksum 0x39ee (correct), ack 2874439019, win 223, options [nop,nop,TS val 2680268 ecr 2680834], length 0
...
client2コンテナ → httpdコンテナ
ホスト2上にあるclient2コンテナからのパケットが、ホスト2のbr0経由でGREでラップされてホスト1のeth0に到達し、httpdコンテナと通信できていることがわかる。
root@26296693f6f3:/# 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.452 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=0.196 ms
...
root@pipework01:~# tcpdump -v -i eth0 src host 10.142.51.196
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
07:46:05.345995 IP (tos 0x0, ttl 64, id 45447, offset 0, flags [DF], proto GRE (47), length 122)
10.142.51.196 > 10.142.51.197: GREv0, Flags [none], length 102
IP (tos 0x0, ttl 64, id 56407, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.99.21 > 192.168.99.10: ICMP echo request, id 2908, seq 1, length 64
07:46:06.346171 IP (tos 0x0, ttl 64, id 45684, offset 0, flags [DF], proto GRE (47), length 122)
10.142.51.196 > 10.142.51.197: GREv0, Flags [none], length 102
IP (tos 0x0, ttl 64, id 56503, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.99.21 > 192.168.99.10: ICMP echo request, id 2908, seq 2, length 64
root@26296693f6f3:/# 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">
...
root@pipework01:~# tcpdump -v -i eth0 src host 10.142.51.196
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
07:49:09.676682 IP (tos 0x0, ttl 64, id 58022, offset 0, flags [DF], proto GRE (47), length 98)
10.142.51.196 > 10.142.51.197: GREv0, Flags [none], length 78
IP (tos 0x0, ttl 64, id 57881, offset 0, flags [DF], proto TCP (6), length 60)
192.168.99.21.56184 > 192.168.99.10.http: Flags [S], cksum 0x3150 (correct), seq 2042147917, win 28440, options [mss 1422,sackOK,TS val 2774612 ecr 0,nop,wscale 7], length 0
07:49:09.676978 IP (tos 0x0, ttl 64, id 58023, offset 0, flags [DF], proto GRE (47), length 90)
10.142.51.196 > 10.142.51.197: GREv0, Flags [none], length 70
IP (tos 0x0, ttl 64, id 57882, offset 0, flags [DF], proto TCP (6), length 52)
192.168.99.21.56184 > 192.168.99.10.http: Flags [.], cksum 0xf6d9 (correct), ack 2040333556, win 223, options [nop,nop,TS val 2774612 ecr 2775178], length 0
...
ホスト3 → httpdコンテナ
異るVLAN上にあるホスト3からのパケットが、ホスト3のbr0を経由してGREでラップされてホスト1のeth0に到達し、ホスト1のbr0を経由してhttpdコンテナと通信できていることがわかる。
root@pipework03:~# 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.24 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=1.23 ms
...
root@pipework01:~# tcpdump -v -i eth0 src host 10.106.242.2
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
07:52:23.437254 IP (tos 0x0, ttl 57, id 9749, offset 0, flags [DF], proto GRE (47), length 122)
10.106.242.2 > 10.142.51.197: GREv0, Flags [none], length 102
IP (tos 0x0, ttl 64, id 46509, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.99.253 > 192.168.99.10: ICMP echo request, id 1475, seq 1, length 64
07:52:24.438746 IP (tos 0x0, ttl 57, id 9837, offset 0, flags [DF], proto GRE (47), length 122)
10.106.242.2 > 10.142.51.197: GREv0, Flags [none], length 102
IP (tos 0x0, ttl 64, id 46598, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.99.253 > 192.168.99.10: ICMP echo request, id 1475, seq 2, length 64
root@pipework03:~# 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">
...
root@pipework01:~# tcpdump -v -i eth0 src host 10.106.242.2
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
07:54:46.513808 IP (tos 0x0, ttl 57, id 44524, offset 0, flags [DF], proto GRE (47), length 98)
10.106.242.2 > 10.142.51.197: GREv0, Flags [none], length 78
IP (tos 0x0, ttl 64, id 26818, offset 0, flags [DF], proto TCP (6), length 60)
192.168.99.253.33516 > 192.168.99.10.http: Flags [S], cksum 0xb799 (correct), seq 3268861327, win 28440, options [mss 1422,sackOK,TS val 2864461 ecr 0,nop,wscale 7], length 0
07:54:46.515162 IP (tos 0x0, ttl 57, id 44525, offset 0, flags [DF], proto GRE (47), length 90)
10.106.242.2 > 10.142.51.197: GREv0, Flags [none], length 70
IP (tos 0x0, ttl 64, id 26819, offset 0, flags [DF], proto TCP (6), length 52)
192.168.99.253.33516 > 192.168.99.10.http: Flags [.], cksum 0xa958 (correct), ack 1421784234, win 223, options [nop,nop,TS val 2864461 ecr 2859388], length 0
...
clien3コンテナ → httpdコンテナ
ホスト3上にあるclient3コンテナからのパケットが、ホスト3のbr0経由でGREでラップされてホスト1のeth0に到達し、httpdコンテナと通信できていることがわかる。
root@d986d5cedb1a:/# 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.70 ms
64 bytes from 192.168.99.10: icmp_seq=2 ttl=64 time=1.31 ms
...
root@pipework01:~# tcpdump -v -i eth0 src host 10.106.242.2
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
07:59:31.649646 IP (tos 0x0, ttl 57, id 17207, offset 0, flags [DF], proto GRE (47), length 122)
10.106.242.2 > 10.142.51.197: GREv0, Flags [none], length 102
IP (tos 0x0, ttl 64, id 36443, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.99.31 > 192.168.99.10: ICMP echo request, id 2908, seq 1, length 64
07:59:32.651510 IP (tos 0x0, ttl 57, id 17293, offset 0, flags [DF], proto GRE (47), length 122)
10.106.242.2 > 10.142.51.197: GREv0, Flags [none], length 102
IP (tos 0x0, ttl 64, id 36673, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.99.31 > 192.168.99.10: ICMP echo request, id 2908, seq 2, length 64
root@d986d5cedb1a:/# 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">
...
root@pipework01:~# tcpdump -v -i eth0 src host 10.106.242.2
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
08:00:48.250724 IP (tos 0x0, ttl 57, id 29998, offset 0, flags [DF], proto GRE (47), length 98)
10.106.242.2 > 10.142.51.197: GREv0, Flags [none], length 78
IP (tos 0x0, ttl 64, id 44503, offset 0, flags [DF], proto TCP (6), length 60)
192.168.99.31.53536 > 192.168.99.10.http: Flags [S], cksum 0x8ae9 (correct), seq 1664400199, win 28440, options [mss 1422,sackOK,TS val 2954896 ecr 0,nop,wscale 7], length 0
08:00:48.252076 IP (tos 0x0, ttl 57, id 29999, offset 0, flags [DF], proto GRE (47), length 90)
10.106.242.2 > 10.142.51.197: GREv0, Flags [none], length 70
IP (tos 0x0, ttl 64, id 44504, offset 0, flags [DF], proto TCP (6), length 52)
192.168.99.31.53536 > 192.168.99.10.http: Flags [.], cksum 0x4003 (correct), ack 2365741000, win 223, options [nop,nop,TS val 2954896 ecr 2949822], length 0
...
まとめ
pipeworkとGREトンネルを使うことで、L2 & L3で接続された複数ホスト間に仮想ネットワークを敷設してDockerコンテナを所属させ、相互に通信させることができた。
各仮想ブリッジのSTPをonにすれば、GREをフルメッシュで設定しても動作するかもしれないが、未検証。