Docker跨主机网络——manual

1. Macvlan 简介

在 Macvlan 出现以前,咱们只能为一块以太网卡添加多个 IP 地址,却不能添加多个 MAC 地址,由于 MAC 地址正是经过其全球惟一性来标识一块以太网卡的,即使你使用了建立 ethx:y 这样的方式,你会发现全部这些“网卡”的 MAC 地址和 ethx 都是同样的,本质上,它们仍是一块网卡,这将限制你作不少二层的操做。有了 Macvlan 技术,你能够这么作了。linux

Macvlan 容许你在主机的一个网络接口上配置多个虚拟的网络接口,这些网络 interface 有本身独立的 MAC 地址,也能够配置上 IP 地址进行通讯。Macvlan 下的虚拟机或者容器网络和主机在同一个网段中,共享同一个广播域。Macvlan 和 Bridge 比较类似,但由于它省去了 Bridge 的存在,因此配置和调试起来比较简单,并且效率也相对高。除此以外,Macvlan 自身也完美支持 VLAN。docker

同一 VLAN 间数据传输是经过二层互访,即 MAC 地址实现的,不须要使用路由。不一样 VLAN 的用户单播默认不能直接通讯,若是想要通讯,还须要三层设备作路由,Macvlan 也是如此。用 Macvlan 技术虚拟出来的虚拟网卡,在逻辑上和物理网卡是对等的。物理网卡也就至关于一个交换机,记录着对应的虚拟网卡和 MAC 地址,当物理网卡收到数据包后,会根据目的 MAC 地址判断这个包属于哪个虚拟网卡。这也就意味着,只要是从 Macvlan 子接口发来的数据包(或者是发往 Macvlan 子接口的数据包),物理网卡只接收数据包,不处理数据包,因此这就引出了一个问题:本机 Macvlan 网卡上面的 IP 没法和物理网卡上面的 IP 通讯!关于这个问题的解决方案咱们下一节再讨论。
Docker跨主机网络——manual
简单来讲,Macvlan 虚拟网卡设备是寄生在物理网卡设备上的。发包时调用本身的发包函数,查找到寄生的物理设备,而后经过物理设备发包。收包时,经过注册寄生的物理设备的 rx_handler 回调函数,处理数据包。vim

2.简单介绍manual的流程

macvlan 就如它的名字同样,是一种网卡虚拟化技术,它可以将一个物理网卡虚拟出多个接口,每一个接口均可以配置 MAC 地址,一样每一个接口也能够配本身的 IP,每一个接口就像交换机的端口同样,能够为它划分 VLAN。网络

macvlan 的作法其实就是将这些虚拟出来的接口与 Docker 容器直连来达到通讯的目的。一个 macvlan 网络对应一个接口,不一样的 macvlan 网络分配不一样的子网,所以,相同的 macvlan 之间能够互相通讯,不一样的 macvlan 网络之间在二层上不能通讯,须要借助三层的路由器才能完成通讯,以下,显示的就是两个不一样的 macvlan 网络之间的通讯流程。
Docker跨主机网络——manual
咱们用一个 Linux 主机,经过配置其路由表和 iptables,将其配成一个路由器(固然是虚拟的),就能够完成不一样 macvlan 网络之间的数据交换,固然用物理路由器也是没毛病的。ide

3.Macvlan 的特色:

1.可以让使用者在同一张实体网卡上设定多个 MAC 地址。
2.承上,带有上述设定的 MAC 地址的网卡称为子接口(sub interface);而实体网卡则称为父接口(parent interface)。
3.parent interface 能够是一个物理接口(eth0),能够是一个 802.1q 的子接口(eth0.10),也能够是 bonding 接口。
4.可在 parent/sub interface 上设定的不仅是 MAC 地址,IP 地址一样也能够被设定。
5.sub interface 没法直接与 parent interface 通信 (带有 sub interface 的 VM 或容器没法与 host 直接通信)。
承上,若 VM 或容器须要与 host 通信,那就必须额外创建一个 sub 6.interface 给 host 用。
7.sub interface 一般以 mac0@eth0 的形式来命名以方便区別。
用张图来解释一下设定 Macvlan 后的样子:函数

Docker跨主机网络——manual

4.实验环境

docker01 docker02
192.168.1.11 192.168.1.13

关闭防火墙和禁用selinux,更改主机名性能

[root@localhost ~]# hostnamectl set-hostname docker01
[root@localhost ~]# su -
上一次登陆:二 12月 17 08:20:36 CST 2019从 192.168.1.1pts/0 上
[root@docker01 ~]# systemctl  stop firealld
Failed to stop firealld.service: Unit firealld.service not loaded.
[root@docker01 ~]# setenforce 0
setenforce: SELinux is disabled
[root@docker01 ~]# systemctl daemon-reload 
[root@docker01 ~]# systemctl restart docker

4.1 macvlan的单网络通讯

Docker跨主机网络——manual
1) 打开网卡的混杂模式
//须要在docker01和docker02_上都进行操做。测试

