前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个 K8s 网络延迟排查与优化实战案例

一个 K8s 网络延迟排查与优化实战案例

作者头像
我是阳明
发布2024-06-26 12:30:19
1810
发布2024-06-26 12:30:19
举报
文章被收录于专栏:k8s技术圈k8s技术圈

在Kubernetes环境中,网络性能和稳定性对于确保服务的正常运行至关重要。然而,conntrack问题常常被忽视,导致网络连接异常,从而影响应用的正常运行。本文通过一个实际案例,详细介绍了如何发现和解决Kubernetes环境中的conntrack问题,以引起大家对这一问题的重视。

01、背 景

这是早前的一个案例,那时候随着微服务数量的增加和请求量的上涨,我们当时从监控注意到业务高峰时线上接口的慢请求越来越多,原本毫秒级响应的接口偶尔会出现请求延迟超过1秒的现象,严重影响了用户体验。为了解决这一问题,我们在非生产环境通过压测工具进行复现,如下是具体排查和优化过程。

02、请求链路

当时采用的是nginx作为流量网关反向代理微服务网关,微服务和其网关跑在k8s集群上,微服务网关通过NodePort的形式暴露,为了方便问题复现和排查,我们把复现环境的Pod设置为单副本,访问链路大致如下。

03、排查与分析过程

1、起初怀疑是节点带宽满了,经查看监控,流量都很正常,所以暂时排除;

2、查看skywalking调用链监控,发现这些请求都有一个共同点,在nginx upstream这个环节耗时较长,难道问题在nginx?

3、看了一下nginx的各项监控指标都很正常,远远没达到其性能瓶颈,那就抓个包呗?不抓还好,一抓下一跳,有大量的 TCP Retransmission(TCP 重传) ,插播知识点:

当发送方的 TCP 在一定时间内没有收到确认(ACK)响应时,会认为数据包可能丢失或未成功传输,因此会重新发送相同的数据包,这个过程称为 TCP 重传。简单来说,TCP 重传是为了确保数据可靠传输的一种机制。 在 Wireshark 中,你可以看到标记为 "TCP Retransmission" 的事件。这表示发送方多次发送了同一个序列号的数据包,因为之前的传输没有得到确认。每次重传,发送方都会等待一段时间,称为超时重传时间(RTO),如果还没有收到 ACK,就会再次发送数据包。 通过这种机制,TCP 能够确保数据即使在网络状况不佳时,也能最终到达目的地,保证了数据传输的可靠性。

4、抽一个看了下跟踪流(TCP Stream),可以看到这个请求与上游服务重传了大约1s才建立了连接,难怪nginx upstream耗时那么长了,好的,我们在找到原因后,我们需要继续探索这些请求为什么会发生TCP重传呢?让我们继续往下看。

5、为了搞清楚TCP重传的原因,我们需要分别在nginx、pod和pod所在的node节点上进行抓包,如下图,我们在pod的抓包结果中发现,pod侧没有收到第一个syn报文 ,所以猜测包可能是在node和pod之间丢了。

6、节点连接数满了?通过下面指令查看,连接数并不是很多,很正常。

代码语言:javascript
复制
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

7、难道是conntrack表满了?之所以想起conntrack,是因为NodePort模式在将报文转发给 Pod 的过程中,报文会经历五元组(源 IP、源端口、目的 IP、目的端口、协议)的转换。由于请求量较大,可能会撑爆conntrack表,果不其然,如下图,我们捕获到conntrack丢包和插入失败的信息,罪魁祸首终于找到了。

代码语言:javascript
复制
# 打印conntrack统计信息
conntrack -S
# 其实也可以通过`dmesg|grep conntrack`查看异常日志,但当时直接用的上面指令,所以没有截图

04、问题优化

好了,在确定根本问题后,优化和避免问题重复发生至关重要。以下是几种优化思路:

  1. 增加NodePort节点:在nginx的upstream中多挂几个NodePort节点分摊负载,这种方式改动最小。
  2. 修改service为LoadBalancer:将service的访问方式修改为LoadBalancer可以直接将流量引导到Pod,避免了通过NodePort和Node的转发,减少了五元组转换带来的瓶颈。
  3. 使用Ingress进行负载均衡:去掉nginx,使用Ingress进行service的负载均衡。

05、Q&A

Q1:conntrack的最大值是多少?

A1:conntrack的最大值(内核参数 net.netfilter.nf_conntrack_max )是根据kube-proxy配置的参数 --conntrack-max-per-core * 节点cpu核数进行计算的,假设 --conntrack-max-per-core的值设置为65536,节点有32核的CPU,则conntrack的最大值为65536 * 32 = 2097152,下图是kube-proxy官方的参数解释。

Q2:conntrack的最大值在哪里看?

A2:可以查看nf_conntrack_max文件,指令如下

代码语言:javascript
复制
cat /proc/sys/net/netfilter/nf_conntrack_max

Q3:conntrack的最大值如何修改?

A3:可以修改kube-proxy的启动参数,或者修改节点的内核参数,一般推荐后者,这是修改的方法

代码语言:javascript
复制
# 临时生效
sudo sysctl -w net.netfilter.nf_conntrack_max=2097152
# 永久生效
echo 'net.netfilter.nf_conntrack_max=2097152' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

06、总 结

conntrack监控真的太重要了,为了尽可能避免conntrack表满的情况,在高并发的场景建议使用ingress的方案,本期分享就到这里,谢谢!

参考链接:

https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/kube-proxy/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 k8s技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档