22

话说kubernetes网络疑难杂症 | 鱼儿的博客

 4 years ago
source link: https://yuerblog.cc/2020/03/06/%E8%AF%9D%E8%AF%B4kubernetes%E7%BD%91%E7%BB%9C%E7%96%91%E9%9A%BE%E6%9D%82%E7%97%87/?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

话说kubernetes网络疑难杂症

大家好,我是来自什么值得买的前台业务架构师owenliang,近期正在推动业务向kubernetes迁移,在这个过程中遇到了一些棘手的问题,在此逐一向大家分享。

在真正进入到问题之前,我会先对我司kubernetes现状以及kuberntes原理做一些基本介绍。

kuberntes技术栈介绍

公司业务主要以PHP、JAVA、Python为主,调用方式均为短连接HTTP方式。

我们基于Django开发了一套Devops发布系统,能够方便的完成镜像构建与Kubernetes应用发布。

Kubernetes集群直接采用Ucloud提供的UK8S集群,版本为1.15,docker版本是18.09。

Kubernetes的Node采用的是4.19.0内核,16核32G配置,kube-proxy采用的是iptables模式(也许有人会问为什么不用IPVS?答:原因后面会讲),iptables版本是1.4.21。

UK8S实现了CNI,提供了underlay扁平网络结构,POD与VM的IP可以互通,网络性能优异。

Kuberntes应用通过LoadBalancer类型的Service向集群外暴露访问地址,Ucloud会为Service创建集群外的ULB负载均衡入口,出于复杂度&管理一致性的考虑,我们现在并没有使用Ingress收敛集群流量入口。

集群内采用Coredns解析域名,我们通过hosts插件配置域名解析service的ULB IP(也许有人会问为什么要解析到ULB而不是Cluster IP ,不怕流量绕出集群么?答:原因后面会讲),并通过template插件响应NXDOMAIN给IPV6查询请求,以此优化DNS查询速度。另外,我们在容器里启用了nscd本地DNS缓存,目的是减轻对Coredns的查询压力。

kubernetes网络原理

以UK8S集群为例,我们需要充分理解其网络原理,才能对网络问题加以分析与优化,这个过程涉及到比较综合的网络理解能力。

CNI原理

首先,UK8S自定义了CNI支持扁平网络结构,这意味着VM和POD的IP地址属于同一个网段,可以直接互通,并不需要通过Nodeport来做流量转发。

下面是宿主机node的IP地址:

1.jpg

Ucloud在SDN层面已经实现了对POD IP的路由,因此当集群外访问POD IP时,流量将会送入到POD所在Node的网卡。

流量进入node后,CNI已经接管了node路由表的管理,它在node上配置了如下的规则:

2.jpg

第1条规则即SDN默认网关10.42.0.1,第2条规则表示node所处网段是10.42.x.x,后续规则是该node上每一个POD的流量递送规则。

当请求POD IP 10.42.13.2的流量被SDN送入到该node后,经过本机路由表确认需要发往与POD相连的本机虚拟网卡(veth pair),从而流量进入到POD。

从POD内来看,其路由表将node作为默认网关:

3.jpg

因此POD回包的目标MAC地址会ARP解析为node的物理网卡地址,进而包经过SDN处理后再次回到node,进而走node路由表默认网关FOWARD送往SDN网关。(CNI并没有在node上建立docker bridge子网,而是直接依托于SDN的扁平网络做ARP响应)

kube-proxy原理

kubernetes基于iptables或者ipvs实现service的负载均衡功能,为了理解service必须理解iptables/ipvs,而理解iptables/ipvs则必须理解它们共同的底层内核机制netfilters。

这里我先发一张netfilters的流量处理流程,翻遍大家对照理解:

iptables.png

为了让大家理解netfilters的原理,我将以实际的3种场景来给大家做对照说明。

场景1)pod1(node1) -> service(cluster ip/ULB ip) -> pod2I(node2)

即集群内POD1通过service负载均衡调用到POD2。

在上面我分析过,POD1发往任意IP的流量其目标MAC地址都会指向node1,进而由node1完成流量转发。

node1收到POD1发来的流量,其目标MAC地址是node1,因此流量被欣然接收。

接着流量经过netfilter的PREROUTING阶段,在此阶段会经历nat表的规则计算,以便匹配流量是否发往cluster ip/ULB ip,我们看一下规则:

