Docker提供了overlay driver,使用户可以创建基于VxLan的overlay网络。
VxLAN可将二层数据封装到UDP进行传输,VxLAN提供与VLAN相同的
以太网二层服务,但拥有更强的扩展性和灵活性。
Docker overlay网络需要一个key-value数据库用于保存网络状态信息,包括Network、Endpoint、IP等。Consul、Etcd、ZooKeeper都是Docker支持的key-value软件,这里使用Consul。
一、准备overlay网络环境
hosts3上部署Consul:
docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap

可以通过http://192.168.11.73:8500访问Consul:


从上图可以看到,加载的实际是文件/usr/lib/systemd/system/docker.service。
修改host1与host2的docker daemon的配置文件/usr/lib/systemd/system/docker.service。

--cluster-store:指定consul地址,表示存储在哪里
--cluster-advertise:告知consul自己的连接地址,本机网卡地址,2376为默认端口
重启docker daemon:
systemctl daemon-reload
systemctl restart docker.service
host1与hosts2将自动注册到Consul数据库:(点击KEY/VALUE,然后点击docker,nodes才会看到)

若物理网卡不支持vxlan,执行:ifconfig ens33 promisc # 开启混杂模式
二、创建overlay网络
在hosts1上创建overlay网络ov_net1:
docker network create -d overlay ov_net1

注意到overlay网络的SCOPE是global,而其他网络为local。
在hosts2上能查看到hosts1上创建的ov_net1(因为网络信息已存如Consul中):

docker network inspect查看ov_net1的详细信息:

三、在overlay中运行容器
hosts1上运行busybox容器并连接到ov_net1:
docker run -itd --name bbox1 --network ov_net1 busybox
查看容器的网络配置:docker exec bbox1 ip r 与 docker exec bbox1 ip addr


bbox1有两个网络接口eth0与eth1。
8号的那个eth0的IP为10.0.0.2,连接的是overlay网络ov_net1,容器的8号网卡连接容器外边的9号,但没在宿主机上找到,这个其实在ip netns网络空间里面,这个我们后边会讲到;
11号的那个eth1的IP为172.18.0.2,容器的11号网卡连接容器外边的12号,在住宿主机上找到了(vethfd2ceeb),默认路由走eth1,但eth1哪来的?
docker会创建一个bridge网络docker_gwbridge,为所有连接到overlay网络的容器提供访问外网的能力。


从docker network inspect docker_gwbridge 的输出可以看到docker_gwbridge的IP范围是172.18.0.0/16,当前连接的容器就是bbox1。

而且此网络的网关就是网桥docker_gwbridge的IP 172.18.0.1:

这样容器bbox1就可以通过docker_gwbridge访问外网:

四、overlay实现跨主机通信
已经在hosts1上运行了容器bbox1。
hosts2上运行busybox容器bbox2并连接到ov_net1:
docker run -itd --name bbox2 --network ov_net1 busybox

bbox2的eth0的IP为10.0.0.3,可以直接ping通bbox1:

可见overlay网络中的容器可以直接通信,实现了DNS服务。
overlay网络的具体实现:
docker会为每个overlay网络创建一个独立的network namespace,其中会有一个linux bridge br0,endpoint还是由veth pair实现,一端连接到容器中eth0,另一端连接到namesapce的br0上。
br0除了连接所有的endpoint,还会连接一个vxlan设备,用于与其他host建立vxlan tunnel。容器之间的数据就是通过这个tunnel通信的。

docker会为我们创建一个独立的网络空间,因为10网段不在物理机上,即我们使用ip a无法看到某个网卡是10网段的。
docker inspect 79 |grep -i sand 查看某个容器属于哪个netns:

使用ip netns查看宿主机的overlay网络的namespace空间,发现没有看到,此时我们需要去docker的文件系统目录下看:

里面有个netns目录,我们把它连接到我们常规查看的网络空间的目录下,然后再次查看
ln -s /var/run/docker/netns/ /var/run/netns
ip netns
这样会报错:

那就将/var/run/docker/netns/目录下的一个一个软连接到/var/run/netns/:
ln -s /var/run/docker/netns/1-16af5cc221 /var/run/netns/1-16af5cc221
ln -s /var/run/docker/netns/5d797e396ed0 /var/run/netns/5d797e396ed0
ln -s /var/run/docker/netns/f4d2d62f0696 /var/run/netns/f4d2d62f0696
再执行ip netns:

hosts2上按照同样的方法:

发现两台主机都有一个1-16af5cc221的空间名字,这就是ov_net1的namespace。
查看一下这个网络空间,发现了9号网卡,之前讲过创建的bbox1容器里面8号网卡连接到9号网卡,但宿主机上找不到9号网卡,在这里找到了:

发现在1-16af5cc221这个网络空间内br0这块网卡是10.0网段的,9那块网卡并没有10.0网段地址,其实我们的9号网卡也就是veth0桥接到br0上。
查看namespace中的br0上的设备:

查看vxlan0设备的具体配置信息可知此overlay使用的VNI(VxLAN ID)为256:

VxLAN IP相同,又在同一个广播域里,地址又是同一个网段,即可以通信。
五、overlay是如何隔离的
不同的overlay网络是相互隔离的。
创建第二个overlay网络ov_net2并运行容器bbox3:

bbox3分配的IP是10.0.1.2,ping不通bbox1:

可见,不同overlay网络之间是隔离的,即便通过docker_gw_bridge也不能通信(通过iptables实现的:
):


实现bbox3与bbox1通信,可以将bbox3也连接到ov_net1:
docker network connect ov_net1 bbox3

六、参考
转载:https://blog.csdn.net/leiwuhen92/article/details/128476909
查看评论