详解Docker 容器跨主机多网段通信解决方案

时间:2022-09-07 23:27:16

一、macvlan

实现docker的跨主机网络通信的方案有很多,如之前博文中写到的通过部署 consul服务实现docker容器跨主机通信

macvlan工作原理:

macvlan是linux内核支持的网络接口。要求的linux内部版本是v3.9–3.19和4.0+;
通过为物理网卡创建macvlan子接口,允许一块物理网卡拥有多个独立的mac地址和ip地址。虚拟出来的子接口将直接暴露在相邻物理网络中。从外部看来,就像是把网线隔开多股,分别接受了不同的主机上一样;
物理网卡收到包后,会根据收到包的目的mac地址判断这个包需要交给其中虚拟网卡。

当容器需要直连入物理网络时,可以使用macvlan。macvlan本身不创建网络,本质上首先使宿主机物理网卡工作在‘混杂模式',这样物理网卡的mac地址将会失效,所有二层网络中的流量物理网卡都能收到。接下来就是在这张物理网卡上创建虚拟网卡,并为虚拟网卡指定mac地址,实现一卡多用,在物理网络看来,每张虚拟网卡都是一个单独的接口。

使用macvlan注意:

  • 容器直接连接物理网络,由物理网络负责分配ip地址,可能的结果是物理网络ip地址被耗尽,另一个后果是网络性能问题,物理网络中接入的主机变多,广播包占比快速升高而引起的网络性能下降问题;
  • 宿主机上的某张网上需要工作在‘混乱模式'下;
  • 前面说到,工作在混乱模式下的物理网卡,其mac地址会失效,所以,此模式中运行的容器并不能与外网进行通信,但是不会影响宿主机与外网通信;
  • 从长远来看bridge网络与overlay网络是更好的选择,原因就是虚拟网络应该与物理网络隔离而不是共享。

工作示意图:

详解Docker 容器跨主机多网段通信解决方案

二、配置实例

实例1(实现容器基于macvlan的单网段跨主机通信)

实现效果:

两台centos 7.3,分别运行着docker服务;
两台docker服务器创建相同的一个macvlan网络,使docker服务器上的容器可以实现跨主机通信。

开始配置

1、第一台docker服务器配置如下

?
1
2
3
4
5
6
7
8
[root@docker01 ~]# ip link set ens33 promisc on       # 开启ens33网卡的混杂模式
[root@docker01 ~]# ip link show ens33   # 确定查看的信息包含以下标红的字样
2: ens33: <broadcast,multicast,'promisc',up,lower_up> mtu 1500 qdisc pfifo_fast state up mode default group default qlen 1000
  link/ether 00:0c:29:9f:33:9f brd ff:ff:ff:ff:ff:ff
