共计 4641 个字符,预计需要花费 12 分钟才能阅读完成。
引言
Kubernetes 要求集群中的每个 pod 都具备惟一的,可路由的 IP,Kubernetes 自身不会调配 IP,而是将工作留给第三方解决方案。
本次课题的指标是找到具备最低提早,最高吞吐量和最低装置老本的解决方案。因为我的负载对提早敏感,因而我的目标是在绝对较高的网络利用率下测量较高的百分比提早,特地是最大负载的 30%到 50%之间的性能,因为我认为这是最能代表非过载零碎的最常见用例。
竞争对手们
Docker with –net=host
这是咱们的一个参考设置,所有其余竞争对手都会与此设置进行比拟。–net=host 选项示意容器继承其主机的 IP,即不波及容器网络。
依据先验准则,没有任何容器网络计划比其余的会有更好的体现,这就是为什么应用此设置作为参考的起因。
Flannel
Flannel 是一个虚构网络解决方案,由 CoreOS 保护,它是通过充沛验证可立刻投入生产的解决方案,因而装置老本最低。将带有 Flannel 的 worker 节点增加到 k8s 群集时,Flannel 会做三件事:
- 应用 etcd 为新 worker 节点调配一个子网
- 在机器上创立虚构网桥接口(称为 docker0 网桥)
- 设置数据包转发后端:
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 的容器,你必须:
- 创立一个齐全没有网络接口的容器
- 在默认网络名称空间中创立 ipvlan 接口
- 将此接口挪动到容器的网络命名空间中
IPvlan 是一个绝对较新的解决方案,因而没有现成的工具能够主动执行此过程。这使得很难在许多服务器和容器中部署 IPvlan,即部署老本很高。
然而,IPvlan 不须要桥接接口,而是间接将数据包从 NIC 转发到虚构接口,因而冀望它的性能优于 Flannel。
负载测试计划
对于每个竞争对手,执行以下步骤:
- 在两台物理机上设置网络
- 在一台机器上的容器中运行 tcpkali,让其以恒定速率发送申请
- 在另一台计算机上的容器中运行 Nginx,让它以固定大小的文件响应
- 捕捉零碎指标和 tcpkali 后果
咱们以每秒 50,000 至 450,000 个申请(RPS)的申请速率运行基准。
在每次申请时,Nginx 都会响应一个固定大小的动态文件:350 B(内容为 100 B,题目为 250 B)或 4 KB。
测试后果
- 结果显示 IPvlan 有着最低的提早和最高的最大吞吐量,host-gw 和 aws-vpc 的 Flannel 紧随其后,然而 host-gw 在最大负载下显示的后果更好。
- 应用 vxlan 的 Flannel 在所有测试中均显示最差的后果,然而,我狐疑 99.999%ile 测试后果的异样是由一个 bug 引起的。
- 4 KB 响应的后果相似于 350 B 响应的后果,但有两个显著的区别:最大的 RPS 要低得多,因为在 4 KB 响应下仅需约 270kRPS 即可齐全加载 10 Gbps NIC。
- 吞吐量测试中 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)