Docker跨主机网络-macvlan
一、搭建Docker的 macvlan 网络环境
docker 开发了另一个支持跨主机容器网络的 driver:macvlan
macvlan 本身是 Linxu kernel 模块,其功能是允许在同一个物理网卡上配置多个 MAC 地址,即多个 interface,每个 interface 可以配置自己的 IP
macvlan 本质上是一种网卡虚拟化技术,Docker 用 macvlan 实现容器网络
macvlan 的最大优点是性能极好,相比其他实现,macvlan 不需要创建 Linux bridge,而是直接通过以太 interface 连接到物理网络
macvlan并不创建网络,只创建虚拟网卡
macvlan会共享物理网卡所链接的外部网络,实现的效果跟桥接模式是一样的
1、macvlan 不创建网络,主要有什么特性?macvlan使用场景
macvlan主要是用来解决效率问题的,也就是说macvlan是效率高的跨主机网络虚拟化解决方案之一,适合在对网络性能要求极高的场景下
2、网络虚拟化的目的
就是在多租户场景下,在统一的底层网络之上,单独为每个租户虚拟出自己的网络从而达到隔离的目的
3、macvlan到底是干什么的
macvlan是网卡虚拟化方案
macvlan将一张物理网卡设置多个mac地址,就是一变多,一对多
注意: 需要物理网卡,打开混杂模式
A、设置网卡为混杂模式
ifconfig 网卡名 promisc
取消网卡的混杂模式:
ifconfig 网卡名 -promisc
既然有了多个mac地址,就可以设置多个IP地址,从而实现,一块物理网卡链接到交换机,变成多个虚拟网卡链接到交换机
B、混杂模式
混杂模式就是接收所有经过网卡的数据包,包括不是发给本机的包,即不验证MAC地址。普通模式下网卡只接收发给本机的包(包括广播包)传递给上层程序,其它的包一律丢弃。
一般来说,混杂模式不会影响网卡的正常工作,多在网络监听工具上使用
以太网(Ethernet)具有共享介质的特征,信息是以明文的形式在网络上传输,当网络适配器设置为监听模式(混杂模式,Promiscuous)时,由于采用以太网广播信道争用的方式,使得监听系统与正常通信的网络能够并联连接,并可以捕获任何一个在同一冲突域上传输的数据包。IEEE802.3 标准的以太网采用的是持续 CSMA 的方式,正是由于以太网采用这种广播信道争用的方式,使得各个站点可以获得其他站点发送的数据。运用这一原理使信息捕获系统能够拦截的我们所要的信息,这是捕获数据包的物理基础。
以太网是一种总线型的网络,从逻辑上来看是由一条总线和多个连接在总线上的站点所组成各个站点采用上面提到的 CSMA/CD 协议进行信道的争用和共享。每个站点(这里特指计算机通过的接口卡)网卡来实现这种功能。网卡主要的工作是完成对于总线当前状态的探测,确定是否进行数据的传送,判断每个物理数据帧目的地是否为本站地址,如果不匹配,则说明不是发送到本站的而将它丢弃。如果是的话,接收该数据帧,进行物理数据帧的 CRC 校验,然后将数据帧提交给LLC 子层
C、网卡具有的几种工作模式
1) 广播模式 (Broad Cast Model)
它的物理地址(MAC)地址是 0Xffffff 的帧为广播帧,工作在广播模式的网卡接收广播帧
- 多播传送 (MultiCast Model)
多播传送地址作为目的物理地址的帧可以被组内的其它主机同时接收,而组外主机却接收不到。但是,如果将网卡设置为多播传送模式,它可以接收所有的多播传送帧,而不论它是不是组内成员
- 直接模式 (Direct Model)
工作在直接模式下的网卡只接收目地址是自己 Mac地址的帧
- 混杂模式 (Promiscuous Model)
工作在混杂模式下的网卡接收所有的流过网卡的帧,信包捕获程序就是在这种模式下运行的
网卡的缺省工作模式包含广播模式和直接模式,即它只接收广播帧和发给自己的帧。如果采用混杂模式,一个站点的网卡将接受同一网络内所有站点所发送的数据包这样就可以到达对于网络信息监视捕获的目的
4、如何查看当前内核是否加载了该driver
macvlan是Linux kernel提供的一种network driver类型
A、查看是否加载
lsmod | grep macvlan
B、手动加载macvlan驱动到内核
modprobe macvlan
lsmod | grep macvlan
5、准备 macvlan 网络
使用 host02 和 host03 上单独的网卡 ens33 创建 macvlan
打开网卡的混杂模式
为保证多个 MAC 地址的网络包都可以从 ens33 通过,需要打开网卡的混杂模式
ip link set ens33 promisc on
ip link set ens33 promisc off
确保 ens33 状态 UP 并且 promisc 模式已经生效
ip link show ens33
- 创建 macvlan 网络
MacVLAN有两种桥接模式
Bridge模式:
不创建子接口的情况下直接去桥接物理接口。直接桥接到与宿主级的同网段
VLAN Bridge模式:
创建子接口去桥接物理接口。可划分多个VLAN
1、(Bridge模式)创建 macvlan 网络名为 macvlan_net01
A、在 host02 和 host03 中执行指令
docker network create -d macvlan \
--subnet=172.16.88.0/24 \
--gateway=172.16.88.1 \
-o parent=ens33 macvlan_net01
即:
docker network create -d macvlan --subnet=172.16.88.0/24 --gateway=172.16.88.1 -o parent=ens33 macvlan_net01
注意:在 host02和host03 中都要执行相同的命令
如果需要访问外网,需要将网络设置为与宿主级相同网络下
本地不可访问,因为桥接的本地网络
单个网卡只能绑定一次如重复添加会报如下错误
ens33网卡已被绑定,不可多次绑定
Error response from daemon: network dm-0a48ab454840 is already using parent interface ens33
删除绑定网卡网络集
docker network rm netID
B、指令解析
1) -d macvlan 指定 driver 为 macvlan
2) macvlan 网络是 local 网络,为了保证跨主机能够通信,用户需要自己管理 IP subnet
3) 与其他网络不同,docker 不会为 macvlan 创建网关,这里的网关应该是真实存在的,否则容器无法路由
4) -o parent 指定使用的网络 interface
C、查看网络详情
docker network inspect macvlan_net01
[
{
"Name": "macvlan_net01",
"Id": "d74283de1d7a35481cfd448afe48d484f5e54034a69ccaf1c54608c15a8da2ac",
"Created": "2020-06-23T11:53:22.176189148+08:00",
"Scope": "local",
"Driver": "macvlan",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.16.88.0/24",
"Gateway": "172.16.88.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"parent": "ens33"
},
"Labels": {}
}
]
2、在 host03 中运行容器 mac_busybox01 并连接到 macvlan_net01
docker run -itd --name mac_busybox01 --ip=172.16.88.10 --network macvlan_net01 busybox
docker exec mac_busybox01 ip r
由于 host02 中的 macvlan_net01 与 host03 中的 macvlan_net01 本质上是独立的,为了避免自动分配造成 IP 冲突,最好通过 --ip 指定 ip 地址
3、在 host02 中运行容器 mac_busybox02,指定 IP 地址
docker run -itd --name mac_busybox02 --ip=172.16.88.11 --network macvlan_net01 busybox
docker exec mac_busybox02 ip r
4、验证host03上的mac_busybox01和host02上的mac_busybox02连通性
docker exec mac_busybox01 ping -c 3 172.16.88.11
docker没有为macvlan提供DNS服务,而overlay网络是有的
mac_busybox01能够ping到mac_busybox02的ip地址 172.16.88.11,但无法解析mac_busybox02的主机名
docker exec mac_busybox01 ping -c 3 mac_busybox02
三、macvlan 网络结构分析
1、查看是否创建新的 bridge(结果为无)
brctl show
macvlan 不依赖 Linux bridge
2、查看容器 mac_busybox01 网络设备
docker exec mac_busybox01 ip link
3、容器的网卡与宿主机网卡关系
除了 lo,容器有网卡 eth0,请注意 eth0 后面的 @if2,这表明该容器的网卡 interface 有一个对应的 interface,其全局的编号为 2
根据 macvlan 的原理,这个 interface 就是主机的 ens33
ip link show ens33
容器的网卡 eth0 就是 ens33 通过 macvlan 虚拟出来的 interface
容器的网卡 interface 直接与主机的网卡连接,这种方案使得容器无需通过 NAT 和端口映射就能与外网直接通信(只要有网关),在网络上与其他独立主机没有区别
4、(VLAN Bridge模式)用 sub-interface 实现多 macvlan 网络
A、在host02上执行,创建macvlan_net02
docker network create -d macvlan \
--subnet=172.16.77.0/24 \
--gateway=172.16.77.1 \
-o parent=ens33 macvlan_net02
【问题描述】
Error response from daemon: network dm-78e7b73a77c2 is already using parent interface ens33
【原理解析】
由于 macvlan 网络会独占物理网卡,也就是说一张物理网卡只能创建一个 macvlan 网络,否则会报错
【解决思路】
想创建多个 macvlan 网络就得用多张网卡,但主机的物理网卡是有限的
macvlan 网络是支持 VLAN 子接口的,所以可通过 VLAN 技术将一个网口划分出多个子网口,这样就可基于子网口来创建 macvlan 网络
macvlan 不仅可以连接到 interface(如 ens33),也可连接到 sub-interface(如 ens33.xxx)
VLAN 是现代网络常用的网络虚拟化技术,它可以将物理的二层网络划分成多达 4094 个逻辑网络,这些逻辑网络在二层上是隔离的,每个逻辑网络(即 VLAN)由 VLAN ID 区分,VLAN ID 的取值为 1-4094
Linux 的网卡也能支持 VLAN(yum install vlan),同一个 interface 可收发多个 VLAN 的数据包,前提是要创建 VLAN 的 sub-interface
比如:希望 ens33 同时支持 VLAN10 和 VLAN20,则需创建 sub-interface ens33.10 和 ens33.20
在交换机上,如果某个 port 只能收发单个 VLAN 的数据,该 port 为 Access 模式
如果支持多 VLAN,则为 Trunk 模式
实际生产中 宿主机的 ens33 要接在交换机的 trunk 口上
B、如何在 ens33.10 和 ens33.20 上创建 macvlan 网络
a、配置 sub-interface
在 host02 和 host03 操作:创建2个VLAN,VLAN ID 10 和 VLAN ID 20
ip a
ip link add link ens33 name ens33.10 type vlan id 10
ip link add link ens33 name ens33.20 type vlan id 20
systemctl status docker
systemctl restart docker
systemctl status docker
b、启用 sub-interface
ip link show ens33.10
ip link show ens33.20
ifup ens33.10
ifup ens33.20
c、host02 和 host03 创建 macvlan 网络
docker network ls
docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens33.10 mac_net10
docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=ens33.20 mac_net20
docker network ls
d、在 host02 中运行容器
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
docker ps
docker exec bbox1 ip r
docker exec bbox2 ip r
e、在 host03 中运行容器
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
docker ps
docker exec bbox3 ip r
docker exec bbox4 ip r
f、验证 macvlan 之间的连通性
docker exec bbox1 ip r
docker exec bbox2 ip r
docker exec bbox1 ping -c 3 172.16.10.11
docker exec bbox2 ping -c 3 172.16.20.11
【问题记录】macvlan 网络下,同一子网下的同一宿主机上的容器可以相互ping,但是不同宿主机上的同一子网的容器ping不通,而且容器也ping不通网关
详情请见,微信公众号