5.jpg这是由node1上的kube-proxy下发的iptables规则,用于实现对访问service的地址改写。

我们继续跟随target跳转到下一个链上的规则:

6.jpg

我截取了某个service的2条规则:

  • 第1条匹配目标IP地址是10.0.132.186的流量,这个IP其实是service的cluster ip,命中则跳转KUBE-SVC-NUA4LXHYE462BSW2链。(可见kube-proxy已经给这条规则写了注释)
  • 第2条匹配目标IP地址是10.42.185.165的流量,这个IP其实是service的ULB ip,命中则跳转KUBE-FW-NUA4LXHYE462BSW2链。

如果我们POD1调用service使用的是Cluster ip则命中第1条规则,如果调用ULB ip则命中第2条规则,之前我也介绍过我司会将域名解析为ULB ip,所以我们就看一下第2条规则的后续行为:

7.jpg

这里又出现了3条规则,第1条规则是使用mark模块给这个连接打了1个标记位(我们暂时不进去看),重要的是第2条规则,它完成了目标IP地址改写(即DNAT):

8.jpg

因为我只有1个后端POD2,所以这里最终追溯到只有1条DNAT规则,将目标IP地址从ULB ip改为这个POD2的IP:10.42.145.194。

那么经过PREROUTING nat改写后,根据netfilters流程图将判断node路由表决定这个包的去向,目标POD2 IP会命中node的默认网关(当然也有概率POD2就在这个node上,那么就如同之前所说直接从虚拟网卡送入POD2),那么流量经过FORWARD阶段->POSTROUTING阶段,最终发往SDN默认网关,进而流入POD2所在的node2。

在流量离开POD1之前还会经历一次POSTROUTING的nat表规则,这里因为在KUBE-SERVICE链命中时对连接标记了mark,所以这里会做一次SNAT改写源IP地址为node1的IP,也就是说这个连接对于POD2来说其源地址并不是POD1而是node1。(实际上在扁平网络结构里,这一步SNAT我认为可以不做)

我们就不继续描述流量到达node2时候如何进入POD2的过程了,留给大家思考。

场景2)pod1(node1) -> redis/mysql(集群外)

即POD1请求部署在集群外虚拟机上的redis,mysql等。

POD1发出的流量经过POD内路由表送往默认网关node1,进入node1的PREROUTING nat阶段,因为其目标IP地址不属于任何service,所以没有进行任何地址改写,查找node1路由表决定发往SDN默认网关,进而走FORWARD和POSTROUTING离开node1,因为没有命中KUBE-SERVICE规则所以没有mark标记,所以POSTROUTING nat也并不会做SNAT,因此在redis/mysql看来源IP是我们的POD1 IP。

场景3)集群外VM -> ULB -> node1 -> pod2(node2)

该场景其实是场景1)的升级版,集群外应用调用ULB,由ULB负载均衡到kubernetes集群某node1的对应nodeport,进而经过node1转发给node2,进入pod2。

ULB会将流量转发到service的nodeport,也就是每个node都会为这个service暴露同一个端口。

在POSTROUTING阶段的KUBE-SERVICES规则末尾,其实有一条针对nodeport端口识别的规则链:

    2   120 KUBE-NODEPORTS  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL

因为ULB转发给kubernetes集群时目标IP就是node的IP,端口是service对应nodeport端口,所以这条规则特意match了目标IP地址是local(也就是本机IP)的流量。

8-1.jpg
我选中的2行规则是针对该service的匹配,它识别nodeport是46794的service,然后给mark标记它是调用service的流量,然后走DNAT规则改写(我就不给大家展开了)。

另外,不知道是UK8S的CNI还是kube-proxy默认行为,会把ULB的IP地址也加到KUBE-SERVICE的匹配规则中,因此POD通过ULB调用另外1个POD,实际流量是直接被iptables改写的,并不会真的离开集群绕道ULB。(这回答了文章开头的一个问题)

至此基本的netfilters流程就差不多了,后面我们还会涉及到更深入的一点补充。

网络疑难杂症分析

对网络流量有了基本理解之后,我们再来分析问题就会清晰很多(如果对先前的内容不是很理解,可能对网络欠缺比较多,可以自行学习这些关键字:iptables、netfilters、路由表、交换机,网桥)。

先说一些结论性的东西:

问题基本集中在4层,主要是TCP,分析问题需要端到端完整的链路分析。