[root@docker01 ~]# ip link show ens33
//查看网卡模式

Docker跨主机网络——manual

[root@docker01 ~]# ip link set ens33 promisc on
//建立网卡模式为混杂模式
[root@docker01 ~]# ip link show ens33
//查看网卡模式

Docker跨主机网络——manual
2)在docker01.上建立macvlan网络3d

[root@docker01 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1  -o parent=ens33 mac_net1
// 建立一个macvlan模式的网络
-o parent=绑定在哪张网卡之上
[root@docker01 ~]# docker network ls
//查看网卡信息

Docker跨主机网络——manual

3)基于建立的macvlan网络运行一个容器调试

[root@docker01 ~]# docker run -itd --name bbox1 --ip 172.22.16.10 --network mac_net1 busybox

4)在docker02.上建立macvlan网络(要和docker01的macvlan如出一辙)

[root@docker02 ~]# docker network create -d macvlan  --subnet 172.22.16.0/24 --gateway 172.22.16.1  -o parent=ens33 mac_net1

[root@docker02 ~]# docker network ls

Docker跨主机网络——manual

5)在docker02. 上,基于建立的macvlan网络运行一个容器,验证与docker01.上容器的通讯。

[root@docker02 ~]# docker run -itd --name bbox2 --network mac_net1 --ip 172.22.16.20 busybox
//基于busybox建立一个容器
[root@docker02 ~]# docker exec -it bbox2 /bin/sh
//进入bbox2容器
/ # ping 172.22.16.10
//ping一下docker01的主机

Docker跨主机网络——manual

4.2macvlan的多网络通讯

Docker跨主机网络——manual

1) docker01和docker02验证内核模块8021q封装
macvlan须要解决的问题:基于真实的ens33网卡,生产新的虚拟网卡。

[root@docker01 ~]# modinfo 8021q
//验证内核模块8021q封装

Docker跨主机网络——manual

[root@docker01 ~]# modprobe 8021q
//若是内核模块没有开启,运行上边的命令导入一下

2)docker01基于ens33建立虚拟网卡
修改ens33网卡配置文件

[root@docker01 ~]# cd /etc/sysconfig/network-scripts/
[root@docker01 network-scripts]# vim ifcfg-ens33

Docker跨主机网络——manual
手动添加虚拟网卡配置文件

[root@docker01 ~]# cd /etc/sysconfig/network-scripts/
[root@docker01 network-scripts]# cp -p ifcfg-ens33  ifcfg-ens33.10
//-p保留源文件或目录的属性
[root@docker01 network-scripts]# vim ifcfg-ens33.10
//修改ens33.10网卡配置文件
BOOTPROTO=none
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
IPADDR=192.168.10.10
PREFIX=24
GATEWAY=192.168.10.2
VLAN=yes

这里注意,IP要和ens33网段作一个区分, 保证网关和网段IP的一致性,设备名称和配置文件的-致性,而且打开VLAN支持模式。

建立第二个虚拟网卡配置文件

[root@docker01 network-scripts]# cp -p ifcfg-ens33.10 ifcfg-ens33.20
[root@docker01 network-scripts]# vim ifcfg-ens33.20
//修改ens33.20网卡配置文件
BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.20
PREFIX=24
GATEWAY=192.168.20.2
VLAN=yes

docker01上的操做,启用建立的虚拟网卡:

[root@docker01 network-scripts]# ifup ifcfg-ens33.10 
[root@docker01 network-scripts]# ifup ifcfg-ens33.20
[root@docker01 network-scripts]# ifconfig
//查看IP

Docker跨主机网络——manual

3)docker02基于ens33建立虚拟网卡
修改ens33网卡配置文件

[root@docker02 ~]# cd /etc/sysconfig/network-scripts/
[root@docker02 network-scripts]# vim ifcfg-ens33

Docker跨主机网络——manual
手动添加虚拟网卡配置文件

[root@docker02 ~]# cd /etc/sysconfig/network-scripts/
[root@docker02 network-scripts]# cp -p ifcfg-ens33  ifcfg-ens33.10
//-p保留源文件或目录的属性
[root@docker02 network-scripts]# vim ifcfg-ens33.10
//修改ens33.10网卡配置文件
BOOTPROTO=none
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
IPADDR=192.168.10.11
PREFIX=24
GATEWAY=192.168.10.2
VLAN=yes

这里注意,IP要和ens33网段作一个区分, 保证网关和网段IP的一致性,设备名称和配置文件的-致性,而且打开VLAN支持模式。

建立第二个虚拟网卡配置文件

[root@docker02 network-scripts]# cp -p ifcfg-ens33.10 ifcfg-ens33.20
[root@docker02 network-scripts]# vim ifcfg-ens33.20
//修改ens33.20网卡配置文件
BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.21
PREFIX=24
GATEWAY=192.168.20.2
VLAN=yes

docker02上的操做,启用建立的虚拟网卡:

