引言

Kubernetes要求集群中的每个pod都具备惟一的,可路由的IP,Kubernetes自身不会调配IP,而是将工作留给第三方解决方案。

本次课题的指标是找到具备最低提早,最高吞吐量和最低装置老本的解决方案。 因为我的负载对提早敏感,因而我的目标是在绝对较高的网络利用率下测量较高的百分比提早,特地是最大负载的30%到50%之间的性能,因为我认为这是最能代表非过载零碎的最常见用例。

竞争对手们

Docker with --net=host

这是咱们的一个参考设置,所有其余竞争对手都会与此设置进行比拟。--net=host选项示意容器继承其主机的IP,即不波及容器网络。

依据先验准则,没有任何容器网络计划比其余的会有更好的体现,这就是为什么应用此设置作为参考的起因。

Flannel

Flannel是一个虚构网络解决方案,由CoreOS保护,它是通过充沛验证可立刻投入生产的解决方案,因而装置老本最低。将带有Flannel的worker节点增加到k8s群集时,Flannel会做三件事:

  1. 应用etcd为新worker节点调配一个子网
  2. 在机器上创立虚构网桥接口(称为docker0网桥)
  3. 设置数据包转发后端:

aws-vpc
在Amazon AWS实例表中注册机器子网,此表的记录数限度为50,即如果将Flannel布与aws-vpc一起使 用,则集群的节点数量不能超过50,此外,尔后端仅实用于Amazon的AWS。
host-gw
通过近程主机IP创立到子网的IP路由。 须要运行Flannel的主机之间2层直连。
vxlan
创立一个虚构VXLAN接口
因为Flannel应用网桥接口转发数据包,因而流量从一个容器到另一个容器的过程中,每个数据包都会通过两个网络栈。

IPvlan

IPvlan是Linux内核中的驱动程序,可能创立具备惟一IP的虚构接口,而不用应用网桥接口。

要将IP调配给具备IPvlan的容器,你必须:

  1. 创立一个齐全没有网络接口的容器
  2. 在默认网络名称空间中创立ipvlan接口
  3. 将此接口挪动到容器的网络命名空间中

IPvlan是一个绝对较新的解决方案,因而没有现成的工具能够主动执行此过程。 这使得很难在许多服务器和容器中部署IPvlan,即部署老本很高。
然而,IPvlan不须要桥接接口,而是间接将数据包从NIC转发到虚构接口,因而冀望它的性能优于Flannel。

负载测试计划

对于每个竞争对手,执行以下步骤:

  1. 在两台物理机上设置网络
  2. 在一台机器上的容器中运行tcpkali,让其以恒定速率发送申请
  3. 在另一台计算机上的容器中运行Nginx,让它以固定大小的文件响应
  4. 捕捉零碎指标和tcpkali后果

咱们以每秒50,000至450,000个申请(RPS)的申请速率运行基准。
在每次申请时,Nginx都会响应一个固定大小的动态文件:350 B(内容为100 B,题目为250 B)或4 KB。

测试后果

  1. 结果显示IPvlan有着最低的提早和最高的最大吞吐量,host-gw和aws-vpc的Flannel紧随其后,然而host-gw在最大负载下显示的后果更好。
  2. 应用vxlan的Flannel在所有测试中均显示最差的后果,然而,我狐疑99.999%ile测试后果的异样是由一个bug引起的。
  3. 4 KB响应的后果相似于350 B响应的后果,但有两个显著的区别:最大的RPS要低得多,因为在4 KB响应下仅需约270kRPS即可齐全加载10 Gbps NIC。
  4. 吞吐量测试中IPvlan有限靠近--net=host。

咱们以后的抉择是应用host-gw模式的Flannel,它没有太多的依赖关系(例如,不须要AWS或新的Linux版本),与IPvlan相比,它易于部署,并且具备足够的性能个性,IPvlan是备选计划,如果某个时候Flannel增加了IPvlan反对,咱们将会切换到它。

只管aws-vpc的性能比host-gw稍好,但其50台计算机节点的局限性以及将其硬连线到Amazon的AWS的事实对咱们来说都是一个阻碍。

50,000 RPS, 350 B


在每秒50,000个的申请速度下,所有候选者都体现出令人满意的性能,次要趋势是:IPVlan体现最佳,host-gw和aws-vpc紧随其后,vxlan体现最差。

150,000 RPS, 350 B



IPvlan略优于host-gw和aws-vpc,然而在99.99 %ile这个指标上是最差的,host-gw的性能略优于aws-vpc。

250,000 RPS, 350 B


这种负载在生产中也很常见,因而这些后果尤为重要。

IPvlan再次显示出最佳性能,然而在99.99和99.999 %ile这两个指标上aws-vpc更胜一筹,host-gw在95和99% %ile上优于aws-vpc。

350,000 RPS, 350 B


在大多数状况下,提早靠近250,000 RPS(350 B状况),但在99.5 %ile之后迅速增长,这意味着咱们曾经靠近最大RPS。

450,000 RPS, 350 B

这是实践上能产生正当后果的最大RPS,IPvlan再次当先,提早比--net-host差30%左右:


乏味的是,host-gw的性能比aws-vpc更好:

500,000 RPS, 350 B

