一.Docker的网络概念
容器网络模型主要包含了三个概念:
-
network:网络,这里可以理解为一个Driver,是一个第三方网络栈,包含多种网络模式。
- 单主机网络模式(none、host、bridge)
- 多主机网络模式(overlay、macvlan、flannel)
-
sandbox:沙盒,它定义了容器内的虚拟网卡、DNS和路由表,是network namespace的一种实现,是容器的内部网络栈。
-
endpoint:端点,用于连接sandbox和network。
这里,我们可以类比传统网络模型,将network比作交换机,sandbox比作网卡,endpoint比作接口和网线。
二.Docker的网络模式
这里网络模式包含:
- host模式
- none模式
- bridge模式
- container模式
2.1 host模式
这个相当于Vmvare中的桥接模式,与宿主机在同一个网络中,但是没有独立的IP地址。
Docker不会为容器创建独有的network namespace,使用宿主机默认的网络命名空间,共享一个网络栈。表现为容器内核宿主机的IP一致。这种模式适用于网络性能要求较高的场景,但网络隔离性不太好。
2.2 bridge模式
桥接模式,这里相当于Vmvare中的Nat模式。
Docker进程启动时会创建一个docker0网桥,docker会为容器创建独有的network namespace,也会为这个命名空间配置好虚拟网卡、路由、DNS、IP地址与iptables规则(也就是sanbox内容)
2.2.1 Docker完成Bridge网络配置详细说明
1.在主机上创建一堆虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
2.Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以veth45h6这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show查看。
[root@harbor ~]# brctl show
bridge name bridge id STP enabled interfaces
br-2ba1d6a2e994 8000.02426cb4a81a no veth6a79ace
br-8d4b6181687f 8000.0242d8d0780d no
docker0 8000.02424dbb4b07 no
3.从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
[root@harbor ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b59058aece1 docker-nexus3:v1 "sh -c ${SONATYPE_DI…" 2 months ago Up 2 months 0.0.0.0:81->8081/tcp nexus3
[root@harbor ~]# docker inspect 4b59058aece1
.......
"Networks": {
"nexus_default": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"4b59058aece1",
"docker_nexus3"
],
"NetworkID": "2ba1d6a2e994bb68c9a9ec000867db8fb14e20c6abcaa95f9399b0d9a270b960",
"EndpointID": "e191fe5833aff25bbc6f71c215a717c5fa6c9f2b62690d94806768a302272129",
"Gateway": "172.18.0.1",
"IPAddress": "172.18.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:12:00:02",
"DriverOpts": null
}
}
}
}
]
# 查看nexus_default的bridge network
[root@harbor_reg ~]# docker network inspect nexus_default
[
{
"Name": "nexus_default",
"Id": "2ba1d6a2e994bb68c9a9ec000867db8fb14e20c6abcaa95f9399b0d9a270b960",
"Created": "2020-08-24T10:20:21.947908808+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"4b59058aece184806ecc8d7d2c7c9dd93b24d7d120ea782d5c6909819725fe2d": {
"Name": "nexus3",
"EndpointID": "e191fe5833aff25bbc6f71c215a717c5fa6c9f2b62690d94806768a302272129",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "nexus",
"com.docker.compose.version": "1.23.2"
}
}
]
2.3 none模式
none模式可以说是桥接模式的一种特例,docker会为容器创建独有的network namespace ,但不会为这个命名空间准备虚拟网卡,IP地址,路由等,需要用户自己配置。这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
2.4 container模式
容器共享模式,这种模式是host模式的一种延伸,一组容器共享一个network namespace。对外表现为它们有共同的IP地址,共享一个网络栈。
三.Docker跨主机网络通讯
默认情况下,单台主机上的Docker容器可以通过docker0网桥直接通信,而不同主机上的Docker容器之间只能通过在主机上做端口映射进行通信。这种端口映射方式对许多集群应用来说非常不方便,如果可以让Docker容器直接使用自己的IP地址进行通信可以解决很多问题。这里按照实现原理可以分为:
- 直接路由模式
- overlay隧道模式(如flannel、ovs+gre)
- 桥接模式(如pipework)
3.1 直接路由
直接在两侧主机增加静态路由来实现:
ip route add 172.16.1.0/24 via 192.168.20.1
ip route add 172.16.2.0/24 via 192.168.20.2
注意:centos系统需要卡其ip转发
vim /etc/sysctl.d/99-sysctl.conf
net.ipv4.ip_forward = 1
sysctl -p
这里测试两台主机的容器跨主机通信可以参考此博文,相当详细:https://www.cnblogs.com/xiao987334176/p/10049844.html
3.2 overlay隧道模式
这里以flannel(flannel+udp或flannel+vxlan)来说明
flannel实现的容器的跨主机通信过程如下过程实现:
- 每个主机安装并运行etcd和flannel
- 在etcd中规划配置所有主机的docker0子网范围
- 每个主机上的flanneld根据etcd中的配置,为本主机的docker0分配子网,保证所有主机的docker0网段不重复,并将结果(及本主机上的docker0子网信息和本主机IP的对应关系)存储到etcd中,这样etcd就保存了所有主机上的docker子网信息和本主机IP的对应关系。
- 当需要与其它主机上的网络进行通信时,查找etcd数据库,找到目的容器的子网所对应的outip(目的宿主机的IP)。
- 将原始数据包封装在Vxlan或UDP数据包,IP层以outip为目的IP进行封装。
- 由于目的IP是宿主机IP,因此路由是可达的。
- Vxlan或UDP数据包到达目的宿主机解封装,解出原始数据包,最终到达目的容器。
3.3 桥接模式
这里可以通过静态指定容器的IP为宿主机同一个网络的形式来实现。这里不做具体说明,可以参考其它博文实现:https://blog.csdn.net/xpt211314/article/details/97375671
参考文档连接:
https://www.jianshu.com/p/22a7032bb7bd
https://zhuanlan.zhihu.com/p/82735394