乐趣区

关于kubernetes:k8s网络解决方案性能PK

引言

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 NUMA
    NUMA node(s):          2
    NUMA node0 CPU(s):     0-8,18-26
    NUMA 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 = 1024000
    net.ipv4.ip_local_port_range = "2000 65535"
    net.ipv4.tcp_max_tw_buckets = 2000000
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 10
    net.ipv4.tcp_slow_start_after_idle = 0
    net.ipv4.tcp_low_latency = 1

    脚注

  • Linux kernel documentation: RPS Configuration)
  • Linux kernel documentation: XPS Configuration)
退出移动版