重点在于,流量在node转发过程中不会过TCP协议栈,只会经过node的netfilters,最终POD才是TCP协议栈的处理者。

问题定位与优化,需要从node和POD分别思考,找到瓶颈所在。

下面是我们遇到的N个主要问题与定位,如果大家对技术细节不关心只想找到解决方法,那么下面的信息对你也很重要。

node上conntrack大量INVALID

现象

压测时,在集群node上观察conntrack -S发现大量INVALID报文。

conntrack俗称流表,或者连接跟踪表,它属于netfilters框架,在之前的netfilters图片中大家可以看到在PREROUTING mangle之前以及OUTPUT mangle之前都会经过一个connection tracking的表。

conntrack是实现nat地址转换的灵魂,一个连接仅在首次经过netfilters链条时会计算nat表,一旦conntrack记录下这次的改写关系,后续无论是去程包还是回程包都是依据conntrack表进行改写关系的处理,不会再重复执行nat表中的DNAT/SNAT规则。

因此,在node的conntrack表中记录了大量的记录,每条记录包含2部分:

  • 改写前的源IP和目标IP
  • 改写后的源IP和目标IP

conntrack是一个内核里的hash表,使用conntrack命令行工具可以查看,给大家看一个例子:

55.jpg

所以说,node上的conntrack在跟踪流过它的每一条连接,包括其连接状态,改写关系,因此conntrack将是kubernetes优化的一个重点对象。

我无法在一篇文章中展开给大家讲述conntrack的原理,希望大家可以在额外学习一下。

分析过程

有问题先看看内核日志,因此输入dmesg,将会看到大量的如下日志:

nf_conntracktable full, dropping packet

说明是压测期间,node上的conntrack哈希表打满了,我们只需要对其优化一下内核参数即可。

解决方法

在node上利用sysctl调整内核选项:

  • nf_conntrack_max
  • nf_conntrack_buckets
  • nf_conntrack_tcp_timeout_time_wait

具体方法我在文章末尾统一给出,想了解这些参数自己谷歌一下学习一下conntrack吧。

POD内大量TCP重传

现象

压测时,在受压POD内观察到大量TCP重传,在受压POD所在node观察到大量conntrack INVALID报文,其他层面(IP层,链路层)网络指标无异常。

受压POD所在node上的其他应用均出现调用方超时,即某应用受压影响了其他应用的网络状况。

我们知道TCP重传是因为对方回复ACK慢导致的,也许是网络慢或者干脆丢失了。

分析过程

一开始出发点是研究node上conntrack大量INVALID报文的原因,通过打开conntrack INVALID日志可以看到大量报文INVALID,但是看不出原因。

因为压测链路从ULB开始,中间环节较多,还需要向下怀疑到云厂商的ULB/SDN之类的,所以定位时间比较长。

在POD内tcpdump抓包也没有明显线索,只是知道有大量重传,利用mtr探测中间链路没有丢包。

经过几天几夜的奋战,最终开始怀疑虚拟机等方面的底层问题,所以决定脱离kubernetes集群,单纯在2个虚拟机之间压测程序看一下是否同样有大量重传,结果还是有大量重传出现!

在逐渐升高压力的过程中,发现链路层PPS包量无法继续上升,虚拟机资源充足,此刻意识到是不是虚拟机包量限制,经过与运维&Ucloud确认,我司使用的机型包括UK8S的默认机型都是低包量的,其PPS瓶颈是6万左右/秒(in+out总共),真的是相当尴尬的结局。

解决方法

升级网络增强型的虚拟机,其PPS可以高达百万/千万。

替换机型后,我重新做了一下node之间的短连接压测极限CPS(connection per second):

每秒新建短连接:约10万次

每秒包量:约80万次

SDN限制包量是相当于中间链路丢包,对虚拟机上没有直接的链路层反馈,非常难查。

此时,POD内重传恢复正常,node上conntrack的INVALID问题也因此消失,可见中间链路丢包导致conntrack跟踪TCP状态出现了很多乱序问题,导致其统计了大量的无效包。

大家在虚拟机环境下一定要注意包量问题,购买更高PPS的主机来支持高并发场景。

node上conntrack少量insert failed报文

现象

压测时,宿主机conntrack -S报少量insert failed报文。

分析过程

谷歌了一下,这是已知问题。

