要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包。如果不同子网之间要进行通信,需要路由机制。
当 Docker守护进程启动时,会自动在主机上创建一个 docker0
虚拟网桥,它会在挂载到它的网口之间进行转发。同时,Docker 随机分配一个本地未占用的私有网段中的一个地址给 docker0
接口,此后启动的容器,在默认的情况下,容器内的网口会自动分配一个与 docker0
同一网段的IP地址,并让它们彼此连通(这样的一对接口叫做veth pair)。
默认情况下,不指定容器的网络类型时,容器使用bridge网络类型。此时容器使用的是同一网段的网络,ping对方的IP地址可以连通。
如果想要实现ping另一个容器的容器名称或容器id能够连通,需要指定两个容器使用同一个网络。具体步骤如下
1 | docker network create -d bridge test # 自定义创建一个Docker网络,类型为bridge,命名为test,任意分配网段 |
此时,容器间ping另一个容器的容器名称或容器id能够连通
将其他容器加入到此网络中,就可以与此网络中的容器相连通
1 | docker network connect 网络名称 容器id/容器名称 |
如果将Docker容器起在不同的物理主机上,我们不可避免的会遭遇到Docker容器的跨主机通信问题,内置跨主机的网络通信一直是Docker备受期待的功能,其思路无非分为两种: 二层VLAN网络和Overlay网络。
简单来说,二层VLAN网络解决跨主机通信的思路是把原先的网络架构改造为互通的大二层网络,通过特定网络设备直接路由,实现容器点到点的之间通信。Macvlan就是使用二层VLAN网络的方案之一。
Macvlan是一种跨主机的网络模型,可以在自定义的网络类型中作为一种驱动(driver)启用(-d 参数指定)。
macvlan是Linux kernel支持的新特性,支持的版本有v3.9——3.19
和 4.0+
,比较稳定的版本推荐 4.0+
。它一般是以内核模块的形式存在,可以先通过modprobe macvlan
命令加载此模块,然后通过lsmod | grep macvlan
查看是否有结果。如果第一个命令报错,或者第二个命令没有返回,说明当前系统不支持 macvlan,需要升级内核。
相同macvlan网络下容器互通
相同Macvlan网络的架构如下:
当使用 MACVLAN 网络时,Docker 默认的虚拟网卡 docker0 并不会直接参与其中,Docker 为每个容器分配一个唯一的 MAC 地址,这使得每个容器看起来就像是直接连接到物理网络上一样,拥有独立的网络标识。
配置macvlan时,需要指定子网和网关以及连接的物理网卡,启动容器时,需要手动指定IP地址。以下是具体步骤:
1 | # 在两台主机上都执行一次此命令,分别创建一个相同的macvlan网络 |
此时,两个不同主机上的容器能够ping通彼此的IP地址。
不同macvlan网络下容器互通
macvlan 会独占主机的物理网卡,也就是说一个物理网卡只能创建一个 macvlan 网络,否则会报错Error response from daemon: network dm-1d34c56c6448 is already using parent interface enp0s3
。如果我们想创建多个 macvlan 网络就得用多张网卡,但主机的物理网卡数量是有限的。好在macvlan网络也是支持VLAN子接口的,所以,我们可以通过VLAN技术将一个网口划分出多个子网口,这样就可以基于子网口来创建 macvlan网络了。
相同 macvlan 可以通信,不同 macvlan 二层是无法通信的,但是可以借助三层路由完成通信。
具体步骤如下:
详细命令自行查阅相关资料
二层VLAN的方案在传输效率上比Overlay网络占优,然而它也存在一些固有的问题。 这种方法需要二层网络设备支持,通用性和灵活性不如后者。 由于通常交换机可用的VLAN数量都在4000个左右,这会对容器集群规模造成限制,远远不能满足公有云或大型私有云的部署需求; 大型数据中心部署VLAN,会导致任何一个VLAN的广播数据会在整个数据中心内泛滥,大量消耗网络带宽,带来维护的困难。
相比之下,Overlay网络是通过VXLAN技术,充分利用成熟的IP路由协议进行数据分发,能够突破VLAN的4000数量限制,并在必要时可将广播流量转化为组播流量,避免广播数据泛滥。 因此,Overlay网络实际上是目前最主流的容器跨节点数据传输和路由方案。
VXLAN技术
VXLAN:Virtual eXtensible Local Area Network(虚拟化可扩展局域网),从名字上就知道,这是一个 VLAN 的扩展协议。 VXLAN 本质上是一种隧道封装技术。它使用 TCP/IP 协议栈的惯用手法——封装/解封装技术,将 L2 的以太网帧(Ethernet frames)封装成 L4 的 UDP 数据报(datagrams),然后在 L3 的网络中传输,效果就像 L2 的以太网帧在一个广播域中传输一样,实际上是跨越了 L3 网络,但却感知不到 L3 网络的存在。
使用Overlay进行跨主机容器互通
部署consul
Docerk overlay 网络需要一个 key-value 数据库用于保存网络状态信息,包括 Network、Endpoint、IP 等。
Consul、Etcd 和 ZooKeeper 都是 Docker 支持的 key-vlaue 软件。在这里我们介绍consul。
1 | docker image pull consul:latest # 拉取consul镜像 |
创建overlay网络
注意:只需要在任意一个节点创建overlay网络即可,无需在所有节点上执行,因为凡是注册在consul服务中的所有docker实例均为同一个集群,它会自动在所有节点上同步网络。
1 | # 指定网络驱动为overlay,并指定子网和网关 |
创建容器
1 | # 在各个节点启动容器,指定网络为刚刚创建的overlay网络,会发现可以互相ping通,需要注意的是,不同overlay网络是互相隔离的 |
Overlay网络架构
如下图所示,是两个主机的Overlay网络架构图
在容器内查看IP地址,可以发现除了overlay网络分配的一个IP地址(eth0)之外,还多出一个IP地址(eth1),这个IP地址是因为Docker自动创建了一个名为docker_gwbridge的网络,它为使用overlay网络的容器分配了一个额外的IP地址,作用是用于连接外网。
从上图中的数据流向也可以看出,容器通过overlay网络分配的虚拟网卡eth0实现跨主机互联,通过docker_gwbridge网络分配的虚拟网卡eth1实现访问外部网络。