玖叶教程网

前端编程开发入门

Docker三种自定义网络(bridge、macvlan、overlay )

一、概述

Docker 提供三种 网络驱动:bridge, macvlan 和 overlay
overlay 和 macvlan 用于创建跨主机的网络

二、自定义桥接(bridge)网络

这个网桥类似于默认网络中的 bridge

创建自定义网络命令:docker network create

$ docker network create --driver bridge --subnet 172.19.0.0/16 --gateway 172.19.0.1 mybridge_net

参数解释:
--driver bridge 表示使用桥接模式
--subnet 172.19.0.0/16 表示子网ip 可以分配 172.19.0.2 到 172.19.255.255
--gateway 172.19.0.1 表示网关
mybridge_net 表示网络名

查看

$ docker network ls
$ docker network inspect mybridge_net

使用新创建的网络创建容器

$ docker run --name=busybox_mybridge_net --net=mybridge_net -td busybox

查看

$ docker network ls
$ network inspect mybridge_net
$ ip a
$ docker run --name=busybox_mybridge_net --net=mybridge_net -td busybox
$ ip a

查看容器IP

$ docker exec -it busybox_mybridge_net ifconfig

三、自定义macvlan网络(物理网卡相当于交换机)

macvlan 是在 宿主机 网卡上创建多个子网卡,并分配独立的 IP 地址和 MAC 地址,把子网卡分配给容器实例来实现实例与物理网络的直通,并同时保持容器实例的隔离性。Host 收到数据包后,则根据不同的 MAC 地址把数据包从转发给不同的子接口,在外界来看就相当于多台主机。

macvlan接口会监听并接收链路上到达本mac地址的报文,因此macvlan(除bridge外)仅能向外部网络发送报文,并接受目的为本机mac的报文。

macvlan 网络会独占物理网卡,也就是说一张物理网卡只能创建一个 macvlan 网络

根据 macvlan 子接口之间的通信模式,macvlan 有四种网络模式:

  • vepa(virtual ethernet port aggregator) 模式
  • passthru 模式
  • private 模式
  • bridge 模式(默认模式,最常用的方式)

3.1、四种模式简介
3.1.1、vepa模式

在这种模式下,macvlan设备不能直接接收在同一个物理网卡的其他macvlan设备的数据包,但是其他macvlan设备可以将数据包通过物理网卡发送出去,然后通过hairpin设备返回的给其他macvlan设备,用于管理内部vm直接的流量,并且需要特殊设备支持。

创建vepa模式的网络(macvlan_mode=vepa)

$ docker network create -d macvlan --subnet=192.168.182.0/24 --gateway=192.168.182.2 -o parent=ens37 -o macvlan_mode=vepa vepamv

使用上述网络运行2个容器

$ docker run -itd --net=vepamv --ip=192.168.182.222 --name=macvlan-vepa-1 busybox /bin/sh
$ docker run -itd --net=vepamv --ip=192.168.182.223 --name=macvlan-vepa-2 busybox /bin/sh

查看网络信息,可以看到驱动类型为macvlan,macvlan模型为vepa,两个网卡有独立的mac地址,底层物理网卡为ens37

$ docker network inspect vepamv

在macvlan-vepa-1中ping macvlan-vepa-2发现无法ping通,因为本地环境上并没有开启hairpin模式的交换机或路由器,报文发送到链路上之后无法返回来。即无法在internal内部进行报文传输

$ docker exec -it macvlan-vepa-1 ping 192.168.182.223

但在external network的机器(宿主机:192.168.182.130)是可以直接访问该容器的(首先该容器的IP属于external network)

3.1.2、passthru模式

这种模式,只允许单个子接口连接主接口,且必须设置成混杂模式,一般用于子接口桥接和创建 VLAN 子接口的场景。

3.1.3、private模式

隔离功能比VPEA更强,阻断了广播和组播,即使交换机开启hairpin也无法通信。

