Docker多主机网络(overlay)

此文档为翻阅cloudman的每天5分钟玩转docker技术的读书笔记

docker 版本:Docker version 17.10.0-ce, build
操作系统版本:centos7.3

Docker Libnetwork Container Network Model(CNM)阵营

Docker Swarm overlay
Macvlan & IP network drivers
Calico
Contiv(from Cisco)

Docker Libnetwork的优势就是原生,而且和Docker容器生命周期结合紧密;缺点也可以理解为是原生,被Docker“绑架”。
Container Network Interface(CNI)阵营

Kubernetes
Weave
Macvlan
Flannel
Calico
Contiv
Mesos CNI

其中overlay和macvlan是docker原生就支持的。weave、flannel、calico是需要安装额外的组件才可以的。

overlay

结构图

docker官方文档中,overlay网络是在swarm集群中配置的,但实际上,overlay网络可以独立于swarm集群实现,只需要满足以下前提条件即可。
1、有consul或者etcd,zookeeper的集群key-value存储服务;
2、组成集群的所有主机的主机名不允许重复,因为docker守护进程与consul通信时,以主机名相互区分;
3、所有主机都可以访问集群key-value的服务端口,按具体类型需要打开进行配置。例如docker daemon启动时增加参数–cluster-store=consul://:8500 – -cluster-advertise=eth0:2376
overlay网络依赖宿主机三层网络的组播实现,需要在所有宿主机的防火墙上打开下列端口;

协议 端口 说明启动后去访问8500端口
udp 4789 容器之间流量的vxlan端口
tcp/udp 7946 docker守护进程的控制端口

安装consul

安装consul,这里通过容器的方式安装

1
docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap

启动后去访问8500端口

修改container-1和container-2的docker-daemon的配置文件

vim /etc/systemd/system/docker.service.d/10-machine.conf

添加
–cluster-store=consul://192.168.111.159:8500
–cluster-advertise=eth0:2376
其中
–cluster-store:指定consul的地址
–cluster-advertise:告知consul自己连接的地址
打开consule可以看见已经连接进来了

创建overlay网络在container-1中创建ov_net1

docker network ls查看当前网络

默认是一个10.0.0.0/24的网段

在container-2中发现这个网络同步过来了

这是因为创建ovnet1时,container-1将overlay网络信息存在consul,container-2从consul读取了新网络的数据,后面ov_net的任何变化都会同步到container-1和container-2

在overlay中运行容器

container-1

1
docker run -itd --name overlay_1 --network ov_net1 busybox

container-2

1
docker run -itd --name overlay_2 --network ov_net1 busybox

container-1上地址为

container-2上地址为

contaner-1 ping container-2

container-2 ping container-1

发现container-1和container-2都有两块网卡

eth0连接的是overlay ,另外docker会创建个docker_gwbridge为使用overlay网络的容器提供上外网的能力

inspect这个网络

1
docker network inspect 07a9d7

发现地址分配记录
overlay隔离
不同overlay网络是相互隔离的
在创建个overlay网络

1
docker network create -d overlay ov_net2

新创建的网络地址是10.0.1.0/24

创建主机
contain-1上

1
docker run -itd --name over_lay3 --network ov_net2 busybox

contain-2上

1
docker run -itd --name over_lay4 --network ov_net2 busybox

ping ov_net1的机器,不通

因为他们vni不同,vlxan就是通过vni起到网络隔离效果。

通过docker_gwbridge也是一样的

overlay原理

1、docker会为每个overlay网络创建个单独的命名空间,在这个命名空间里创建了个br0的bridge。
2、在这个命名空间内创建两张网卡并挂载到br0上,创建一对veth pair端口 和vxlan设备。
3、veth pair一端接在namespace的br0上一端接在container上。
4、vxlan设备用于建立vxlan tunnel,vxlan端口的vni由docker-daemon在创建时分配,具有相同vni的设备才能通信。
5、docker主机集群通过key/value存储(我们这里用的是consul)共享数据,在7946端口上,相互之间通过gossip协议学习各个宿主机上运行了哪些容器。守护进程根据这些数据来在vxlan设备上生成静态MAC转发表。
6、vxlan设备根据静态mac转发表,通过host上的4789端口将数据发到目标节点。
7、根据流量包中的vxlan隧道ID,将流量转发到对端宿主机的overlay网络的网络命名空间中。
8、对端宿主机的overlay网络的网络命名空间中br0网桥,起到虚拟交换机的作用,将流量根据MAC地址转发到对应容器内部。

查看namespace 由于容器和overlay的网络的网络命名空间文件不再操作系统默认的/var/run/netns下,只能手动通过软连接的方式查看。

ln -s/var/run/docker/netns /var/run/netns
可以看见两个host上都有这个1-xx的namespace

查看vni

查看vxlan设备上生成的静态mac地址转发表

可以看见又192.168.111.162和192.168.111.163的mac地址

缺点

1、由于vxlan网络与宿主机网络默认不再同一网络环境下,为了解决宿主机与容器的通信问题,docker为overlay网络中的容器额外增加了网卡eth1作为宿主机与容器通信的通道。这样在使用容器服务时,就必须根据访问性质的不同,选择不同的网卡地址,造成使用上的不便。
2、容器对外暴露服务仍然只能使用端口绑定的方式,外界无法简单地直接使用容器IP访问容器服务。
3、从上面的通信过程中来看,原生的overlay网络通信必须依赖docker守护进程及key/value存储来实现网络通信,约束较多,容器在启动后的一段时间内可能无法跨主机通信,这对一些比较敏感的应用来说是不可靠的。

container的ip都是自动分配的,如果需要静态的固定ip,怎么办?
在创建网络的过程中有区别

1
2
3
4
5
docker network create -d overlay --subnet=192.168.2.0/24 multihost
docker run -d --name host1 --net=multihost --ip=192.168.2.2 centos7
docker run -d --name host2 --net=multihost --ip=192.168.2.3 centos7

IPAM
overlay网络中所有主机共享一个大的subnet,容器启动时会顺序分配ip,可以通过–subnet指定ip地址。