上一篇文章在我们使用docker inspect 查看容器详细信息、使用iptables查看路由策略时发现了docker是有自己的通信机制的,接下来我们将详细讲一下docker的网络结构。
Docker 网络设置了容器如何与其他容器和外部服务通信。为了获得网络访问、容器需要,是 Docker 网络的一部分。容器可以通信的方式取决于它的网络连接。Docker 提供了五种标准网络模式来执行核心网络功能:None、Host(主机)、container模式、bridge模式、Overlay(重叠)、IPvlan、Macvlan。
通信类别
同一台宿主机的容器和容器通信
None模式、Host(主机)模式、container模式、bridge模式
不同宿主机的容器和容器通信
Overlay(重叠)模式、IPvlan模式、Macvlan模式。
docker默认的私有网络
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2"
[root@scdocker docker]# docker inspect sc-nginx-1 查看容器的详细信息
......前面的省略
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "75574c2b181ce5e8ae647ce030d60eb42977979c182c14bbfd429bd46960f8d5",
"EndpointID": "08836438d9540bd5b852df28474e040795ecf4d985c87d85e99db8804c12be25",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
host模式
容器和宿主机共享ip地址,端口号要区别开
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
总结:和宿主机同一个ip+不同端口
none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
只有lo接口,没有其他的接口
对于这个容器,禁用所有网络
container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
bridge模式
每个容器都会获得一个独一无二的 IP 地址。通过与主机的桥接连接,这些容器还可以相互交互,与本地网络(LAN)和 Internet 互联。然而,它们不会以物理设备的形式出现在 LAN 上
docker虚拟出bridge网桥,默认网桥ip是172.17.0.1,其他容器通过与bridge桥接连接宿主机。
创建一个新的网桥,并且启动一个容器连接我的网桥,此时该网桥ip地址为172.18.0.1,容器ip地址为172.18.0.2,网关为网桥的ip地址
[root@lb1 volumes]# docker network create my-net
[root@lb1 volumes]# docker run --name wang-nginx-1 -d --network my-net -p 5566:80 nginx
[root@lb1 volumes]# ip add|egrep br-a5
44: br-a5dde116fb9c: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-a5dde116fb9c
46: vethff49252@if45: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-a5dde116fb9c state UP group default
[root@lb1 volumes]#
[root@lb1 volumes]# docker network inspect my-net
[
{
"Name": "my-net",
"Id": "a5dde116fb9c83144a838a141dd8cce9bdc549c9fd4c03823bf2d5f67c521ea4",
"Created": "2022-03-30T14:43:44.595943546+08:00",
"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,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"25556d5abacf293ac848aaea4160523b6773bd06475c3f8fbdf7f2403faa3c40": {
"Name": "wang-nginx-1",
"EndpointID": "ac1993dd6ed67277c852f01d74c214f83f6b0707a82c1b8070bf2a3000d0034d",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
[root@lb1 volumes]#
连接到用户定义的网桥
[root@lb1 volumes]# docker network connect my-net wang-nginx-1
从用户定义的网桥断开容器
[root@lb1 volumes]# docker network disconnect my-net wang-nginx-1
Overlay模式
以上几种都是一个docker之间的通信,而Overlay可以实现跨docker容器之间的通信
Overlay网络实际上是目前最主流的容器跨节点数据传输和路由方案,overlay网络用于连接不同机器上的docker容器,允许不同机器上的容器相互通信,同时支持对消息进行加密。
Overlay 网络将多个 Docker 守护进程连接在一起,使 swarm(docker的一个集群管理软件) 服务能够相互通信。
底层原理VXLAN
VXLAN是一种隧道技术。通过将虚拟网络中的数据帧封装在实际物理网络中的报文中进行传输。具体实现方式为:将虚拟网络的数据帧添加VXLAN首部后,封装在物理网络中的UDP报文中,然后以传统网络的通信方式传送该UDP报文,到达目的主机后,去掉物理网络报文的头部信息以及VXLAN首部,将报文交付给目的终端。整个通信过程目的终端不会感知到物理网络的存在。
VXLAN用到的技术
- NVE(Network Vritual Endpoint,网络虚拟端点):实现网络虚拟化功能。报文经过NVE封装转换后,NVE间就可基于三层基础网络(ip)建立二层虚拟化网络(接口)。
- VTEP(VXLAN Tunnel Endpoints,VXLAN隧道端点):封装在NVE中,用于VXLAN报文的封装和解封装。
- VNI(VXLAN Network Identifier,VXLAN网络标识ID):类似于VLAN ID,用于区分VXLAN段,不同的VXLAN段不能直接二层网络通信。
大概的通信过程
- 1、左右两边分别为容器节点1与容器节点2。
- 2、当容器节点1发出一个报文时会通过VTEP将这个数据包进行封装,封装完成之后再由ech0转发到对应的主机中。
- 3、通过UDP协议在VXLAN Tunnel隧道中传输。
- 4、对应的主机也通过eth0收到数据包,通过VTEP将收到的数据包进行解封装,从里面取出对应的mac地址等信息发送到对应的容器中
详细通信过程
路线图见上面箭头方向
- 1、容器Container1会通过Container eth0 将这个数据包发送到 10.0.0.1 的网关。
- 2、网关将数据包发送出去后到达br0网桥。
- 3、b20网桥针对VXLAN设备,主要用于捕获对外的数据包通过VETP进行数据包封装。
- 4、封装好将VXLAN格式数据包交给eth0,通过UDP方式交给Container2的eth0。
- 5、Container2收到数据包后通过VETP将数据包解封装。
- 6、网桥通过网关将解封装的数据包转发给Container eth0,完毕通信。
报文封装格式
ipvlan模式
IPvlan 驱动程序让用户可以完全控制 IPv4 和 IPv6 寻址。VLAN 驱动程序建立在此之上,为对底层网络集成感兴趣的用户提供了对第 2 层 VLAN 标记甚至 IPvlan L3 路由的完全控制。
如果你需要将容器服务连接到已有物理网络,此模式会很有用。IPvLAN 网络具有自己的接口,其性能可能比基于桥接网络的网络更好。
上面的图,容器2、3、4、5直接和eth0组成了一个局域网--》相当于一个vlan
下面的操作分成了3个不同的网段,相当于3个不同的vlan
[root@lb1 volumes]# ip add add 192.168.98.2/24 dev ens33 label ens33:20
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:ea:ac:65 brd ff:ff:ff:ff:ff:ff
inet 192.168.2.130/24 brd 192.168.2.255 scope global noprefixroute dynamic ens33
valid_lft 5723sec preferred_lft 5723sec
inet 192.168.100.2/24 scope global ens33 #打标签,假设该网段是vlan
valid_lft forever preferred_lft forever
inet 192.168.99.2/24 scope global ens33:10 #打标签,假设该网段是vlan10
valid_lft forever preferred_lft forever
inet 192.168.98.2/24 scope global ens33:20 #打标签,假设该网段是vlan20
valid_lft forever preferred_lft forever
inet6 fe80::561d:1783:8a81:5deb/64 scope link noprefixroute
Macvlan模式
Macvlan 是一种更高级的选项,让容器能像网络上的物理设备一样运行。它通过为每个容器分配自己的 MAC 地址来实现这一点。
对于此类型的网络,你需要将主机的一个物理网络接口分配给虚拟网络。此外,更广泛的网络还应设置为处理来自具有大量容器的 Docker 主机的许多 MAC 地址
练习
1.查看docker里有哪些网络类型,对应的命名空间
2.创建一个网络的命名空间叫sc
3.创建2个centos7的容器,使用sc这个网络命名空间
4.进入创建容器里面,查看下ip地址,互相ping下
5.创建一个使用默认的命名空间的容器,名字自己定义
6.进入新创建容器,ping使用sc网络命名空间的容器,看是否可以ping通?
结论:同一个网络命名空间的容器能够ping通,不同命名空间的容器之间不能通信