对于 OpenStack 原生的 Neutron 网络,往往诟病良多,核心问题就在性能无法满足生产环境的要求。一般来说,实验室数据往往需要是需求数据的几倍才能平稳、无明显延时的应对用户在真实生产环节下的复杂网络流量。
Neutron 的网络构成非常复杂,以一个典型的 OpenStack 网络节点为例,所使用的核心组件包括但不限于下面的模块/软件:
■ Linux Kernel 协议栈,包括系统软中断到完整的 TCP/IP 协议栈,用以收发报文、路由和策略路由等;
■ iptables,作为内核模块,与 conntrack 共同完成带状态的 DNAT 与 SNAT,如果有安全策略,例如 FWaaS 或者 LBaaS 的安全组,则也需要 iptables 过滤报文;
■ tc,用于收发报文的限速,例如浮动 IP 的限速,社区版代码并没有这部分,但如果厂商需要实现浮动 IP 限速,比较常见的方法是在这里做,此外如果有厂商希望提高 1:1 NAT 的性能,也可以通过 tc 实现,但比较少见;
■ Openswan、strongSwan、Libreswan,一般厂商会从中选取认为稳定、可靠的 Driver 提供简单的 IPSec VPN 功能;
■ Open vSwitch,作为虚拟交换机,要实现基本的二层交换功能,同时提供诸如流表、ARP 代答、二层标签替换等功能,如果想实现相对简单的流控功能,也可以通过 Open vSwitch,但目前应用厂商也较少;
■ VXLAN 模块,如果使用 VXLAN 网络,搭配内核 Datapath 的 Open vSwitch,则需要内核的 VXLAN 模块解析和封装外边的 VXLAN 报文;
■ HAProxy,作为 OpenStack 默认的 LBaaS Plugin(假定用户没有使用 Octavia,毕竟还比较新),为用户提供负载均衡功能;
■ Dnsmasq,作为 OpenStack 默认的 DHCP 的 Driver,为用户提供 DHCP Server 功能,还可以提供 DNS 查询;
■ 网卡驱动,包括物理网卡驱动例如 ixgbe,也包括虚拟网卡驱动例如 vport-internal,当然 internal 接口实际上是 Open vSwitch 代码的一部分。
(没有时间画一个很完整的图,这个图大概表现了内核网络的大概过程,可以参考下)
这么多组件、模块,集合在一台服务器上,调优的难度相当大。我们如果仔细考察整个过程对计算资源的使用(内存资源在 x86 中往往比较宽裕),其中协议栈部分和协议栈相关软件依赖 Namespace 隔离(然而,内核里的很多计算资源使用是无法隔离的),网卡的 Soft IRQ 其实是共用资源,只能通过哈希尽量分散对 CPU 资源的使用,Open vSwitch 的 Datapath 和 vswitchd 也很难说对用户做完整的资源隔离,因此总体来看,网络节点通过大量手段完成了网络通信的隔离(二层通信依赖 VLAN/VXLAN,三层以上依赖 Namespace),但是 IO 对计算资源的使用依然是一个很难解决的待处理难题。
一种思路是通过对网络通信的限制完成隔离,例如限制网络带宽和 PPS,其中限制带宽是一种比较不太有效的方法,例如我们允许虚拟机对外访问使用 1Gbps 带宽,相当于虚拟的一个千兆网卡,此时虚拟机小包线速可以发到 1.4Mpps,依然是一个很高的数字。在例如从外边收到攻击或者收到海量的报文,如果到 namespace 下的 tc 才做 QoS,很有可能 Open vSwitch 和网卡 softirq 都会瞬间跑满,以至一个用户影响所有用户。此时如果通过 Open vSwitch 控制带宽,效果会比 tc 好一些,如果使用 Flow director,效果可能会更好。
另一种思路是通过强隔离的手段分离用户对资源的使用,例如 NFV 思路,将网络功能封装在虚拟机里,这样资源隔离完全通过 Hypervisor 实现,设置 Flavor 和隔离资源都可以达到很好的效果,但目前 Neutron 社区的进展并不很突出。
无论哪种思路,大多都离不开 Open vSwitch,如何很好的评估 Open vSwitch 的性能、评估整个 Neutron 网络的性能因此成为一个对厂商比较困扰的问题。
简单来讲,评估测试的手段有以下这些(分类不完全科学,以尽量表现特点为主):
1、依赖内核协议栈的打流工具,如 iPerf、netperf 等;
2、依赖内核的打包工具,如 pktgen、hping、nping 等;
3、专业的测试仪表,例如思博伦、IXIA 等;
4、基于 dpdk 的打包工具如 dpdk-pktgen、moongen、trex 等。
其中:
1的性能较弱,定制流的能力较差,难以反映准确结果;
2的灵活性比较一般,难以超出其本身 scpoe 灵活打流,统计功能一般,性能也无法达到专业需求;
3在各方面都是最佳之选,无奈价格昂贵,一般厂商难以承担,而且测试仪使用繁琐,效率不高;
4我们测试过 moongen 和 trex,moongen 在测试过程中经常出现流打不稳的问题,而且统计功能一般,最终我们选择了 trex,并已经投入生产研发。
trex 的安装、编译非常简单,文档也比较全面,这里直接介绍两个简单的 use case:
⋅通过 trex 测试 Open vSwitch 的 VXLAN 二层性能;
⋅通过 trex 测试 VXLAN 拓扑下内核路由性能。
其中第一个我们可以这样测试:
其中呢,我们在 Trex 绑定两块网卡,Trex 所在服务器(TG)通过交换机连接到待测服务器(DUT),在 DUT 上配置 IP 地址 10.0.109.171/24,并在 Open vSwitch 上建立两条到 TG 的 VXLAN 隧道,Switch 上和 DUT 上配置 10.0.109.67 和 10.0.109.68 的静态 ARP(交换机上添加 CAM 即可),以避免内核协议栈发送 ARP 请求和交换机泛洪。图中实线表示实际物理连线,虚线表示隧道,虚线平行四边线表示这个 IP 通过静态 ARP 配置,并不是真实配置的 IP 地址,实线平行四边形表示配置在网口上的 IP 地址。
然后在 Open vSwitch 上添加流表,将 vxlan-port-1 口的流量直接转发给 vxlan-port-2,DUT 配置为 Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz,Intel 82599ES,调整 pstate 为性能,开启超线程,将网卡 IRQ 绑定在本地 Node 上,开启 UDP RSS 的四元组哈希。
Trex 支持 Stateful 发包和 Stateless 发包,在这里我们使用后者。其内置 Scapy 版本为 2.3.1,这个版本没有直接支持 VXLAN,有两种处理方法,一是自己在发包脚本中修改,类似官方的实例:stl/udp_1pkt_vxlan.py,另一种方法是直接修改 scapy 的代码,为了方便起见,我们采用了后者:
创建一个文件:external_libs/scapy-2.3.1/python2/scapy/contrib/vxlan.py,内容如下:
此外再创建文件 external_libs/scapy-2.3.1/python2/scapy/contrib/all.py:
最后在 external_libs/scapy-2.3.1/python2/scapy/all.py 添加:
下面我们就可以发送 VXLAN 报文了,以我们的测试代码为例:
Base 报文构造需要看具体的测试场景,这的注意是为了方便 DUT 哈希,我们通过外层报文的 UDP 原端口和内层报文的源 IP 构造了多流,但修改报文后要记得恢复 Checksum,特别是 VXLAN 报文,需要保证内层报文的三、四层校验值、外层报文的三、四层校验值。
此时我们已经可以用 trex 发包了,注意发送 statless 报文时,需要先使用 interactive 模式打开 t-rex,再通过 trex-console 连接下发命令,当我们将发送速度限制在 3.2Mpps 时可以看到丢包率为 0,且较为平稳,再提升将会出现丢包:
上图为 trex 的统计数据,可以看到 trex 实际使用的资源很少,而且此时发包 pps 为 3.21 Mpps,収包为 3.05 Mpps,这两个数字并不匹配,但 trex 认为此时 droprate 已经为 0 了。阅读源代码可以看到 trex 代码中认为 drop-rate 如果低于 tx 速率的 0.1 就会直接抹平,可能是考虑到了统计数据的不准确性,但是大致已经可以反映性能指标。
下面我们可以尝试测试路由性能,拓扑是类似的,只是在 OVS 上添加两个端口:
为了路由能够完成,我们需要在 qr-1、qr-2 上添加 IP 地址,以达到内核能够正确路由的目的,此外需要在 Name Space 上额外添加静态 ARP,以避免命名空间发送 ARP。为了尽可能模拟 Neutron 实际使用,我们添加了 VLAN 头部转换的过程,OVS 流表可以这么写:
此外 trex 还有很多高级功能,例如 Stateful 发包、测量延时、发送高级的多流、发送波峰等,还可以自动通过二分查找 NDR(Non Drop Rate)、PDR(Partially Drop Rate)下面是一个 Trex 与 IXIA 比较:
Have fun!(作者:王为,UnitedStack有云)