[root@docker01 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1 -o pa
rent=ens33 mac_net1
#创建macvlan网络,指定网关、网段等信息,“-o”指定绑定在哪张网卡之上
[root@docker01 ~]# docker run -itd --name test1 --ip 172.22.16.10 --network mac_net1 busybox   # 基于新创建的macvlan网络运行一个容器,并指定其ip

确认运行的容器的ip地址

?
1
2
3
4
5
6
7
8
9
[root@docker01 ~]# docker exec test1 ip a   # 查看ip,确定以下标红与配置的一样
1: lo: <loopback,up,lower_up> mtu 65536 qdisc noqueue qlen 1000
  link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
6: eth0@if2: <broadcast,multicast,up,lower_up,m-down> mtu 1500 qdisc noqueue
  link/ether 02:42:ac:16:10:0a brd ff:ff:ff:ff:ff:ff
  inet '172.22.16.10/24' brd 172.22.16.255 scope global eth0
    valid_lft forever preferred_lft forever

2、第二台docker服务器配置如下(与第一台docker服务器基本相似)

?
1
2
3
4
5
6
7
8
9
10
[root@docker02 ~]# ip link set ens33 promisc on    # 开启混杂模式
[root@docker02 ~]# ip link show ens33
2: ens33: <broadcast,multicast,'promisc',up,lower_up> mtu 1500 qdisc pfifo_fast state up mode default group default qlen 1000
  link/ether 00:0c:29:b5:bc:ed brd ff:ff:ff:ff:ff:ff
[root@docker02 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway=172.22.16.1 -o parent=ens33 mac_net1
#创建一个与第一台docker服务器的网段、网关相同的macvlan。并绑定到物理网卡上。
#为了可以直观的看出其他docker服务器上的macvlan和第这台是在同一个网段的。所以,建议设置的网络名称一样。
[root@docker02 ~]# docker run -itd --name test2 --ip 172.22.16.11 --network mac_net1 busybox
#运行一个容器,并指定是基于macvlan网络的
#注意,其ip地址不要与其他docker服务器上的容器ip地址冲突

确认运行的容器的ip地址

?
1
2
3
4
5
6
7
8
9
[root@docker02 ~]# docker exec test2 ip a
1: lo: <loopback,up,lower_up> mtu 65536 qdisc noqueue qlen 1000
  link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
6: eth0@if2: <broadcast,multicast,up,lower_up,m-down> mtu 1500 qdisc noqueue
  link/ether 02:42:ac:16:10:0b brd ff:ff:ff:ff:ff:ff
  inet '172.22.16.11/24' brd 172.22.16.255 scope global eth0
    valid_lft forever preferred_lft forever

使用第二台docker服务器上的容器test2对第一台docker服务器上的容器test1进行ping测试

详解Docker 容器跨主机多网段通信解决方案

ok,跨主机的容器通信就通过macvlan实现了。由于使用混杂模式会造成物理网卡的mac地址失效,所以容器并不能通过此模式进行与外网的通信。

实例2(基于macvlan的跨主机网络多网段的解决方案)

实现的效果如下:

  • 两台centos 7.3,分别运行着docker服务;
  • 每台宿主机创建了两个macvlan网段供容器使用(172.10.16.0/24和172.20.16.0/24);
  • 第一台docker服务器上运行容器test1和test2,第二台docker服务器运行容器test3和test4。
  • 最终实现跨主机的同网段容器互相通信。

开始配置:

1、第一台docker服务器配置如下

?
1
2
3
4
5
6
7
[root@docker01 ~]# ip link set ens33 promisc on       # 开启ens33网卡的混杂模式
#也就是开启网卡的多个虚拟interface(接口)
[root@docker01 ~]# ip link show ens33   # 确定查看的信息包含以下标红的字样
2: ens33: <broadcast,multicast,'promisc',up,lower_up> mtu 1500 qdisc pfifo_fast state up mode default group default qlen 1000
  link/ether 00:0c:29:9f:33:9f brd ff:ff:ff:ff:ff:ff
[root@docker01 ~]# modinfo 8021q
 #查看是否加载8021q模块,如果有信息返回,则表示该模块已经加载

modinfo 8021q命令返回的信息如下

详解Docker 容器跨主机多网段通信解决方案

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[root@docker01 ~]# modprobe 8021q   #若没有加载8021q模块,则执行此命令
[root@docker01 ~]# cd /etc/sysconfig/network-scripts/
[root@docker01 network-scripts]# vim ifcfg-ens33
           ...................
bootproto=manual       # 将此配置项改为“manual”,也是手动的意思
[root@docker01 network-scripts]# cp -p ifcfg-ens33 ifcfg-ens33.10       # 复制一份网卡配置文件,-p保留原本文件的属性
[root@docker01 network-scripts]# vim ifcfg-ens33.10
bootproto=none
name=ens33.10        #注意更改名称
device=ens33.10   #注意更改名称
onboot=yes
ipaddr=192.168.10.11       # 给虚拟网卡设置一个ip
prefix=24
gateway=192.168.10.2
vlan=yes
[root@docker01 network-scripts]# cp ifcfg-ens33.10 ifcfg-ens33.20
[root@docker01 network-scripts]# vim ifcfg-ens33.20
bootproto=none
name=ens33.20
device=ens33.20
onboot=yes
ipaddr=192.168.20.10        # 注意,此处的ip与ens33.10并不在同一网段
prefix=24
gateway=192.168.20.2
vlan=yes
[root@docker01 network-scripts]# ifdown ens33;ifup ens33     #重启网卡,使更改生效
[root@docker01 network-scripts]# ifup ens33.10   # 启动该网卡
[root@docker01 network-scripts]# ifup ens33.20   # 启动
[root@docker01 ~]# docker network create -d macvlan --subnet 172.10.16.0/24 --gateway 172.10.16.1 -o parent=ens33.10 mac_net10
#创建一个macvlan网络,给其定义一个网段、网关及绑定到ens33.10
[root@docker01 ~]# docker network create -d macvlan --subnet 172.20.16.0/24 --gateway 172.20.16.1 -o parent=ens33.20 mac_net20
#创建一个macvlan网络,给其定义一个网段、网关及绑定到ens33.20
#接下来分别基于刚刚创建的macvlan网络运行一个容器

2、第二台docker服务器配置如下(基本与第一台操作类似,要注意ip不要冲突)

?
1
2
3
4
5
6
[root@docker02 ~]# ip link set ens33 promisc on    # 开启混杂模式
[root@docker02 ~]# ip link show ens33
2: ens33: <broadcast,multicast,'promisc',up,lower_up> mtu 1500 qdisc pfifo_fast state up mode default group default qlen 1000
  link/ether 00:0c:29:b5:bc:ed brd ff:ff:ff:ff:ff:ff
[root@docker02 ~]# modinfo 8021q
返回信息可参考图一
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[root@docker02 ~]# modprobe 8021q   #若没有加载8021q模块,则执行此命令
[root@docker02 ~]# cd /etc/sysconfig/network-scripts/
[root@docker02 network-scripts]# vim ifcfg-ens33
      ...............#省略部分内容
bootproto=manual   
[root@docker02 network-scripts]# scp root@192.168.171.151:/etc/sysconfig/network-scripts/ifcfg-ens33.* .         # 要注意后面的“.”
ifcfg-ens33.10                            100% 128  83.4kb/s  00:00 
ifcfg-ens33.20                            100% 124  75.0kb/s  00:00
[root@docker02 network-scripts]# vim ifcfg-ens33.10
bootproto=none
name=ens33.10
device=ens33.10
onboot=yes
ipaddr=192.168.10.11      # 更改ip,以防和第一台冲突
prefix=24
gateway=192.168.10.2
vlan=yes
[root@docker02 network-scripts]# vim ifcfg-ens33.20
 
bootproto=none
name=ens33.20
device=ens33.20
onboot=yes
ipaddr=192.168.20.11
prefix=24
gateway=192.168.20.2
vlan=yes
[root@docker02 network-scripts]# ifdown ens33;ifup ens33     # 重启网卡 ,使配置生效
[root@docker02 network-scripts]# ifup ens33.10   # 启动网卡
[root@docker02 network-scripts]# ifup ens33.20
#接下来创建macvlan网络,与第一台docker服务器创建的网络一样
[root@docker02 ~]# docker network create -d macvlan --subnet 172.10.16.0/24 --gateway 172.10.16.1 -o parent=ens33.10 mac_net10
[root@docker02 ~]# docker network create -d macvlan --subnet 172.20.16.0/24 --gateway 172.20.16.1 -o parent=ens33.20 mac_net20
[root@docker02 ~]# docker run -itd --name test3 --network mac_net10 --ip 172.10.16.11 busybox
[root@docker02 ~]# docker run -itd --name test4 --network mac_net20 --ip 172.20.16.21 busybox

配置至此,即可进行ping测试了,如果配置无误,则test3应该和test1互通(因为其都是基于mac_net10网络);test4应该和test2互通(同理)。

但test3和test1不能和test4和test2互通(因为其不是基于同一个虚拟局域网)。

容器test3 ping 容器test1测试(注意:若是使用vmware虚拟机进行测试,由于vmware的特性,需将其网络适配器改为“桥接模式”,而不是nat模式等。否则无法通信)

详解Docker 容器跨主机多网段通信解决方案

容器test4 ping 容器test2测试:

详解Docker 容器跨主机多网段通信解决方案

至此,跨主机网络多网段已经实现,同样,各个容器无法与外网进行通信。若有耐心,还是建议阅读 docker官方文档

到此这篇关于docker 容器跨主机多网段通信解决方案的文章就介绍到这了,更多相关docker 容器跨主机多网段通信内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.51cto.com/14227204/2516964