软件的复杂度随着软件功能的丰富和接口的复杂性的上升几乎是必然的,Open vSwitch 的稳定性和性能也一直在提升,所以社区决定要发动力量主要解决第二个问题。
首先是 HA,企业 IT 系统首先关心的,莫过于系统的稳定性,一个可靠的 HA 方案是社区首先考虑的。很多网络服务的高可用都是借助 VRRP 协议的,Neutron 也不例外,通过 Keepalived + conntrackd,实现 Master 和 Slave 共同维护 VIP,一旦 Master 挂掉了,VIP 将自动飘到 Slave 节点上,因为 conntrackd 始终在自动拷贝session 信息,所以理论上可以实现用户的无感知自动切换。
L3 HA 确实实现了高可用,但是东西流量还是没有优化啊,这里面一大原因是 VxLan本来支持组播的,但是 OVS 目前支持有限,我们总是不得把一些无效的 ARP 广播发送出去。比如说下图中,A 的广播包其实只对 3 和 4 有用,但是 2 和 5 也收到了:
如何优化,这里的问题是虚拟机不知道通信对方的位置,可是 Neutron 知道啊,Neutron 数据库中保存着每一个 Port 联接的虚拟机信息、其 IP、MAC 地址、其宿主机信息等等,所以如果有新的虚拟机建立起来,连接了网络,那么 Neutron 就往所有 Agent 发送消息,告诉他们新的 Port 的所有信息,大家就低头检查看看自己是不是也有这个网络的虚拟机,如果有就更新流表规则,将来要请求这个 IP 的 ARP 可以直接回应,如果没有就忽略。这就是 L2 Population 和 ARP responder。
OK,更加优化了一步,但是他也有问题啊,就是
因为消息是广播的,很耗费资源;
跨网络的通讯还要依赖于路由器;
它目前没办法和 L3 HA 共同工作!
为什么它无法和 L3 HA 共同工作呢,因为 L2 Pop 假定了每个 Port 都工作在一个固定的节点上,这样 L2 Pop 才能将 ARP 和 Tunnel 引过去,然而 L3 HA 破坏了这个假设…… Bug 的 report 见 Launchpad 上的 #1365476 ,目前尚未解决…… 新的架构这么说来,Neutron 在企业化道路上真实困难重重啊,怎么办,社区决定不能在旧的架构上修修补补了,让我们真正实现一个分布式虚拟路由(Distributed Virtual Routing 简称 DVR)吧!
由于过去的集中化的虚拟路由 L3 Agent 实现的很完整了,社区决定方案就是将其从单独部署在网络节点转为分布式的部署在所有计算节点上,每个计算节点都有自己的 Router Namespace,就像之前 Nova-network 在各个节点上都有自己的 Gateway 一样。
首先我们看虚拟机绑定公网 IP 情况下的公网流量:
当一个外部的报文需要和虚拟机通信时,首先会发到网桥 br-ex,然后 FIP Namespace 的 fg 设备响应其 ARP,再被路由到 fpr 上,进入 DVR Namespace,这里再通过 iptables 将公网 IP DNAT 为内网地址,发往虚拟机。内部网外部通信也是类似的道理。
对很多用户来说,南北流量不是他们最关心的问题,他们最关心的是东西流量:
因为现在路由器就在计算节点上,所以我们只需要在 Namespace 内完成路由就行了,这和以前在网络节点上是一样的。但是会出现多个计算节点上会存在同一子网的网关,怎么办?解决方案是为每一个计算节点生成唯一的DVR MAC 地址,在对外发出数据包之前,将原有 MAC 替换成 DVR MAC,保证双向通信的正常进行。
OK,我们解决了问题,但也引入了新的问题:
因为现在 ARP 应答无法跨计算节点,像 Allowed address pair 这样的扩展也无法工作了(回应非 Port 自己本身绑定的 IP 的 ARP 请求)。