Docker多机网络
前言
前面的文章主要聚焦于单机网络上,对于生产环境而言,单机环境不满足高可用的特点,所以是不具备上生产的条件,因此在开始Docker Swarm篇的时候我们先来聊聊多机网络之间Docker的通信如何做,厦门主要介绍三种跨主机通信的方式。
Docker系列文章:
为什么要学习Docker Docker基本概念 Docker镜像基本原理 Docker容器数据卷 Dockerfile Docker单机网络上 Docker单机网络下 Docker单机网络实战 Docker隔离技术 Docker限制 Docker Compose
Host
Host模式容器之间可以通过宿主机的IP+端口的形式进行访问,这种方式很直接,该网络模式就和我们在虚拟机的时候两台机器之间通信的方案是一样的。这种通常依靠路由器。
overlay
overlay被称为隧道网络,它是基于 VxLAN 协议来将二层数据包封装到 UDP 中进行传输的,目的是扩展二层网段,因为 VLAN 使用 12bit 标记 VLAN ID,最多支持 4094 个 VLAN,这对于大型云网络会成为瓶颈,而 VxLAN ID 使用 24bit 来标记,支持多达 16777216 个二层网段,所以 VxLAN 是扩展了 VLAN,也叫做大二层网络。
overlay 网络需要注册中心来记录网络中的信息,比如主机地址、子网等,需要向注册中心注册必要的信息,然后它就会自动去收集、同步网络的信息,同时,还需要维护一个 IP 地址池,给主机中的的容器分配IP。 这里我们采用Consul来做注册中心。
实战
搭建的环境如上图,实验前准备在阿里云购买了三台机器2C2G的机器IP分别为172.21.122.237、172.21.122.238、172.21.122.239,分别安装完成Docker,可以参考该文章
在172.21.122.237通过docker搭建Consul单节点的服务;
#-h:表示consul的主机名;--name consul 表示为该容器名;--restart=always 表示可以随着docker服务的启动而启动;
#运行consul容器,该服务的默认端口是8500,-p:表示将容器的8500端口映射到宿主机的8500端口
#-serve -bootstarp:表示当在群集中,加上这两个选项可以使其以master的身份出现
docker run -d -p 8500:8500 -h consul --name consul --restart=always progrium/consul -server -bootstrap
验证Consul服务是否正常,如果是阿里云的话需要通过外网访问,设置8500端口开放外网,访问外网IP+8500,出现下图情况如下:
修改172.21.122.238和172.21.122.239两台机器的docker服务配置文件;
#编辑docker.service文件
vim /usr/lib/systemd/system/docker.service
#找到ExecStart替换
#/var/run/docker.sock:Docker的一个编程接口
#-H tcp://0.0.0.0:2376:使用本机的tcp2376端口;
#--cluster-store=consul:指定运行着Consul服务的第一台docker服务器IP及端口;
#--cluster-advertise:告知Consul自己的连接地址;
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://172.21.122.237:8500 --cluster-advertise=172.21.122.238:2376
#重启docker
systemctl daemon-reload
systemctl restart docker
访问Consul服务器,如下图,当出现如下情况说明注册成功;
在172.21.122.238创建overlay网络,我们会发现在172.21.122.239上也会同步该网络,这是因为创建 238_overlay 时候 172.21.122.238 会将 overlay 网络信息存入了 Consul, 172.21.122.239会 从 Consul 读取到了新网络的数据。之后 238_overlay 的任何变化都会同步到 172.21.122.238和 172.21.122.239;
#在172.21.122.238创建overlay网络,网路地址10.0.2.1/24
docker network create -d overlay --subnet=10.0.2.1/24 238_overlay
#172.21.122.239验证是否同步该网络
docker network ls
在172.21.122.238创建app238容器并连接到238_overlay网络;
docker run -d -it --name app238 --network 238_overlay busybox
查看容器app238的网络情况,app238除了本地回环地址外,还有有两个网口 eth0 和 eth1,eth0 IP为10.0.2.2,连接的是238_overlay的网络, eth1 IP为172.18.0.2,连接的是docker默认网络;
#查看容器内部的网络情况
docker exec app238 ip a
查看172.21.122.238宿主机docker的网络情况,我们可以看到容器默认创建了一个docker_gwbridge的网络,该网络为所有连接到 overlay 网络的容器提供访问外网的能力,我们可以进入到容器内部访问下外网,我们会发现该网络是通畅的;查看docker_gwbridge网络的集体情况,我们发现该ip地址的范围为172.18.0.0/16, 说明容器app238默认的网络就是docker_gwbridge,我们也可以看到宿主机上也挂载了该网络;
#查看容器情况
docker network ls
#进入容器内部
docker exec -it app238 /bin/sh
#查看docker_gwbridge网络的具体情况
docker network inspect docker_gwbridge
#查看宿主机网络
ip addr
检查网络的互通性,我们在宿主机172.21.122.239创建app239容器并使用238_overlay网络,检查app238与app239容器之间网络的是否连通,经过试验我们会发现该网络是连通的,说了overlay网络容器可以互相通信,并且也可以通过容器名称进行访问,也就是实现DNS服务;
#在宿主机172.21.122.239创建app239容器使用238_overlay网络
docker run -d -it --name app239 --network 238_overlay busybox
#从容器app238 ping 容器app239 我们会发现该网络是通畅的
docker exec app238 ping app239
#从容器app239 ping 容器app238 我们会发现该网络是通畅的
docker exec app239 ping app238
原理再探,在172.21.122.238和172.21.122.239两台机器上查看 overlay网络的 namespace,我们可以发现两台机器上出现相同的命名空间信息,1-57a6c0273a就是238_overlay 的namespace,接下来可以查看namespace中的网桥上的设备,我们会发现在br0网桥上挂载了veth0和vxlan0两个设备,至此就完成我们对overlay网络的验证;
#先执行
ln -s /var/run/docker/netns /var/run/netns
#查看命名空间
ip netns
#安装bridge-utils
yum install -y bridge-utils
#查看namespace中的网桥上的设备
ip netns exec 1-57a6c0273a brctl show
总结
在相同overlay 网络中,不同主机之间的容器是相互连通的,不同 overlay 网络之间是隔离,这点我就不进行验证了,有兴趣大家可以自己验证一下。
macvlan
macvlan是一种网卡虚拟化技术,它能够将一个物理网卡虚拟出多个接口,每个接口都可以配置 MAC 地址,同样每个接口也可以配自己的 IP。macvlan 下的虚拟机或者容器网络和主机在同一个网段中,共享同一个广播域。macvlan 和 bridge 比较相似,但因为它省去了 bridge 的存在,所以配置和调试起来比较简单,而且效率也相对高。除此之外,macvlan 自身也完美支持 VLAN。
macvlan 的做法其实就是将这些虚拟出来的接口与 Docker 容器直连来达到通信的目的。一个 macvlan 网络对应一个接口,不同的 macvlan 网络分配不同的子网,因此,相同的 macvlan 之间可以互相通信,不同的 macvlan 网络之间在二层上不能通信,需要借助三层的路由器才能完成通信。用 Macvlan 技术虚拟出来的虚拟网卡,在逻辑上和物理网卡是对等的。物理网卡也就相当于一个交换机,记录着对应的虚拟网卡和 MAC 地址,当物理网卡收到数据包后,会根据目的 MAC 地址判断这个包属于哪一个虚拟网卡。
四种模式
private mode
过滤掉所有来自其他 macvlan 接口的报文,因此不同 macvlan 接口之间无法互相通信。
vepa(Virtual Ethernet Port Aggregator) mode
需要主接口连接的交换机支持 VEPA/802.1Qbg 特性。所有发送出去的报文都会经过交换机,交换机作为再发送到对应的目标地址(即使目标地址就是主机上的其他 macvlan 接口),也就是 hairpin mode 模式,这个模式用在交互机上需要做过滤、统计等功能的场景。
bridge mode
此种模式类似 Linux 的 Bridge,拥有相同父接口的两块 Macvlan 虚拟网卡是可以直接通讯的,不需要把流量通过父网卡发送到外部网络,广播帧将会被泛洪到连接在"网桥"上的所有其他子接口和物理接口。这个模式下,主机外是看不到主机上 macvlan interface 之间通信的报文的。这比较适用于让共享同一个父接口的 Macvlan 网卡进行直接通讯的场景。
passthru mode
此种模式会直接把父接口和相应的MacVLAN接口捆绑在一起,这种模式每个父接口只能和一个 Macvlan 虚拟网卡接口进行捆绑,并且 Macvlan 虚拟网卡接口继承父接口的 MAC 地址。
实战
网卡设置为混杂模式,ens33就该宿主机的网卡设备;
#设置为混杂模式
ip link set ens33 promisc on
#查看是否设置为混杂
ifconfig ens33
创建macvlan网络,在两台主机上eth0网卡创建一个10.200.1.0网段的macvlan网络,名字为macnet,指定对应的网关10.200.1.1;
#--subnet 指定macvlan网络所在的网络
#--gateway 指定网关
#-o parent 指定用来分配macvlan网络的网卡
docker network create -d macvlan --subnet=10.200.1.0/24 --gateway=10.200.1.1 -o parent=ens33 -o macvlan_mode=bridge macnet
在两台宿主机上分别创建容器test1和容器test2;
docker run -it -d --name test1 --ip=10.200.1.2 --network macnet busybox
docker run -it -d --name test2 --ip=10.200.1.3 --network macnet busybox
验证网络的联通性,必须两台机器混杂模式都开启才可以保证联通;
docker exec test2 ping 10.200.1.2
结束
欢迎大家点点关注,点点赞!