背景说明
MacVLAN是Linux kernel 支持的新特性,支持的版本有 v3.9-3.19 和 4.0+,比较稳定的版本推荐4.0+。它一般是以内核模块的形式存在。
MacVLAN这种技术能将一块物理网卡虚拟成多块虚拟网卡。 MacVLAN使得容器网络和主机网络在同一个广播域内,是一种跨主机互联的网络模式 不能识别容器的主机名称进行PING
解决方案
环境检查
系统检查
我们可以通过以下方法判断当前系统是否支持
[root@vm2 ~]# modprobe macvlan
[root@vm2 ~]# lsmod | grep macvlan
macvlan 19239 0
[root@vm2 ~]#
网卡检查
[root@vm2 docker]# ip addr show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:43:2c:2d brd ff:ff:ff:ff:ff:ff
inet 192.168.184.142/24 brd 192.168.184.255 scope global noprefixroute dynamic ens33
valid_lft 1140sec preferred_lft 1140sec
inet6 fe80::1d72:8c06:652b:cc91/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::2452:200d:395f:968a/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@vm2 docker]#
由于
[root@vm2 docker]# ip link set ens33 promisc on
[root@vm2 docker]# ip addr show ens33
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:43:2c:2d brd ff:ff:ff:ff:ff:ff
inet 192.168.184.142/24 brd 192.168.184.255 scope global noprefixroute dynamic ens33
valid_lft 1051sec preferred_lft 1051sec
inet6 fe80::1d72:8c06:652b:cc91/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::2452:200d:395f:968a/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@vm2 docker]#
主机网络
查看主机网络的网络范围和网关地址,这里网络范围:192.168.184.0/24 网关:192.168.184.2
[root@vm1 ~]# ip route
default via 192.168.184.2 dev ens33 proto dhcp metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.184.0/24 dev ens33 proto kernel scope link src 192.168.184.137 metric 100
[root@vm1 ~]# ip addr show ens33
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:ac:19:5a brd ff:ff:ff:ff:ff:ff
inet 192.168.184.137/24 brd 192.168.184.255 scope global noprefixroute dynamic ens33
valid_lft 1568sec preferred_lft 1568sec
inet6 fe80::1d72:8c06:652b:cc91/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@vm1 ~]#
工作原理
网络创建
创建MacVLAN网络,两台主机均需要执行,注意网络范围和网关需要和主机网络保持一致。
主机192.168.184.137 vm1
[root@vm1 ~]# docker network create --driver macvlan --subnet 192.168.184.0/24 --gateway 192.168.184.2 -o parent=ens33 macvlantest
013ccaa2997eb2f9cbdef05d10b609e4c85fdf13242f553a2d828576edbd68a8
[root@vm1 ~]#
[root@vm1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
892af10cd339 bridge bridge local
4a5006c650f6 host host local
94030ad50044 macvlantest macvlan local
a027c870d158 none null local
[root@vm1 ~]#
主机192.168.184.142 vm2
[root@vm2 ~]# docker network create --driver macvlan --subnet 192.168.184.0/24 --gateway 192.168.184.2 -o parent=ens33 macvlantestfba0554e018d9bc0812d422ed1c88d9fa280873d429d533239cddf15ac540d2d
[root@vm2 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
801380e310dd bridge bridge local
4a5006c650f6 host host local
fba0554e018d macvlantest macvlan local
a027c870d158 none null local
[root@vm2 ~]#
由于MacVLAN 网络会独占物理网卡,也就是说一张物理网卡只能创建一个 macvlan网络,重复创建出现如下错误
[root@vm1 ~]# docker network create --driver macvlan --subnet 192.168.184.0/24 --gateway 192.168.184.2 -o parent=ens33 -o macvlan_mode=bridge macvlan1
Error response from daemon: Pool overlaps with other one on this address space
如果想创建多个macvlan网络就需要多块网卡,也可以通过VLAN子接口的方案。
容器创建
网络创建完成后,创建容器
主机192.168.184.137 vm1
[root@vm1 ~]# docker run -it --name c11 --network=macvlantest centos /bin/bash
[root@6dd18751f4d7 /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
12: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/ether 02:42:c0:a8:b8:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.184.3/24 brd 192.168.184.255 scope global eth0
valid_lft forever preferred_lft forever
[root@6dd18751f4d7 /]#
[root@6dd18751f4d7 /]# ping 192.168.184.142
PING 192.168.184.142 (192.168.184.142) 56(84) bytes of data.
64 bytes from 192.168.184.142: icmp_seq=1 ttl=64 time=0.281 ms
64 bytes from 192.168.184.142: icmp_seq=2 ttl=64 time=0.328 ms
64 bytes from 192.168.184.142: icmp_seq=3 ttl=64 time=0.229 ms
[root@6dd18751f4d7 /]# ping 192.168.184.137
PING 192.168.184.137 (192.168.184.137) 56(84) bytes of data.
From 192.168.184.3 icmp_seq=1 Destination Host Unreachable
由于容器创建时的网络地址是macvlantest分配的,它并不知道哪些IP进行了使用,可能有些IP已经被使用了会出现冲突的情况,建议容器创建时指定—p进行指定。
主机192.168.184.142 vm2
docker run -it --name c22 --network=macvlantest centos /bin/bash
[root@218d4f9d0464 /]#
[root@218d4f9d0464 /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
11: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/ether 02:42:c0:a8:b8:01 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.184.4/24 brd 192.168.184.255 scope global eth0
valid_lft forever preferred_lft forever
[root@218d4f9d0464 /]#
[root@0d5042b162e8 /]# ping 192.168.184.137
PING 192.168.184.137 (192.168.184.137) 56(84) bytes of data.
64 bytes from 192.168.184.137: icmp_seq=1 ttl=64 time=0.612 ms
64 bytes from 192.168.184.137: icmp_seq=2 ttl=64 time=0.269 ms
[root@0d5042b162e8 /]# ping 192.168.184.142
PING 192.168.184.142 (192.168.184.142) 56(84) bytes of data.
From 192.168.184.4 icmp_seq=1 Destination Host Unreachable
由于容器创建时的网络地址是macvlantest分配的,它并不知道哪些IP进行了使用,可能有些IP已经被使用了会出现冲突的情况,建议容器创建时指定—p进行指定。
网络测试
在主机192.168.184.142 vm2上ping容器c11
[root@vm2 ~]# ping 192.168.184.3
PING 192.168.184.3 (192.168.184.3) 56(84) bytes of data.
64 bytes from 192.168.184.3: icmp_seq=1 ttl=64 time=0.505 ms
64 bytes from 192.168.184.3: icmp_seq=2 ttl=64 time=0.481 ms
在主机192.168.184.137 vm1上ping容器c22
[root@vm1 ~]# ping 192.168.184.4
PING 192.168.184.4 (192.168.184.4) 56(84) bytes of data.
64 bytes from 192.168.184.4: icmp_seq=1 ttl=64 time=0.461 ms
64 bytes from 192.168.184.4: icmp_seq=2 ttl=64 time=0.991 ms
网络问题
在上文中可以发现,宿主机和宿主机上面容器之间无法互相PING通,一般在macvlan模式下同网段的其他机器可以和容器互通,但宿主不能和容器互通,这是在macvlan模式设计的时候为了安全而禁止了宿主机和容器直接通信。
参考网址
https://rehtt.com/index.php/archives/236/
解决方案
如果想要实现互通,有个曲线救国的方法,就是macvlan与macvlan之间可以互通,只需要在宿主机再创建一个macvlan网络,然后修改路由,让数据经过这个macvlan达到互通的目的。
环境梳理
现有网段: 192.168.184.0/24 网关: 192.168.184.2
名字 | 网络地址 | 接口 |
---|---|---|
宿主机vm1 | 192.168.184.137 | ens33 |
容器c11 | 192.168.184.3 | macvlantest |
宿主机vm2 | 192.168.184.142 | ens33 |
容器c22 | 192.168.184.4 | macvlantest |
网络创建
这里以宿主机vm1进行举例,在宿主机上执行,建立一个名为macvlan-fixed的macvlan接口,并分配一个ip:
名字 | 网络地址 | 接口 |
---|---|---|
macvlan-fixed | 192.168.184.200 | ens33 |
这里的网络地址在网段192.168.184.0/24范围内均可
[root@vm1 ~]# ip link add macvlan-fixed link ens33 type macvlan mode bridge
[root@vm1 ~]# ip addr add 192.168.184.200 dev macvlan-fixed
[root@vm1 ~]# ip link set macvlan-fixed up
语法: ip link add macvlan2(一个网络名称) link ovs_eth0(你的物理网卡) type macvlan mode bridge
路由添加
修改路由,让宿主机到容器(192.168.184.3)的数据经过macvlan2:
[root@vm1 ~]# ip route add 192.168.184.3 dev macvlan-fixed
这里的192.168.184.3是容器网络地址 语法格式: ip route add 目的ip(需要建立通讯的macvlan容器 ip) dev macvlan(刚宿主机建立的macvlan)
访问验证
宿主机访问容器:192.168.184.3 => 192.168.184.200
[root@0a10f82ad3ea /]# ping 192.168.184.200
PING 192.168.184.200 (192.168.184.200) 56(84) bytes of data.
64 bytes from 192.168.184.200: icmp_seq=1 ttl=64 time=0.696 ms
64 bytes from 192.168.184.200: icmp_seq=2 ttl=64 time=1.01 ms
64 bytes from 192.168.184.200: icmp_seq=3 ttl=64 time=0.274 ms
^C
--- 192.168.184.200 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2015ms
rtt min/avg/max/mdev = 0.274/0.661/1.013/0.302 ms
[root@0a10f82ad3ea /]#
容器访问宿主机: 192.168.184.137 vm1
[root@0a10f82ad3ea /]# ping 192.168.184.137
PING 192.168.184.137 (192.168.184.137) 56(84) bytes of data.
64 bytes from 192.168.184.137: icmp_seq=1 ttl=64 time=0.131 ms
64 bytes from 192.168.184.137: icmp_seq=2 ttl=64 time=0.066 ms
64 bytes from 192.168.184.137: icmp_seq=3 ttl=64 time=0.043 ms
^C
--- 192.168.184.137 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2067ms
rtt min/avg/max/mdev = 0.043/0.080/0.131/0.037 ms
[root@0a10f82ad3ea /]#