3.1.4、bridge模式

在这种模式下,寄生在同一个物理设备的macvlan设备可以直接通讯,不需要外接的hairpin设备帮助,使用如下的命令创建一个bridge的macvlan网络。


3.2、相同 macvlan 网络之间的通信原理

1)准备两台机器

host1:192.168.182.130  ens33
host2:192.168.182.152  bond0

2)创建两台宿主机上macvlan

# 在host1创建macvlan网络
$ docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens33 mac1
# 在192.168.182.152上创建macvlan网络
$ docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.11.1 -o parent=bond0 mac1
# 查看
$ docker network ls

参数解释
-d/--driver 指定 Docker 网络 driver
--subnet 指定 macvlan 网络所在的网络
--gateway 指定网关
-o parent 指定用来分配 macvlan 网络的物理网卡

3)使用上面创建的macvlan网络创建容器

# 在host1上创建以macvlan网络的容器
$ docker run -itd --name c1 --ip=172.16.10.2 --network mac1 busybox
# 在host2上创建macvlan网络
$ docker run -itd --name c2 --ip=172.16.10.3 --network mac1 busybox

--ip 指定容器 c1 使用的 IP,这样做的目的是防止自动分配,造成 IP 冲突
--network 指定 macvlan 网络

4)验证,在 host1 c1 中 ping host2 c2

$ docker exec c1 ping -c 2 172.16.10.3

3.2、不同 macvlan 网络之间的通信
准备三台机器(Centos8),桥接模式

host1:
	ens33(NAT)  192.168.182.153  
	ens34(桥接)  192.168.0.110
host2:
	ens33(NAT)  192.168.182.154  
	ens34(桥接)  192.168.0.111
host3:
	ens33(NAT)  192.168.182.155  
	ens34(桥接)  192.168.0.112

第一步:先实现相同macvlan网络之间的通信

接下来,我们来看看相同 macvlan 网络之间的连通性,搭建以下的拓扑环境:

由于 macvlan 网络会独占物理网卡,也就是说一张物理网卡只能创建一个 macvlan 网络,如果我们想创建多个 macvlan 网络就得用多张网卡。

好在 macvlan 网络也是支持 VLAN 子接口的,所以,我们可以通过 VLAN技术将一个网口划分出多个子网口,这样就可以基于子网口来创建 macvlan 网络了,下面是具体的创建过程。

1)开启混杂模式

$ ip link set ens34 promisc on

2)首先分别在两台主机上将物理网口 ens33创建出两个 VLAN 子接口。

$ ip link add link ens34 name ens34.10 type vlan id 100
$ ip link add link ens34 name ens34.20 type vlan id 101
# 启动子网卡
$ ip link set ens34.10 up
$ ip link set ens34.20 up

3)分别在 host1 和 host2 上基于两个 VLAN 子接口创建 2 个 macvlan 网络,macvlan10 和 macvlan20。

$ docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens34.10 mac_net10
$ docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=ens34.20 mac_net20

4)分别在 host1 和 host2 上运行容器,并指定不同的 macvlan 网络。

# host1
$ docker run -itd --name bbox1 --ip=172.16.10.10 --network mac_net10 busybox
$ docker run -itd --name bbox2 --ip=172.16.20.10 --network mac_net20 busybox
# host2
$ docker run -itd --name bbox3 --ip=172.16.10.11 --network mac_net10 busybox
$ docker run -itd --name bbox4 --ip=172.16.20.11 --network mac_net20 busybox

通过验证,bbox1 和 bbox3,bbox2 和 bbox4 在同一 macvlan 网络下,互相可以 ping 通,bbox1 和 bbox2,bbox1 和 bbox4 在不同的 macvlan 网络下,互相 ping 不通。

$ docker exec -it bbox1 ping 172.16.10.11
$ docker exec -it bbox2 ping 172.16.20.11
$ docker exec -it bbox1 ping 172.16.20.10
$ docker exec -it bbox1 ping 172.16.20.11