这是linux内核做SNAT时的时序竞争bug,2个连接并发做SNAT时候有一定概率分配到同一个本地源端口,如果2个连接的目标IP+port恰好也一样,那么相当于出现了2个连接的5元祖(协议,源IP/PORT,目标IP/PORT)完全相同,将会导致连接插入/更新conntrack表失败,因此记录为insert fail。

解决方法

先说结论,这个问题在高压下也不严重,不一定非要解决。

如果要解决,需要做如下的事情:

  • 升级iptables到1.6版本,它支持一个叫做–random-fully的端口选择策略,可以通过更加随机的方式选择端口,降低冲突率。
  • 升级kubernetes集群到1.16版本,从该版本开始kube-proxy下发SNAT规则时才会携带–random-fully选项。

这个问题还是国内的一个团队发现与修复的,给大家一些参考链接:

node上conntrack大量INVALID(再次)

现象

后续我为了得到一些极限性能数据,在2个kubernetes node之间直接进行了短连接压测,目的是对node的内核参数进行优化。

我使用netperf的TCP_CRR模式压测2个node之间极限的短连接压力表现,这里并没有涉及到POD,但是因为node有kube-proxy下发的nat规则,因此conntrack依旧会跟踪我的压测连接,就在此时我发现受压node的conntrack -S报大量INVALID报文,与压力成正比关系。

分析过程

之前已经对conntrack进行了性能优化,唯一的区别就是之前都是利用工具压测HTTP接口,而这次是利用netperf工具压测TCP短连接,主要区别是工具的改变。

遇到conntrack INVALID问题可以通过打开log观察INVALID报文的信息来定位问题,所以我打开了conntrack的INVALID log,结果发现虽然INVALID狂涨,但一条日志都没有滚动,一度怀疑是不是我打开conntrack INVALID log的方式有问题,直到偶尔蹦出一条日志才让我打消了怀疑。

所以,我开始怀疑是不是conntrack在某些INVALID场景下不会打印调试日志呢?

于是我决定看一下linux kernel关于conntrack的源码。

1)找到TCP协议追踪处理的主要方法:https://github.com/torvalds/linux/blob/master/net/netfilter/nf_conntrack_proto_tcp.c#L837

1.png

也就是说,当收到新来的SYN时,conntrack表里还有上一次的TIMEWAIT记录,此时conntrack的逻辑时删除旧的插入新的,并且返回一个NF_REPEAT(repeat表示重复)的负值。

但是这个逻辑并没有打印日志,而其他返回负值的地方都会打印INVALID log。

2)调用该函数的逻辑则认为返回负值就是INVALID,所以会增加一次计数,但是对于返回-NF_REPEAT的情况,会goto跳到代码最上面重新处理一遍这个包:

22.png

但此时我还是有一点疑惑,为什么服务端会遇到TIME_WAIT,通常不都应该是客户端主动关闭连接吗?

于是我在2个node上使用netstat -tanlp|grep TIME_WAIT统计了一下TIME_WAIT连接数量,竟然发现受压node有大量TIME_WAIT,而netperf发压方几乎没有一条TIME_WAIT,这说明netperf的行为是服务端主动关闭连接!

我又在受压node上看了一下netstat -s,观察到海量的TIME_WAIT连接溢出被丢弃,这个问题也就基本定位了:

33.jpg

解决方法

暂时不需要解决,因为返回-NF_REPEAT的话conntrack会goto跳转二次进入处理方法,将该包最终按照正常包处理,最终不会是INVALID包,因此这个INVALID计数也算作conntrack实现的一个”bug”吧。

滚动发布时调用方超时

在最初,我们kubernetess集群采用的是IPVS模式,因此也遇到了一个大坑。

现象

我们使用deployment发布应用,但是发现每次滚动发布都会引发调用方超时,匪夷所思。

分析过程