在500,000 RPS下,只有IPvlan依然无效,体现甚至优于--net=host,然而提早是如此之高,以至于咱们认为这对提早敏感的程序毫无用处。

50k RPS, 4 KB


较大的响应会造成较高的网络使用率,但测试后果看起来与较小的响应简直雷同:

150k RPS, 4 KB


Host-gw具备令人诧异的99.999%ile,对于较低的百分位数也显示出良好的后果。

250k RPS, 4 KB


这是在大的申请响应下的最大RPS,与小的申请响应测试用例不同,aws-vpc的性能比host-gw好得多,Vxlan再次从图中排除。

测试环境

背景

为了了解本文并重现咱们的测试环境,你应该相熟无关高性能的基础知识。
这些文章提供了无关该主题的有用见解:

  • 如何每秒接管一百万个数据包 by CloudFlare
  • 10Gbps以太网如何实现低提早 by CloudFlare
  • 扩大Linux网络堆栈 from the Linux kernel documentation

    服务器规格清单

  • 须要2台Amazon AWS EC2实例,零碎版本为CentOS 7,实例规格为c4.8xlarge,两个实例均开启了加强联网性能。
  • 每个实例都有2个处理器的NUMA,每个处理器有9个外围,每个外围有2个超线程,这实际上容许在每个实例上运行36个线程。
  • 每个实例都有一个10Gbps网络接口卡(NIC)和60 GB内存。
  • 为了反对加强联网性能和IPvlan,曾经装置了带有Intel ixgbevf驱动程序的Linux内核4.3.0版本。

    装置部署

    古代NIC通过多个中断请求(IRQ)线提供接管方扩大(RSS),EC2在虚拟化环境中仅提供两条中断线,因而咱们测试了几种RSS和接管数据包导向(RPS)接管数据包导向(RPS)配置,最终失去以下配置,局部由Linux内核文档提供:

    IRQ

    两个NUMA节点中的每个节点上的第一个核都配置为接管来自NIC的中断。
    应用lscpu将CPU与NUMA节点匹配:

    $ lscpu | grep NUMANUMA node(s):          2NUMA node0 CPU(s):     0-8,18-26NUMA node1 CPU(s):     9-17,27-35

    这是通过将0和9写入/proc/irq/<num>/smp_affinity_list来实现的,其中IRQ编号是通过grep eth0 /proc/interrupts取得的:

    $ echo 0 > /proc/irq/265/smp_affinity_list$ echo 9 > /proc/irq/266/smp_affinity_list

    RPS

    已测试了RPS的几种组合,为了进步提早,咱们仅应用CPU 1–8和10–17加重了IRQ解决处理器的累赘。与IRQ的smp_affinity不同,rps_cpus sysfs文件条目没有_list对应项,因而咱们应用位掩码列出RPS能够将流量转发到的CPU:

    $ echo "00000000,0003fdfe" > /sys/class/net/eth0/queues/rx-0/rps_cpus$ echo "00000000,0003fdfe" > /sys/class/net/eth0/queues/rx-1/rps_cpus

    Transmit Packet Steering (XPS)

    将所有NUMA 0处理器(包含HyperThreading,即CPU 0-8、18-26)设置为tx-0,将NUMA 1(CPU 9-17、27-37)设置为tx-12:

    $ echo "00000000,07fc01ff" > /sys/class/net/eth0/queues/tx-0/xps_cpus$ echo "0000000f,f803fe00" > /sys/class/net/eth0/queues/tx-1/xps_cpus

    Receive Flow Steering (RFS)

    咱们打算应用60k常驻连贯,官网文档倡议将其四舍五入为最靠近的2的幂:

    $ echo 65536 > /proc/sys/net/core/rps_sock_flow_entries$ echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt$ echo 32768 > /sys/class/net/eth0/queues/rx-1/rps_flow_cnt

    Nginx

    Nginx应用18个worker,每个worker都有本人的CPU(0-17),通过worker_cpu_affinity选项设置:

    **workers** 18;**worker_cpu_affinity** 1 10 100 1000 10000 ...;

    Tcpkali

    Tcpkali没有内置的CPU亲和性反对,为了利用RFS,咱们在工作集中运行tcpkali并调整调度程序,避免线程迁徙的产生:

    $ echo 10000000 > /proc/sys/kernel/sched_migration_cost_ns$ taskset -ac 0-17 tcpkali --threads 18 ...

    与咱们尝试过的其余设置相比,此设置可能更平均地在CPU内核之间调配中断负载,并以雷同的提早实现更好的吞吐量。
    CPU 0和9专门解决NIC中断,不解决数据包,但它们仍是最忙碌的:

    RedHat的调整也与网络提早配置文件一起应用,为了最大水平地缩小nf_conntrack的影响,增加了NOTRACK规定,内核参数已调整为反对大量tcp连贯:

    fs.file-max = 1024000net.ipv4.ip_local_port_range = "2000 65535"net.ipv4.tcp_max_tw_buckets = 2000000net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_fin_timeout = 10net.ipv4.tcp_slow_start_after_idle = 0net.ipv4.tcp_low_latency = 1

    脚注

  • Linux kernel documentation: RPS Configuration)
  • Linux kernel documentation: XPS Configuration)