对macvlan 不熟悉的同学,可以先看下这篇macvlan virtual network简介

默认情况下Linux kernel会阻止(drop)宿主机(host eth0)虚拟出来的 macvlan network(bridge mode) 和宿主机host eth0)之间网络数据包。

调试了一段时间后,我们发现了可以通过路由表来绕过这个限制。 具体实施的方法如下:

在host network namesapces下新增 一个macvlan device,然后添加路由规则即可。

通信的两个方向简单解释如下:

eth0(host) -> pod(macvlan)

宿主机host eth0 通过break0 设备 和route table的路由规则 可以访问到pod(在macvlan中)

shell调试脚本如下:

1
2
3
4
5
6
ip link add break0 link eth0 type macvlan mode bridge
# NOTE: if use /24 CIDR will auto add a route rule 
# (100.75.30.0/24 dev break0 proto kernel scope link src 100.75.30.1) 
# which we don't need
ifconfig break0 100.75.30.7/32 up 
ip r a 100.75.30.71 dev break0 # 100.75.30.71 is a pod ip for test

因为kuryr是用python配置网络的,所以也提供对应的python脚本如下:

 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
from pyroute2 import IPDB

def _create_break0(self):
    with IPDB() as ipdb:
        i = ipdb.interfaces.get(IF_NAME)
        if i:
            i.up().commit()
            return i.index
        try:
            with ipdb.create(
                ifname=IF_NAME,
                kind=MACVLAN_KIND,
                link=ipdb.interfaces[self.parent],
                macvlan_mode=MACVLAN_MODE_BRIDGE,
            ) as i:
                i.add_ip(self.addr + "/32")
                i.up()
            return i.index
        except ipdb_exceptions.CreateException as e:
            LOG.info("Exception when create break0 device %s", e)
            return 0

def _route_spec(self, ip):
   return {"dst": ip + "/32", "oif": self.idx}

def add_route(self, ip):
    spec = self._route_spec(ip)
    with IPDB() as ipdb:
        try:
            ipdb.routes.add(spec).commit()
        except (ipdb_exceptions.CommitException, link_exceptions.NetlinkError) as e:
            LOG.info("Exception %s when add route table " + ip, e)

pod -> eth0(host)

因为是2层打通的,所以只要有mac_addr就可以访问,和pod以及宿主机eth0具体的IP 地址没关系。

在pod 里面使用 arp -n 可以看到,host IP(100.75.30.51) 和 break0 (100.75.30.7) 的IP 对应的是同一个mac addr, 都是 break0的mac addr。

在主机上添加 路由 ip r add 100.75.30.71 dev break0 (100.75.30.71 是pod 的IP地址),

然后在 pod 上ping 下 host IP, 宿主机eth0的hostIP 和 break0 的两个条目就会在pod的arp 表里显示出来。

如果只是从 host ping pod, 则 pod的arp 表只显示 break0 这个条目。