docker四种单机网络模型
docker共有4种网络模型:分别是:封闭式网络、桥接式网络、联邦式网络、开放式网络;网络安全性依次减弱,因为网络对外的开放性依次加强
本地查看网络模式:
[root@reg harbor]# docker network ls
NETWORK ID NAME DRIVER SCOPE
c551b2c85d8b bridge bridge local
ca84b629148b host host local
cab24ad22074 none null local
# 安装docker后,默认具有3个网络,none,host,和bridge
# docker run --network ,运行容器时,可以指定其所运行的网络,默认是bridge,桥接到docker0上;
[root@reg harbor]# ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:51:02:79:1c txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
封闭网络:none-container
该网络中容器,只有一个环回接口,不进行网络通信与外界;适合执行一次性job的容器;
实验
1、运行一个none网络的容器;
[root@reg harbor]# docker run --name b1 --rm -it --network none busybox
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
# 可见,只有一个lo口,没有任何路由,无法网络通信;
none模型图
none网络下的容器,只有一个lo口,无法和宿主机及其其他容器进行通信;适合无需网络通信的容器;
桥接网络:bridge-container
参考:https://docs.docker.com/network/network-tutorial-standalone/
该网络中容器,桥接到宿主机上docker0网络,默认是172.17.0.0.0/16网段,容器通过nat形式借助宿主机网络与外面网络通信;
实验
1、运行一个bridge网络的busybox镜像
# 默认即为bridge网络,可不加--network bridge
[root@reg harbor]# docker run --name b1 -it --network bridge busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1016 (1016.0 B) TX bytes:0 (0.0 B)
# 默认2条路由,一是同连在docker0上的其他容器同172.17网段的路由;
# 二是以docker0为默认网关,借助docker0,eth0出去;
/ # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
# 可以访问宿主机,以及宿主机同网段的其他ip;
/ # ping 192.168.80.101
PING 192.168.80.101 (192.168.80.101): 56 data bytes
64 bytes from 192.168.80.101: seq=0 ttl=64 time=0.174 ms
^C
--- 192.168.80.101 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.174/0.174/0.174 ms
/ # ping 192.168.80.102
PING 192.168.80.102 (192.168.80.102): 56 data bytes
64 bytes from 192.168.80.102: seq=0 ttl=63 time=0.890 ms
64 bytes from 192.168.80.102: seq=1 ttl=63 time=0.662 ms
2、查看生成一个一对网卡
[root@reg harbor]# yum install -y bridge-utils
[root@reg harbor]# brctl show
bridge name bridge id STP enabled interfaces
br-97c0b3d84ade 8000.0242418a7b64 no
# 该网卡即为容器b1的eth0的另一半,接在了docker0上;
docker0 8000.02425102791c no
bridge模型图
描述:
docker的桥接模型下,每创建一个容器,都会生成一对网卡,一头接在容器上,为容器的eth0;一头接在docker0上,为vethxx开头的网卡,docker的行为类似交换机,与外界通信时,借助docker和宿主机的eth0网卡,经过nat通信
user-defined-network
在单机桥接网络的基础之上,可以定义用户需要的网络,即再定义另外网段的桥接网络,官方介绍,如默认是172.17.0.0/16网段,用户可以自定义172.18.0.0/16网段,构成2个局域网,
# 创建一个名为alpine-net的网络;
docker network create --driver bridge alpine-net
# 自动被分配为172.18网段;
docker network inspect alpine-net
[
{
"Name": "alpine-net",
"Id": "e9261a8c9a19eabf2bf1488bf5f208b99b1608f330cff585c273d39481c9b0ec",
"Created": "2017-09-25T21:38:12.620046142Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
# 创建容器时通过alpine-net加入该自定义网络
docker run -dit --name alpine1 --network alpine-net alpine ash
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
e9261a8c9a19 alpine-net bridge local
17e324f45964 bridge bridge local
6ed54d316334 host host local
7092879f2cc8 none null local
联邦网络:joined-container
该网络中容器,多个容器共享一个tcp/ip协议栈,一般适用于边车模式捆绑一起运行的容器,其主容器和辅助容器公用一套协议栈;联盟网络是基于bridge网络;
也叫container模型,创建容器时,通过container:一个已经运行的容器名或id来加入其网络;
实验
1、创建第一个容器b1
[root@reg harbor]# docker run --name b1 --rm -it busybox
/ # echo joined-containers > /tmp/index.html
/ # httpd -h /tmp/
/ # netstat -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 :::80 :::* LISTEN
/ # wget -O - -q 127.0.0.1
joined-containers
/ # ifconfig -a
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:0 (0.0 B)
2、创建容器b2,指明公用b1的网络
# 新开一个窗口,利用参数--network container:b1 指明公用b1的网络;
# 可以看到,b2和b1的网卡一样,监听的服务和端口一样,因为是同一个net namespace
[root@reg ~]# docker run --name b2 --rm -it --network container:b1 busybox
/ # netstat -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 :::80 :::* LISTEN
/ # wget -O - -q 127.0.0.1
joined-containers
/ # ifconfig -a
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:0 (0.0 B)
# 看到,文件系统不共享;只是服务共享;
/ # ls /tmp/
joined模型图
联邦网络模式其实还是bridge模型;联邦网络模型之下,2个以及以上的容器公用一个net namespace,但文件系统,user,等仍为隔离的;创建方法:先创建一个容器,然后在此容器基础之上,再创建容器时,指明网络为公用第一个容器的网络即可;
主机网络:host-container
该网络中容器,容器借用宿主机的网络,和宿主机公用一个tcp/ip协议栈;
实验
1、运行一个host网络的容器
# 从容器中看,可以发现监听的端口,网卡都是和宿主机一模一样;
# host网络的容器,不需要-p映射其中的服务,但是注意,和宿主机端口不能冲突;
[root@reg harbor]# docker run --name b1 --rm -it --network host busybox
/ # ifconfig
br-97c0b3d84ade Link encap:Ethernet HWaddr 02:42:41:8A:7B:64
inet addr:172.18.0.1 Bcast:172.18.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:41ff:fe8a:7b64/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:79 errors:0 dropped:0 overruns:0 frame:0
TX packets:94 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3980 (3.8 KiB) TX bytes:19082 (18.6 KiB)
docker0 Link encap:Ethernet HWaddr 02:42:51:02:79:1C
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:51ff:fe02:791c/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:5 errors:0 dropped:0 overruns:0 frame:0
TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:308 (308.0 B) TX bytes:1026 (1.0 KiB)
eth0 Link encap:Ethernet HWaddr 00:0C:29:2D:5D:7C
inet addr:192.168.80.101 Bcast:192.168.80.255 Mask:255.255.255.0
inet6 addr: fe80::eb02:a6b5:be84:952/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2382 errors:0 dropped:0 overruns:0 frame:0
TX packets:1278 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1054246 (1.0 MiB) TX bytes:155717 (152.0 KiB)
eth1 Link encap:Ethernet HWaddr 00:0C:29:2D:5D:86
inet addr:192.168.10.101 Bcast:192.168.10.255 Mask:255.255.255.0
inet6 addr: fe80::7822:f591:feb0:47ea/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:48 errors:0 dropped:0 overruns:0 frame:0
TX packets:14 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:4338 (4.2 KiB) TX bytes:1040 (1.0 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:352 errors:0 dropped:0 overruns:0 frame:0
TX packets:352 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:34827 (34.0 KiB) TX bytes:34827 (34.0 KiB)
/ # netstat -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp 0 0 :::22 :::* LISTEN
tcp 0 0 ::1:25 :::* LISTEN
2、host模式运行一个nginx容器
host模型图
host网络模型下,所有运行在该模式的容器,都不会获得单独的net namespace,而是公用宿主机的tcp/ip协议栈;
docker两种跨主机网络模型
以上四种网络模型,均为单机情况下,docker提供的网络模型;且生产主机不可能只有单主机;
在多宿主机互联的情况下,docker另外提供了2种网络模型,分别是macvlan和overlay网络,
- macvlan
- overlay
实验:跨主机容器间通信(overlay)
实验环境:
host2:192.168.80.101
docker0为172.17.10.1/24
host3:192.168.80.102
docker0为172.17.20.1/24
防火墙和selinux全部关闭
2个宿主机的桥接网段不能在同一个网段,所以需要对默认的172.17.0.0/16做修改
-
修改2台宿主机的docker0网段
-
2台宿主机分别启动一个桥接网络的容器
-
2台宿主机分别添加一条静态路由,指向对方的物理网卡的ip
-
其中一台宿主机的物理网卡开启抓包
-
2容器间互ping测试
-
修改2台宿主机的docker0网段
[root@host2 ~]# vim /usr/lib/systemd/system/docker.service [Service] Type=notify # the default is not to use systemd for cgroups because the delegate issues still # exists and systemd currently does not support the cgroup feature set required # for containers run by docker ExecStart=/usr/bin/dockerd --bip=172.17.10.1/24 # 在末尾加了--bip=172.17.10.1/24,指定了docker0上网卡地址,以及其网段; [root@host2 ~]# systemctl daemon-reload [root@host2 ~]# systemctl restart docker [root@host2 ~]# ifconfig docker0 docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.10.1 netmask 255.255.255.0 broadcast 172.17.10.255 --- 同理,host2也对应修改 [root@host3 ~]# grep bip !$ grep bip /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd --bip=172.17.20.1/24 [root@host3 ~]# systemctl daemon-reload [root@host3 ~]# systemctl restart docker [root@host3 ~]# ifconfig docker0 docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.20.1 netmask 255.255.255.0 broadcast 172.17.20.255
-
2台宿主机分别启动一个桥接网络的容器
host2:
[root@host2 ~]# docker run --name b1 -it busybox / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:0A:02 inet addr:172.17.10.2 Bcast:172.17.10.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:10 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:836 (836.0 B) TX bytes:0 (0.0 B) # 此时还无法ping通host3上的启停容器 / # ping 172.17.20.2 PING 172.17.20.2 (172.17.20.2): 56 data bytes ^C --- 172.17.20.2 ping statistics --- 2 packets transmitted, 0 packets received, 100% packet loss / # route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.17.10.1 0.0.0.0 UG 0 0 0 eth0 172.17.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
host3:
[root@host3 ~]# docker run --name b2 -it busybox / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:14:02 inet addr:172.17.20.2 Bcast:172.17.20.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:12 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1016 (1016.0 B) TX bytes:0 (0.0 B)
-
2台宿主机分别添加一条静态路由,指向对方的物理网卡的ip
host2:
[root@host2 ~]# route add -net 172.17.20.0/24 gw 192.168.80.102 [root@host2 ~]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 172.17.20.0 192.168.80.102 255.255.255.0 UG 0 0 0 eth0 [root@host2 ~]# iptables -A FORWARD -s 192.168.80.0/24 -j ACCEPT
host3:
[root@host3 ~]# route add -net 172.17.10.0/24 gw 192.168.80.101 [root@host3 ~]# route -n Kernel IP routing table 172.17.10.0 192.168.80.101 255.255.255.0 UG 0 0 0 eth0 [root@host3 ~]# iptables -A FORWARD -s 192.168.80.0/24 -j ACCEPT
-
其中一台宿主机的物理网卡开启抓包
[root@host3 ~]# tcpdump -i eth0 -vnn icmp tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 14:30:14.550012 IP (tos 0x0, ttl 63, id 6477, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.80.101 > 172.17.20.2: ICMP echo request, id 2816, seq 0, length 64 14:30:14.550099 IP (tos 0x0, ttl 63, id 50101, offset 0, flags [none], proto ICMP (1), length 84) 172.17.20.2 > 192.168.80.101: ICMP echo reply, id 2816, seq 0, length 64 14:30:15.551182 IP (tos 0x0, ttl 63, id 6764, offset 0, flags [DF], proto ICMP (1), length 84) # 2台宿主机没配置上面接受来源是192.168.80.0/24的iptable规则时,是无法ping通,ping包有去无回,因为被宿主机过滤掉了 # 添加后正常ping通,可以看出在host3的eth0上来看,来源ip是host2的物理网卡80.101,访问的是容器的桥接网段,反之亦然,因为是overlay叠加网络,数据包封装了2层ip头部,对于数据包的接收方来说,宿主机接收到之后,进到容器网段之前,看到的只是发送方容器所在宿主机的物理网卡的ip,即外层ip;
-
2容器间互ping测试
/ # ping 172.17.20.2 PING 172.17.20.2 (172.17.20.2): 56 data bytes 64 bytes from 172.17.20.2: seq=0 ttl=62 time=0.571 ms 64 bytes from 172.17.20.2: seq=1 ttl=62 time=2.233 ms 可以ping通;
dokcer网络模型总结
- none无网络
- host共享主机网络
- bridge,也叫standlone网络,(默认网络)
- 延伸1:joined-container联盟网络
- overlay
- macvlan
利用容器名通信
-
启动2个容器,正常启动
[root@host2 ~]# docker run --name b1 --rm -it busybox / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:0A:02 inet addr:172.17.10.2 Bcast:172.17.10.255 Mask:255.255.255.0 / # cat /etc/hosts 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 172.17.10.2 397b8c9382f4 [root@host2 ~]# docker run --name b2 --rm -it busybox / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:0A:03 inet addr:172.17.10.3 Bcast:172.17.10.255 Mask:255.255.255.0 / # cat /etc/hosts 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 172.17.10.3 50e37004077e / # ping 172.17.10.2 PING 172.17.10.2 (172.17.10.2): 56 data bytes 64 bytes from 172.17.10.2: seq=0 ttl=64 time=0.210 ms # 启动的2个容器,可以通过ip互相ping通,但是无法通过主机名,容器名,容器id实现互通, # 因为一hosts文件没有对应记录,二没有dns服务
-
启动第3个容器,加入--link参数
[root@host2 ~]# docker run --name b3 --rm -it --link b1 --link b2 busybox / # cat /etc/hosts 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 172.17.10.2 b1 397b8c9382f4 172.17.10.3 b2 50e37004077e 172.17.10.4 b629dc90c558 # --link后跟,已经存在的容器名,可以在hosts文件中加入一条记录,从而实现利用主机名通信; / # ping b1 PING b1 (172.17.10.2): 56 data bytes 64 bytes from 172.17.10.2: seq=0 ttl=64 time=0.123 ms ^C --- b1 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.123/0.123/0.123 ms / # ping b2 PING b2 (172.17.10.3): 56 data bytes 64 bytes from 172.17.10.3: seq=0 ttl=64 time=0.107 ms ^C --- b2 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.107/0.107/0.107 ms