我首先详细复习了一下Deployment和Service的联动流程,明确要做如下几点调整:

  • POD一定要有livenessProbe和readinessProbe两个健康检查,否则service就会把流量打到一个还没准备好的新POD上。
  • 程序一定要有优雅退出逻辑,kubernetes会首先从service中摘除旧POD的转发规则,然后才会给POD发送SIGTERM退出信号,此时不会有新流量进入,但是程序必须把现有连接服务完毕再退出。
  • 一定要给POD足够的优雅退出时间,通过YAML中设置terminationGracePeriodSeconds实现,建议给比较大的时间窗口(比如30秒),避免流量较多的时候处理残余流量耗时较长,因为一旦超时就会SIGKILL掉程序,导致部分调用就失败了。
  • kubernetes默认行为是给程序发送SIGTERM信号,然后等待terminationGracePeriodSeconds秒后如果程序还没退出则发送SGIKILL。然而NGINX的优雅退出信号并不是SIGTERM,所以我们可能需要借助preStop的Hook,自定义向Nginx发送对应的优雅退出信号,这样kubernetes就不会发送默认的SIGTERM信号了,而且terminationGracePeriodSeconds依旧有效。

做了如上调整后,滚动发布仍旧引发了调用方一连串的报错,QPS越高则越严重。

于是重新思考了一下,要么是上线新POD引发超时,要么是下线旧POD引发的超时,而滚动发布又同时在做下线&上线,怎么区分定位一下呢?

于是决定先将POD从5个扩容程10个,发现没有报错,这说明新POD的健康检查是有效的,流量的进入时机也没问题。而从10个缩为5个POD则引发了报错,因此缩小范围是下线POD引起的。

可是kubernetes下线POD的过程是先摘除service转发,才发送SIGTERM信号给POD,程序也已经是优雅退出的,为啥会有问题呢?

于是开始怀疑是不是其他问题,所以首先怀疑到一个kubernetes工作机制:

deployment会标记1个POD为terminating状态,然后发生了2个并发的事情:

  • kubelet收到etcd变化事件,会立即给POD发送SIGTERM,程序开始优雅退出。
  • kube-proxy收到etcd变化事件,,会立即摘除node上对应pod的iptables转发规则。

kubelet和kube-proxy感知到etcd事件的先后存在时间差,如果先发送SIGTERM再摘除规则就会导致部分新连接在竞争窗口内受损,因为SIGTERM已经让程序关闭监听了。

为了验证这个想法,我们在preStop里首先sleep了2秒再发送优雅退出信号:

– lifecycle:
preStop:
exec:
command:
– /bin/sh
– -c
– sleep 2;pkill xxx;

sleep的目的是为了让iptables规则先下线,再停止程序监听。

然而,这个也没有修复问题。

最终,还是谷歌帮助了我们,明确这是IPVS下线规则时候的一个bug,会导致新连接发送到已经下线的POD内。

解决方法

具体原因大家就看看官方issue吧:https://github.com/kubernetes/kubernetes/issues/81775

目前有2个解决方案:

  • 忍着,每次滚动发布都要报错,等待未来的官方方案。
  • 替换iptables方案。

我们选择了后者,因为涉及到HPA弹性的需求,我们不可能容忍每次伸缩都引发调用方超时。

iptables我们维护起来更加熟悉,它在service规模超过1000+的情况下才会出现性能下降,对我们来说也足够了。

其他影响不大的问题-1(不明显的问题,但可能帮助到大家的场景)

还是与conntrack有关,下面的选项需要生效到所有node:

/proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal=1

它令conntrack在跟踪TCP连接时对TCP滑动窗口的sequence校验宽松一些,否则TCP包乱序到达时conntrack会认为包超出了自己已知的窗口范围,会将包标记为INVALID,进而导致被kubernetes下发的一条INVALID DROP规则丢弃,这样会引发调用方超时重传。

大家感兴趣可以看一下官方说明:https://kubernetes.io/blog/2019/03/29/kube-proxy-subtleties-debugging-an-intermittent-connection-reset/

其他影响不大的问题-2(不明显的问题,但可能帮助到大家的场景)

ucloud实现的CNI在POD里下发了一条没有用的SNAT规则,这将会触发POD内conntrack机制,导致POD内也要面临conntrack性能问题:

WechatIMG1.png

我们目前是通过privileged特权的init-container,在POD启动之前执行了iptables -t nat -F删除了该规则,后续ucloud也会修正这个历史遗留问题。

上面讨论了那么多问题,最终其实就是几行优化参数,吃快餐的同学可以直接拿走。

node调参

node瓶颈是conntrack,它跟踪所有流量,但自身又不处理协议栈:

# conntrack优化
net.netfilter.nf_conntrack_tcp_be_liberal = 1
net.netfilter.nf_conntrack_tcp_loose = 1
net.netfilter.nf_conntrack_max = 3200000
net.netfilter.nf_conntrack_buckets = 1600512
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30

