基于对network namespace的控制,docker可以为在容器创建隔离的网络环境,在隔离的网络环境下,容器具有完全独立的网络栈,与宿主机隔离,也可以使容器共享主机或者其他容器的网络命名空间,基本可以满足开发者在各种场景下的需要。按docker官方的说法,docker容器的网络有五种模式:
- bridge:docker默认的网络模式,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。容器从原理上是可以与宿主机乃至外界的其他机器通信的。同一宿主机上,容器之间都是连接到docker0这个网桥上的,它可以作为虚拟交换机使容器可以相互通信。然而,由于宿主机的IP地址与容器veth pair的 IP地址均不在同一个网段,故仅仅依靠veth pair和namespace的技术,还不足以使宿主机以外的网络主动发现容器的存在。为了使外界可以方位容器中的进程,docker采用了端口绑定的方式,也就是通过iptables的NAT,将宿主机上的端口端口流量转发到容器内的端口上。很明显,bridge模式的容器与外界通信时,必定会占用宿主机上的端口,从而与宿主机竞争端口资源,对宿主机端口的管理会是一个比较大的问题。同时,由于容器与外界通信是基于三层上iptables NAT,性能和效率上的损耗是可以预见的。
- host:直接使用容器宿主机的网络命名空间。采用host模式的容器,可以直接使用宿主机的IP地址与外界进行通信,若宿主机具有公有IP,那么容器也拥有这个公有IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行NAT转换,而且由于容器通信时,不再需要通过linuxbridge等方式转发或者数据包的拆封,性能上有很大优势。当然,这种模式有优势,也就有劣势,主要包括以下几个方面:
- 最明显的就是容器不再拥有隔离、独立的网络栈。容器会与宿主机竞争网络栈的使用,并且容器的崩溃就可能导致宿主机崩溃,在生产环境中,这种问题可能是不被允许的。
- 容器内部将不再拥有所有的端口资源,因为一些端口已经被宿主机服务、bridge模式的容器端口绑定等其他服务占用掉了。
- none:为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo回环,用户可以在此基础上,对容器网络做任意定制。
- 其他容器:与host模式类似,只是容器将与指定的容器共享网络命名空间,也就是网卡。其他网络模式是docker中一种较为特别的网络的模式。在这个模式下的容器,会使用其他容器的网络命名空间,其网络隔离性会处于bridge桥接模式与host模式之间。当容器共享其他容器的网络命名空间,则在这两个容器之间不存在网络隔离,而她们又与宿主机以及除此之外其他的容器存在网络隔离。
- 用户自定义:docker 1.9版本以后新增的特性,允许容器使用第三方的网络实现或者创建单独的bridge网络,提供网络隔离能力。除了Docker自动创建的三个网络,用户可以为Docker创建新的网络。为Docker增加新的网络的方式有两种——使用Docker自带的bridge和overlay两种网络驱动,或提供新的网络插件。
这些网络模式在相互网络通信方面的对比如下所示:
模式 | 支持多主机 | 访问外部网络 | 容器互访 |
---|---|---|---|
bridge | no | 宿主机端口绑定 | Linux bridge |
host | yes | 宿主机网络 | 宿主机网络 |
none | no | 无法通信 | 只能通过link通信 |
其他容器 | no | 宿主机端口绑定 | 通过link通信 |
用户自定义 | 按网络实现而定 | 按网络实现而定 | 按网络实现而定 |
本文同时对Docker跨主机之间容器通信的overlay网络模式作简要介绍,其详细说明创建方法可参考Getting started for overlay.
Docker内置overlay网路模式驱动libnetwork,可以用于创建跨多个主机的网络。在同一个overlay网络里的容器,无论运行在哪个主机上,都能相互通信。
要创建overlay网络,首先要有一个提供key-value存储服务的服务器,当前Docker支持的key-value存储服务器有Consul, Etcd和ZooKeeper. 组成overlay网络的Docker的主机之间、Docker主机和key-value存储服务器之间都要能互通互联。在Docker主机上还要开放如下两个端口:
udp端口:4789,用于传输VXLAN网络数据的端口
tcp/udp端口:7946,用于控制平面的端口
对要加入overlay网络里里的每台Docker主机,都要完成如下配置:
--cluster-store=PROVIDER://URL/ 配置key-value存储服务器的地址
--cluster-advertise=HOST_IP|HOST_IFACE:PORT Docker所在的当前主机的地址和端口
--cluster-store-opt=KEY-VALUE OPTIONS 其他配置信息,如TLS证书等
然后用docker network create命令就能创建一个overlay网络,并能在该网络上创建容器。
$ docker network create --driver overlay my-multi-host-network
$ docker run -itd --net=my-multi-host-network busybox