我们正在运行一个中型AWS EKS
集群(约 120 个kubelet
节点),主要运行Go
服务。集群中部署的服务非常繁忙,每小时处理数百万个调用。每个服务都kubelet
运行在同一版本的标准 Amazon Linux 上
Linux 4.14.203-156.332.amzn2.x86_64 #1 SMP Fri Oct 30 19:19:33 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
前段时间,我们在Grafana
仪表板上注意到,每个kubelet
节点TCP mem
(字节)随着时间的推移稳步增长,从未下降。
我们设法将这个问题归咎于一个单一但相当“庞大”(就代码库的大小而言)的Go
服务。我们现在定期回收此服务,同时寻找泄漏的原因。
我现在开始质疑我是否从主持人即Linux Kernel
PoV 的角度正确理解了这个问题,并想避免陷入幻想。
就我目前的理解,TCP
内存字节泄漏既可以发生在接收端,也可以发生在发送端。我怀疑这些字节是分配给套接字(内核中的某个位置)的,该套接字无限期保持打开状态,数据在某个地方排队,不会被“耗尽”。这是正确的,还是我在自欺欺人?
如果是,我有什么办法可以检查数据吗?我说的“检查”是指找到保存这些数据的套接字。
通过在主机端运行来追踪打开的套接字lsof
现在已经导致我可以跟进许多线索,但我注意到的一件事是,服务“内部”有很多套接字Pod
处于TIME_WAIT
状态,我认为这不应该是一个大问题,但只是为了确保我没有错过任何东西,我确实将其值降低tcp fin_timeout
到比默认设置低得多的值(60 秒 - > 10 秒)以更快地回收套接字。
现在,我明白这是我们的服务泄漏内存,但我正在寻找有关以下问题的一些答案:
- 我从内核角度思考这个问题是否正确,即是否是打开的套接字/FD 的缓冲区没有被清除(读/写)导致这个问题?
- 如果上述问题的答案是肯定的,那么在繁忙的服务器上,有什么方法可以判断或确定哪些套接字已分配但未清除缓冲区以及在哪一端(发送/接收)
谢谢