pod调参

pod内conntrack不开启,主要瓶颈在TCP协议栈处理短连接部分:

# socket buffer优化(好像意义不大)
net.ipv4.tcp_wmem = 4096        16384   4194304
net.ipv4.tcp_rmem = 4096        87380   6291456
net.ipv4.tcp_mem = 381462       508616  762924
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# timewait相关优化
net.ipv4.tcp_max_tw_buckets = 131072 # 这个优化意义不大
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1 # 仅对客户端有效果,可以复用TIME_WAIT端口
net.ipv4.tcp_tw_recycle=0 # 仅存在低版本内核中,需要关闭,因为在NAT变换IP的场景下用时间戳做校验会有回退问题,需禁用
net.ipv4.ip_local_port_range="5120 65000" # 端口范围
net.ipv4.tcp_fin_timeout=30 # 缩短TIME_WAIT时间,加速端口回收
# 握手队列相关优化
net.ipv4.tcp_max_syn_backlog = 10240
net.core.somaxconn = 10240
net.ipv4.tcp_syncookies = 1

一键node/port通用

如果想快速验证一下所有参数,在node以及privileged的POD内生效如下命令即可:

#!/bin/bash
sysctl -w net.netfilter.nf_conntrack_tcp_be_liberal=1
sysctl -w net.netfilter.nf_conntrack_tcp_loose=1
sysctl -w net.netfilter.nf_conntrack_max=3200000
sysctl -w net.netfilter.nf_conntrack_buckets=1600512
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
sysctl -w net.ipv4.tcp_timestamps=1
sysctl -w net.ipv4.tcp_tw_reuse = 1
sysctl -w net.ipv4.tcp_tw_recycle=0 # 高版本内核已经删除了该垃圾选项
sysctl -w net.ipv4.ip_local_port_range="5120 65000"
net.ipv4.tcp_fin_timeout=30
sysctl -w net.ipv4.tcp_max_syn_backlog=10240
sysctl -w net.core.somaxconn=10240
sysctl -w net.ipv4.tcp_syncookies=1

用到的工具

输出conntrack INVALID日志

生效如下命令:

iptables -t mangle -A FORWARD -m conntrack --ctstate INVALID -j LOG --log-prefix 'FORWARD -> ' --log-level=debug --log-tcp-sequence --log-tcp-options --log-ip-options
iptables -t mangle -A INPUT -m conntrack --ctstate INVALID -j LOG --log-prefix 'INPUT -> ' --log-level=debug --log-tcp-sequence --log-tcp-options --log-ip-options
iptables -t mangle -A OUTPUT -m conntrack --ctstate INVALID -j LOG --log-prefix 'OUTPUT -> ' --log-level=debug --log-tcp-sequence --log-tcp-options --log-ip-options
iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j LOG --log-prefix 'PREROUTING -> ' --log-level=debug --log-tcp-sequence --log-tcp-options --log-ip-options
iptables -t mangle -A POSTROUTING -m conntrack --ctstate INVALID -j LOG --log-prefix 'POSTROUTING -> ' --log-level=debug --log-tcp-sequence --log-tcp-options --log-ip-options

观察dmesg。

netperf压测

服务端启动命令(会启动到后台,会打印一条warinng日志没关系):

netserver

客户端短连接压测(-l持续秒数,-m请求应答的大小):

netperf -t TCP_CRR -H 目标服务器 -l 1200 — -m50,100 &

需要启动多个netperf客户端到后台,每一个客户端会令netserver服务端启动一个独立端口,避免单个TCP监听队列的瓶颈问题,从而可以试探出整机的TCP短连接极限。

随便想了一些常用的命令:

  • netstat -s
  • conntrack -S
  • sar -n ETCP 1
  • sar -n DEV 1
  • ifconfig
  • tcpdump
  • netperf
  • iptables
  • vmstat
  • iostat
  • iotop
  • netstat -tanlp

问题遇到的越早越好,如果你没有遇到问题,说明你的问题更大。

如果文章帮助了你,请帮我点击1次谷歌广告,或者微信赞助1元钱,感谢!

mm_reward_qrcode_1545359795775-2.png

知识星球有更多干货内容,对我认可欢迎加入:

WechatIMG1-2.png

本条目发布于2020年3月6日。属于k8s分类。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK