前面我们通过对虚拟化网络基础知识的一番铺垫后,现在,我们就可以尝试使用这些知识去解构容器间的通信原理了,毕竟运用知识去解决问题,才是学习网络虚拟化的根本目的。
我们先以 Docker 为目标,谈一谈Docker 所提供的容器通信方案。当下节课介绍过 CNI 下的 Kubernetes 网络插件生态后,你也许会觉得 Docker 的网络通信相对简单,对于某些分布式系统的需求来说,甚至是过于简陋了。不过,虽然容器间的网络方案多种多样,但通信主体都是固定的,不外乎没有物理设备的虚拟主体(容器、Pod、Service、Endpoints 等等)、不需要跨网络的本地主机、以及通过网络连接的外部主机三种层次。
所有的容器网络通信问题,其实都可以归结为**本地主机内部的多个容器之间、本地主机与内部容器之间,以及跨越不同主机的多个容器之间的通信问题,其中的许多原理都是相通的(本班同学间交流,本班老师和同学交流,本班同学和外班同学交流)**,所以我认为 Docker 网络的简单,在作为检验前面网络知识有没有理解到位时,倒不失为一种优势。
Docker 的网络方案在操作层面上,是指能够直接通过docker run --network参数指定的网络,或者是先被docker network create创建后再被容器使用的网络。安装 Docker 的过程中,会自动在宿主机上创建一个名为 docker0 的网桥,以及三种不同的 Docker 网络,分别是 bridge、host 和 none,你可以通过docker network ls命令查看到这三种网络,具体如下所示:
代码语言:javascript复制$ docker network ls
NETWORK ID NAME DRIVER SCOPE
2a25170d4064 bridge bridge local
a6867d58bd14 host host local
aeb4f8df39b1 none null local
事实上,这三种网络,对应着 Docker 提供的三种开箱即用的网络方案,它们分别为:
用过虚拟机的读者应该都知道,设置虚拟机的时候也是这几种模式。
- 桥接模式,使用--network=bridge指定,这种也是未指定网络参数时的默认网络。桥接模式下,Docker 会为新容器分配独立的网络名称空间,创建好 veth pair,一端接入容器,另一端接入到 docker0 网桥上。Docker 会为每个容器自动分配好 IP 地址,默认配置下的地址范围是 172.17.0.0/24,docker0 的地址默认是 172.17.0.1,并且会设置所有容器的网关均为 docker0,这样所有接入同一个网桥内的容器,可以直接依靠二层网络来通信,在此范围之外的容器、主机就必须通过网关来访问(具体过程我在前面介绍 Linux Bridge 时已经举例讲解过了,这里不再啰嗦)。
- 主机模式,使用--network=host指定。主机模式下,Docker 不会为新容器创建独立的网络名称空间,这样容器一切的网络设施,比如网卡、网络栈等,都会直接使用宿主机上的,容器也就不会拥有自己独立的 IP 地址。在这个模式下与外界通信,也不需要进行 NAT 转换,没有性能损耗,但它的缺点也十分明显,因为没有隔离,就无法避免网络资源的冲突,比如端口号就不允许重复。
- 空置模式,使用--network=none指定。空置模式下,Docker 会给新容器创建独立的网络名称空间,但是不会创建任何虚拟的网络设备,此时容器能看到的只有一个回环设备(Loopback Device)而已。提供这种方式是为了方便用户去做自定义的网络配置,比如自己增加网络设备、自己管理 IP 地址,等等。
而除了前面三种开箱即用的网络方案以外,Docker 还支持由用户自行创建的网络,比如说:
- 容器模式,创建容器后使用--network=container:容器名称指定。容器模式下,新创建的容器将会加入指定的容器的网络名称空间,共享一切的网络资源,但其他资源,比如文件、PID 等默认仍然是隔离的。两个容器间可以直接使用回环地址(localhost)通信,端口号等网络资源不能有冲突。
- MACVLAN 模式,使用docker network create -d macvlan创建。这种网络模式允许为容器指定一个副本网卡,容器通过副本网卡的 MAC 地址来使用宿主机上的物理设备,所以在追求通信性能的场合,这种网络是最好的选择。这里要注意,Docker 的 MACVLAN 只支持 Bridge 通信模式,所以在功能表现上跟桥接模式是类似的。
- Overlay 模式,使用docker network create -d overlay创建。Docker 说的 Overlay 网络,实际上就是特指 VXLAN,这种网络模式主要用于 Docker Swarm 服务之间进行通信。然而由于 Docker Swarm 败给了 Kubernetes,并没有成为主流,所以这种网络模式实际上很少被人使用。
小结
虚拟化网络是容器编排必不可少的功能,网络的功能和性能,对应用程序各个服务间通讯都有非常密切的关联,这一点你要重点关注。在实际生产中,容器编排系统就是由一批容器通过网络交互来共同对外提供服务的,其中的开发、除错、效率优化等工作,都离不开这些基础的网络知识。
一课一思
你在使用 Docker 时,有没有关注或者调整过它的容器通讯网络?在哪些需求场景下你做出过调整呢?