问题背景:总有很少部分租户称他们的某个业务部署在Kubernetes容器平台后经常会重启,也很少部分租户称某个业务在运行一段时间时会产生大量的`CLOSE-WAIT`,还有租户反馈说某个业务跑着就会hang住。刚开始我们都会让业务开发者先自己找问题,因为这些租户反映的只是偶偶发生,大多数租户没有反映类似问题,我们会理所当然的认为是租户业务自身问题,而非平台问题。当然大多数情况下,还是租户业务本身程序没有写好,或者健康检查配置不当等引起。
分析过程:
一、排除干扰项
分析完了问题,一般会根据经验先从比较简单的可能产生的影响因素开始排除干扰选项,这样我们大概就会有一个比较接近问题根因的方向。比如上面三个问题中的其中一个 "容器内出现大量处于`CLOSE_WAIT`状态的TCP链接":
“CLOSE-WAIT”有很多原因引起,有可能是
1、服务端代码处理TCP挥手不合理引起,比如忘记了close相运维管理岗岗位学习教程应的socket连接,那么自然不会发出FIN包;
2、出现死循环之类的问题,导致close最后没有被调用执行;
3、服务端程序响应过慢,或者存在耗时逻辑,导致close延后;
4、accept的backlog设置的太大,导致服务端来不及消费的情况,引起多余的请求还在队列里就被对方关闭了。
5、内核参数配置没有做优化处理,比如调整“tcp\_keepalive\_time” / “tcp\_keepalive\_intvl” / “tcp\_keepalive\_probes”等。林林总总,但经过我们排查后,以上的可能影响点都不是,所以排除上述这些干扰选项。
二、结合“业务方”与“平台方”
“业务方”——从如下几个方向进行了代码方面的排查:
1、多次检查TCP四次挥手代码逻辑;
2、检查 springboot的相关配置是否恰当;
3、由于连接数过多,也排查了tomcat线程池相关代码;
4、修改ActiveMQ连接池的配置;
5、采用jstack、jmap查看应用的线程堆栈,确定程序没有死锁,只看到少量线程在 block和wait状态;
6、采用jstack-gcutil查看java垃圾回收时间,因为其可能会引起垃圾回收异常等;
以上发现都是正常的,无果。
“平台方”——尝试过以下排查:
1、修改Kubernetes node主机的内核相关配置(比如:tcp keepalived相关参数,ulimit限制数等);
2、检查Kubernetes Ingress入口Nginx的配置(比如:Kubernetes Nginx的超时配置与业务自身Nginx的超时时间减少些,比如900秒;改用NodePort模式不经过Nginx代理等),发现同样有问题,这个就排除采用 Nginx代理引起,也就排除了Nginx参数配置问题;
3、排查docker分区的文件系统,排除容器底层导致;
4、查看dockerd日志和系统日志;
5、还有各种其他可能的方面都尝试过等等;
参考资料:https://mp.weixin.qq.com/s/4SgBPE9lWheCNxEASFhF9A