注意:如果你是vmware环境的话,由于VMware虚拟机的原因,必须将两台主机默认的NAT模式修改为桥接模式才能够正常通信

第二步:不同macvlan网络之间的通信实现

通过上面验证同一个二层macvlan网络是可以互通,但是不通macvlan网络是不通的,如果需要通,则需要通过三层的路由,我们这就来验证下。

就加一台 host3,以下操作都是在host3上操作的,通过打开 ip_forward 把它改造成一台路由器,用来打通不同 macvlan 网络,大概的图示如下所示:

跨主机通信已经不从虚线走了,都从host3走,因为host3充当着两个maclvan的网关,当然也是路由器的角色。
1)首先对 host3 执行 sysctl -w net.ipv4.ip_forward=1 打开路由开关。

$ sysctl -w net.ipv4.ip_forward=1
#查看
$ sysctl  net.ipv4.ip_forward
$ cat /proc/sys/net/ipv4/ip_forward

2)然后host3创建两个 VLAN 子接口,一个作为 macvlan 网络 mac10 的网关,一个作为 mac20 的网关。

# host1,host2创建子接口,注意name和id必须要跟上面的两台机器一样,要不然会网络不通
$ ip link add link ens34 name ens34.100 type vlan id 100
$ ip link add link ens34 name ens34.200 type vlan id 101

# 对 vlan 子接口配置IP充当网关 IP 并启用
$ ip addr add 172.16.10.1/24 dev ens34.100
$ ip link set ens34.100 up

$ ip addr add 172.16.20.1/24 dev ens34.200
$ ip link set ens34.200 up

3)这样之后再从 bbox1 和 bbox2,bbox1 和 bbox4,就可以 ping 通了。

$ docker exec -it bbox1 ping 172.16.20.10
$ docker exec -it bbox1 ping 172.16.20.11

可能有些系统做了安全限制,可能 ping 不通,这时候可以添加以下 iptables 规则,目的是让系统能够转发不通 VLAN 的数据包。我这里是没加也是可以通的。

$ iptables -t nat -A POSTROUTING -o ens34.10 -j MASQUERADE

$ iptables -t nat -A POSTROUTING -o ens34.20 -j MASQUERADE

$ iptables -A FORWARD -i ens34.10 -o ens34.20 -m state --state RELATED,ESTABLISHED -j ACCEPT

$ iptables -A FORWARD -i ens34.20 -o ens34.10 -m state --state RELATED,ESTABLISHED -j ACCEPT

$ iptables -A FORWARD -i ens34.10 -o ens34.20 -j ACCEPT

$ iptables -A FORWARD -i ens34.20 -o ens34.10 -j ACCEPT

缺点:不能自动校验ip冲突,得人为区分,只能容器之间访问,而且无法访问到外网,overlay可以补足

四、自定义overlay网络(swarm网络)

4.1、介绍

Overlay网络模式,在多个docker daemon 主机之间穿件一个分布式的网络,该网络(overlay)位于docker主机层次之上,允许容器(同一集群服务的容器)之间加密通讯,因此,docker需要处理每一个主机(docker daemon)和每个分布的容器之间的包路由。

每当初始化一个集群(swarm)或者添加一个docker主机到集群时,则在该主机上会自动创建两个网络(ingress和docker_gwbridge),但是swarm集群需要三个网络,还有一个自定义overlay网络。

# 查看docker网络
$ docker network ls
# 在192.168.0.113机器上初始化一个swarm集群
$ docker swarm init --advertise-addr 192.168.0.113
# 再查看docker网络
$ docker network ls

  • ingress网络是一个特殊的 overlay 网络,该网络处理集群服务间的控制和数据信息。当创建一个集群服务、但未指定用户自定义网络时,该服务上的节点默认连接到ingree网络。
  • docker_gwbridge桥接网络,该网络,连接单个主机的守护进程(docker daemon)与其他主机的守护进程,参与集群服务。
  • 自定义Overlay networks 管理 Swarm 中 Docker 守护进程间的通信。你可以将服务附加到一个或多个已存在的 overlay 网络上,使得服务与服务之间能够通信。以下就是创建一个overlay网络:
$ docker network create -d overlay my-overlay

4.2、overlay netwrok 操作
1)环境

host1 192.168.0.113 ens33 centos8
host1 192.168.0.114 ens33 centos8

2)准备工作

  • 2377/tcp:管理端口
  • 7496/tcp/udp:节点间通信端口,发现网络的
  • 4789/udp: 覆盖网的流量交互(例如密钥交互等)

放通这三个端口(所有节点都执行)

# 放通2377/tcp,7946/udp,4789/udp端口
$ firewall-cmd --zone=public --add-port=2377/tcp --permanent
$ firewall-cmd --zone=public --add-port=7946/tcp --permanent
$ firewall-cmd --zone=public --add-port=7946/udp --permanent
$ firewall-cmd --zone=public --add-port=4789/udp --permanent
# 重新加载生效
$ firewall-cmd --reload
# 查看
$ firewall-cmd --list-ports

清理上面创建的swarm集群和创建出来的网络

# 删除集群节点,因为上面初始化了,相对于删除了集群了,删除集群后会自动把swarm网络删掉,所以这里只需要手动删除docker_gwbridge。
$ docker swarm leave -f
$ docker network rm docker_gwbridge


以下操作在host1上执行
3)初始化一个swarm集群

$ docker swarm init --advertise-addr 192.168.0.113
# 查看集群
$ docker node ls
# 查看网络
$ docker network ls

3)创建 overlay network

$ docker network create --attachable -d overlay  my-overlay
# 或者指定子网,不指定会随机生成一个子网
$ docker network create -d overlay --subnet=10.0.1.0/24 --gateway=10.0.1.1 --attachable my-overlay
# 查看
$ docker network inspect my-overlay

--attachable允许集群服务间的容器交互连接或者独立的容器之间能够连接。swarm在设计之初是为了service(一组container)而服务的,因此通过swarm创建的overlay网络在一开始并不支持单独的container加入其中。但是在docker1.13, 我们可以通过“--attach” 参数声明当前创建的overlay网络可以被container直接加入。

4)把host2加入集群

# 在host1上执行,查看加入命令
$ docker swarm join-token worker
# 在host2上执行,把host2加入到swarm集群
$ docker swarm join --token SWMTKN-1-54jufnlpeihtnedmpsexqvayz2jbm8f78ijlt4pik7huie9bmr-djfn6m3lz143e0fyjbcocnqhl 192.168.0.113:2377

5)查看swarm集群

$ docker node ls

6)在host1 manager节点上创建一个容器busybox1,指定上面创建的overlay网络

$ docker run -itd --name=busybox1 --network=my-overlay busybox /bin/sh

再次查看网络,可以发现有了容器的IP及LB IP

$ docker network inspect my-overlay

7)在host2 worker节点上创建一个容器busybox2:

$ docker run -itd --name=busybox2 --network=my-overlay busybox /bin/sh
# 查看网络
$ docker network inspect my-overlay

8)在上面刚创建的2个容器内互相PING对方做测试

再ping外网

从上图看,既可以ping内网,也可以ping外网,得益于每个容器有两块网卡,一块内网通信,一块直接桥接到docker_gwbridge出外网。

根据上面讲解和实验,容器间的网络架构图如下:

其实从上图看,可能有朋友会发现,为啥有vxlan的标注,因为vxlan才是实体,overlay只是网络模型;一句话就是vxlan是overlay网络的一种实现,如果不清楚vxlan的,可以看这里。
其实可以查看my-overlay网络的具体信息,里面会有vxlan的一些参数

$  docker network inspect my-overlay

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言