前言
ovn场景下vlan模式的流量问题,相关资料甚少,当前社区针对vlan网络的问题没有很明确的解决方案。本系列文章旨在阐述ovn vlan网络的关键点和问题,以供参考。
相关技术
首先介绍一下vlan网络模式下,几个相关技术点,了解了这些才能更容易理解问题的产生。
dvr
dvr即分布式路由(distributed virtual routing)的缩写,区别于传统集中式的路由模式,它是在每个计算节点上都会驻留一个虚拟router,并实现路由功能。也就是说访问不同网段的虚机流量,在源节点就完成了路由,直接转发给目的虚机。
localnet port
之前文章也提到了localnet port。这种port是连接br-xx和br-int的patch端口,ovn-controller会在br-int与br-xx建立patch,该patch就用于与物理网络通信。
external port
externl port可以用于代理外部网络资源(无法接入br-int)的dhcp或者三层流量,比如裸金属网卡,sriov虚机网卡的流量。该类型的port只会驻留在网关节点上,也就是标记了external-ids
为ovn-cms-options=enable-chassis-as-gw
的节点。简单描述就是,裸金属的dhcp报文或者三层,只会被external port所在的网关节点处理。
arp proxy
二层arp-proxy:ovn针对非unkonw的port(配置了address),会进行arp代理。简单理解就是,针对同一网段下的虚机/裸金属发送arp请求后,是由ovn-controller来代答的。
table=16(ls_in_arp_rsp), priority=50, |
三层arp-proxy:对于跨网段的访问,dvr模式下也实现了,将报文的目的mac地址修改为目的ip对应的mac。
table=14(lr_in_arp_resolve), priority=100 , |
mac_binding
路由阶段,对于三层的ip<–>mac解析,比如说跨网段访问未知ip地址,ovn-controller会通过发送arp请求学习ip对应的mac地址,然后写入sb的mac_binding
表中。
()[root@ovn-tool-0 /]# ovn-sbctl list mac_binding |
注意这个表项是没有老化机制的,所以在ip/mac关系有变化的同时进行新的arp学习,或者删除对应表项,要不然就会导致查询到老的ip/mac关系。
大致流程如下:
1.发送给目地ip未知的报文,则通过get_arp查询mac_binding表获取到对应的mac,然后将目的mac地址修改:
table=14(lr_in_arp_resolve ), priority=0, match=(ip4), |
如果没有查到,则将目的mac置为全0
2.如果目的mac为全0,即上送ovn-controller,将arp请求从lrp发送出去:
table=18(lr_in_arp_request ), priority=100, |
3.从lrp收到arp回复报文,ovn-controller会先通过lookup_arp查看在mac_binding表项有没有记录:
table=1 (lr_in_lookup_neighbor), priority=100, |
4.如果没有记录,则通过put_arp将学习到的ip-mac映射关系写入mac_binding表中:
table=2 (lr_in_learn_neighbor), priority=90, match=(arp), |
二层流量问题分析
这种情况早前我们遇到比较频繁:发现同vlan网段的虚机icmp报文,在所有的计算节点都能抓到该报文,即单播报文被广播。
对于vlan模式的二层广播问题,结合前面基本概念里就提到的,ovn-controller会对已知port进行arp代答。这样导致的后果就是:
- 虚机/裸机的mac地址,在被访问的期间未被物理交换机fdb所学习到。
- 源虚机/裸机通过ovn-controller拿到目的mac后,直接封装目的地址,将报文发送出去了。
基于以上两种情况,就可能会出现,交换机在处理报文时会认为mac地址是未知的,进而将报文进行广播。直到下一次交换机学习到mac。
我们的解决方案:ovn侧提供了一个可选参数 arp-proxy
用于使能网络的arp代答功能,默认关闭了vlan网络的arp代答,除localnet port,localport外的其它所有port,产生流量期间都需要主动发送arp报文,从而使得交换机能适时地学习到mac。
东西向路由问题分析
vlan的东西向路由,有如下需要注意的地方
mtu
大家都知道geneve的包头更长,跨vlan网段访问geneve网络的时候,vlan网络的mtu值其实是不准确的了,所以这种情况下,需要将物理层面的mtu调整得更大。
裸金属跨网段
上面提到了,裸金属的流量由对应的external port代理,包括它的三层流量,除external port所在节点的其它网关节点默认丢弃该报文。
又如果路由采用了集中式而不是dvr,即所有三层的流量都要集中转发到一个节点上处理。
那么就会出现一个矛盾的地方,如果external port所在节点和路由器网关节点不是同一个的话,裸金属访问三层的流量将会被丢掉。
这是neutron的一个较早的问题,通过reside-on-redirect-chassis
强制所有vlan要上路由的流量转发到路由节点,那么router就不是分布式的了。(最新的neutron做了部分调整)
ovn为什么引入该参数?是为了规避vlan mtu的问题,有兴趣可以去了解。
解决方案:修改了ml2/ovn插件代码不走集中式路由,并利用ovn侧的这两个功能:OVN: Enable E-W Traffic, Vlan backed DVR, OVN: Vlan backed DVR N-S, redirect packet via localnet port,解决了裸金属的跨网段流量不通的问题。
ovn-chassis-mac-mappings的使用
正常使用vlan网络接入dvr,会有如下问题:
- 跨网段访问vlan网段报文,src mac是vlan网段网关mac,如果多个节点都有报文跨网段转发的话,物理交换机就会从不同节点学习到相同mac,这样就会出现流量冲突。
对于以上问题,ovn提出了ovn-chassis-mac-mappings
这个配置项,使用该配置项为每一个chassis(节点)配置一组不同的mac地址,ovn-controller会将src mac是子网网关mac的vlan报文,替换src mac为ovn-chassis-mac-mappings
配置的对应mac。这样的话,就能保证跨网段的报文从不同节点发出的源mac是不同的,避免了交换机上mac冲突。
配置命令:
ovs-vsctl set Open_vSwitch . external-ids:ovn-chassis-mac-mappings=physnet1:aa:bb:cc:dd:ee:ff,physnet2:bb:aa:cc:dd:ee:ff |
广播问题
类似二层vlan的广播问题,在三层路由时也会存在。当访问垮网段访问vlan网络时,由于ovn-controller进行了目的mac代理,所以如果物理交换机fdb没有目的mac的记录,则会判断报文目的mac为未知mac,然后将报文进行广播。
可能有人会提出,采用类似上面提到的关闭arp代理的方案是不是就可以解决问题了,实际是不行的。如果关闭arp代理,按照ovn逻辑路由的流程,它还会走mac_binding的流程。即前面提到的,ovn在三层路由里实现了对未知ip的mac学习功能,也就是说即便arp代理关闭了,它还可以通过arp学习完成。
目前dvr下的广播问题,社区讨论dvr for vlan is not completely supported有一个很粗略的方案,简单描述就是,定期的往物理交换机上送虚机rarp报文,让交换机定期学习到mac。
这个patch:controller: send GARPs for LSPs in vlan-backed network scenario提供参数使ovn-controller替虚机网卡发送rarp,不过看上去不能替裸机/sriov虚机发送。
总结
总的来看,ovn的vlan网络存在诸多问题,其中像mtu和dvr子网网关mac冲突这些都还可以workaround的方式规避掉,但是广播问题却是没有好的方案去解决。所以我们目前是禁止vlan租户网络(不包括外部网络)接入dvr,如果你有更好的方案恳请沟通交流(^_^)。
下一篇文章将会分析ovn vlan网络下的南北向流量问题。
个人分析,欢迎指正,若转载请注明出处!