[root@docker02 network-scripts]# systemctl restart network
[root@docker02 network-scripts]# ifup ifcfg-ens33.10 
[root@docker02 network-scripts]# ifup ifcfg-ens33.20
[root@docker02 network-scripts]# ifconfig
//查看IP

Docker跨主机网络——manual
4)docekr01和docker02基于虚拟网卡,建立macvlan网络

[root@docker02 network-scripts]# docker network create -d macvlan --subnet 172.16.10.0/24 --gateway 172.16.10.1  -o parent=ens33.10 mac_net10
//建立一个新的网卡基于ens33.10
[root@docker02 network-scripts]# docker network create -d macvlan --subnet 172.16.20.0/24 --gateway 172.16.20.1  -o parent=ens33.20 mac_net20
//建立一个新的网卡基于ens33.20

5)Docker01部署一个私有仓库
Docker01

72  docker pull registry
//下载registry镜像
   73  docker run -itd --name registry -p 5000:5000  --restart=always registry:latest 
//基于registry镜像,启动一台容器
   76  docker tag busybox:latest  192.168.1.11:5000/busybox:v1 
//把容器重命名一个标签
   77  docker ps

Docker跨主机网络——manual

78  vim /usr/lib/systemd/system/docker.service #13行修改
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.1.11:5000  

   80  systemctl daemon-reload 
   81  systemctl restart docker.service 
//重启docker
  100  docker push 192.168.1.11:5000/busybox:v1
//上传容器到私有仓库 
  101  docker images

Docker02

78  vim /usr/lib/systemd/system/docker.service #13行修改
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.1.11:5000  

   80  systemctl daemon-reload 
   81  systemctl restart docker.service 
     //重启docker
   99  docker pull 192.168.1.11/busybox:v1 
     //下载刚刚上传的镜像

6)docker01和docker02基于busybox:v1镜像和网卡mac_net10,mac_net20,建立容器。
Docker01

[root@docker01 ~]# docker run -itd --name bbox10 --network mac_net10 --ip 172.16.10.10 192.168.1.11:5000/busybox:v1
[root@docker01 ~]# docker run -itd --name bbox20 --network mac_net20 --ip 172.16.20.20 192.168.1.11:5000/busybox:v1
**Docker02**
[root@docker02 ~]# docker run -itd --name bbox10 --network mac_net10 --ip 172.16.10.10 192.168.1.11:5000/busybox:v1
[root@docker02 ~]# docker run -itd --name bbox20 --network mac_net20 --ip 172.16.20.20 192.168.1.11:5000/busybox:v1

***这里只需注意,咱们在这里的操做跟在docker01和上面的操做是如出一辙的,操做顺序大体为:
验证8021q内核封装
基于ens33网卡建立新的虚拟网卡,ens33.10和ens33.20 (注意和docker01. 上的ens33.10和ens33.20必须是在同一-网段,且IP不能冲突)基于此网络运行容器。(注意和docker01 上的容器,都是基于刚刚建立的macvlan网络,但IP地址不能冲突)


7)验证
在docker01.上进入容器bbox10和docker02.上的bbox11进行通讯。
在docker01.上进入容器bbox20和docker02.上的bbox21进行通讯。
注意: VMware的网络必须设置为Bridge模式。

如今把docker01和docker02的网络模式设置为桥接模式

Docker跨主机网络——manual
测试一下相同网卡的主机是否能ping通

[root@docker01 ~]# docker exec -it bbox10  /bin/sh
/ # ping 172.16.20.20

Docker跨主机网络——manual

[root@docker02 ~]# docker exec -it bbox20  /bin/sh
/ # ping 172.16.20.20

Docker跨主机网络——manual

5.Macvlan 的局限性

Macvlan 是将 VM 或容器经过二层链接到物理网络的近乎理想的方案,但它也有一些局限性:

1.Linux 主机链接的交换机可能会限制同一个物理端口上的 MAC 地址数量。虽然你可让网络管理员更改这些策略,但有时这种方法是没法实行的(好比你要去给客户作一个快速的 PoC 演示)。
2.许多 NIC 也会对该物理网卡上的 MAC地址数量有限制。超过这个限制就会影响到系统的性能。
3.IEEE 802.11 不喜欢同一个客户端上有多个 MAC 地址,这意味着你的 Macvlan 子接口在无线网卡或 AP 中都没法通讯。能够经过复杂的办法来突破这种限制,但还有一种更简单的办法,那就是使用 Ipvlan,感兴趣能够本身查阅相关资料。

6.总结

macvlan是一种网卡虚拟化技术,可以将一张网卡虚拟出多张网卡。

macvlan的特定通讯模式,经常使用模式是bridge。

在Docker中,macvlan只支持bridge模式。

相同的macvlan能够通讯,不一样的macvlan二层没法通讯,能够经过三层路由完成通讯。

思考一下:

macvlan bridge和bridge的异同点还有一种相似的技术,多张虚拟网卡共享相同MAC地址,但有独立的IP地址,这是什么技术?

相关文章
相关标签/搜索