問題背景:總有很少部分租戶稱他們的某個業務部署在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