Docker的网络模式和如何跨主机通信

  1. 云栖社区>
  2. 博客>
  3. 正文

Docker的网络模式和如何跨主机通信

smooth00 2018-09-26 17:44:20 浏览293 评论1

摘要: Docker有四种网络模式:Bridge、Host、Container、None,一般常用的是前面两种,默认的是第一种,不安全的是第二种,以下介绍一下四种网络模式,并重点介绍一下如何配置自己的跨主机通信网络。

Docker有四种网络模式:Bridge、Host、Container、None,一般常用的是前面两种,默认的是第一种,不安全的是第二种,以下介绍一下四种网络模式,并重点介绍一下如何配置自己的跨主机通信网络。

一、网络模式介绍

1、Bridge模式:

        默认是这种模式(使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看),用Rancher工具创建Docker对应的托管模式也属于这种。当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

        从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看(该命令可以通过yum install -y bridge-utils安装)。具体网络架构如下图所示:

2、Host模式:

        如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。具体网络架构如下所示:

3、Container模式

        这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。具体网络架构如下所示:

4、None模式

        使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。Node模式示意图如下:

5、其他模式

以上4种模板是基本模式,如果使用Rancher(容器编排和管理系统),还能看到托管模式(managed),这种模式是一种复杂网络模式,是通过Rancher在各个主机上部署的network-services/network-manager容器服务进行管理,IP的分配策略完全不同于Bridge。具体的管理机制目前还不清楚,但是这种模式的网络性能是比较差的(我做过一次网络吞吐压力测试),甚至有时候导致以docker attach或exec命令连接进入容器都很困难。所以从性能角度来考虑,还是推荐使用默认的Bridge模式。

二、跨主机通信

        Docker默认的网络环境下,单台主机上的Docker容器可以通过docker0网桥直接通信,而不同主机上的Docker容器之间只能通过在主机上做端口映射进行通信。这种端口映射方式对很多集群应用来说可能不方便。如果能让Docker容器之间直接使用自己的IP地址进行通信,会解决很多问题。按实现原理可分别直接路由方式、Overlay隧道方式(如flannel、ovs+gre)、桥接方式(如pipework)。

1、直接路由

        通过在Docker主机上添加静态路由实现跨宿主机通信:

2、隧道方式:Flannel(Flannel + UDP 或者 Flannel + VxLAN)

Flannel实现的容器的跨主机通信通过如下过程实现:

  • 每个主机上安装并运行etcd和flannel;
  • 在etcd中规划配置所有主机的docker0子网范围;
  • 每个主机上的flanneld根据etcd中的配置,为本主机的docker0分配子网,保证所有主机上的docker0网段不重复,并将结果(即本主机上的docker0子网信息和本主机IP的对应关系)存入etcd库中,这样etcd库中就保存了所有主机上的docker子网信息和本主机IP的对应关系;
  • 当需要与其他主机上的容器进行通信时,查找etcd数据库,找到目的容器的子网所对应的outip(目的宿主机的IP);
  • 将原始数据包封装在VXLAN