生產環境k8s偶發超時問題排查及解決

前言: 凡是有明確報錯的問題,都是能很快解決的,真正難以解決和排查的,是偶發且籠統報錯的問題。 這裏記錄整個解決的過程,期間有走過彎路,有思維侷限,但慶幸最終找到了原因,正常把我們系統上線到 k8s 平臺了。

 

問題表現:

  生產某套應用訪問時,偶爾會報 timed out 。相同的配置在 開發、測試、預生產都能正常運行。

 

 排查思路:

   1、 首先,因爲這個問題是偶發性的,因此這個問題很可能是由於某部分服務器網絡不通暢導致;

   2、 由於開發、測試、預生產是相同的 k8s yaml 文件,因此排除因爲部署導致該問題的可能;

   3、 不排除由於生產環境 k8s 平臺本身導致該問題的可能,因爲在平臺上運行的另一個系統在當月 12 日也發生過超時問題。


 針對第一點,我通過 以下方法進行監控:

1、 shell 腳本 for 循環ping集羣各個節點IP,驗證集羣網絡的穩定性;

#!/bin/bash
for ((i=0;i<=43200;i++)); do
sleep 2

time=$(date "+%Y-%m-%d %H:%M:%S")

echo $time >> /app/test/xx3.txt
echo $time >> /app/test/xx4.txt
echo $time >> /app/test/xx5.txt
echo $time >> /app/test/xx6.txt
echo $time >> /app/test/xx7.txt
echo $time >> /app/test/xx8.txt
echo $time >> /app/test/xx9.txt
echo $time >> /app/test/xx0.txt
echo $time >> /app/test/xx1.txt
echo $time >> /app/test/xx6.txt
echo $time >> /app/test/xx7.txt

ping -c1 -w2 10.28.x.xx3 >> /app/test/xx3.txt
ping -c1 -w2 10.28.x.xx4 >> /app/test/xx4.txt
ping -c1 -w2 10.28.x.xx5 >> /app/test/xx15.txt
ping -c1 -w2 10.28.x.xx6 >> /app/test/xx6.txt
ping -c1 -w2 10.28.x.xx7 >> /app/test/xx7.txt
ping -c1 -w2 10.28.x.xx8 >> /app/test/xx8.txt
ping -c1 -w2 10.28.x.xx9 >> /app/test/xx9.txt
ping -c1 -w2 10.28.x.xx0 >> /app/test/xx0.txt
ping -c1 -w2 10.28.x.xx1 >> /app/test/xx1.txt
ping -c1 -w2 10.28.x.xx6 >> /app/test/xx6.txt
ping -c1 -w2 10.28.x.xx7 >> /app/test/xx7.txt

echo "\n" >> /app/test/xx3.txt
echo "\n" >> /app/test/xx4.txt
echo "\n" >> /app/test/xx5.txt
echo "\n" >> /app/test/xx6.txt
echo "\n" >> /app/test/xx7.txt
echo "\n" >> /app/test/xx8.txt
echo "\n" >> /app/test/xx9.txt
echo "\n" >> /app/test/xx0.txt
echo "\n" >> /app/test/xx1.txt
echo "\n" >> /app/test/xx6.txt
echo "\n" >> /app/test/xx7.txt
done

腳本中的幾個IP是我需要部署應用所使用到的主節點及其物理機IP,每兩秒ping所有地址,將結果記錄到txt文檔中,因爲我遇到的網絡timed out 時間比較長,大概有幾十秒沒有響應,因此我統計各個IP對應的txt文檔中,零點幾秒的記錄和總數做對比,來確定超時的請求數量。

當然有更好的腳本可以實現監控網絡,我這裏有點偷懶,隨便寫的,大家隨便參考。

實際的監控結果是,集羣內部物理機之間網絡很穩定。

 

針對第三點,結合當天發生超時的日誌,發現是由於服務重啓時,域名緩存導致。

具體原因如下:

1、 前端通過nginx進行發佈並跳轉後端應用,後端應用的域名使用 k8s 內部域名;

2、後端應用刪除了svc,並更新了內部域名對用的 ClusterIP;

3、 nginx中緩存的內部域名記錄的還是老 ClusterIP ,導致訪問 timed out;

針對這一點,我們優化了發佈應用的流程及腳本解決了。

 

解決以上兩點問題後,決定重新上線看是否還會出現超時的問題,結果發現超時的問題還是時有發生。

在沒有找到其他問題的情況下,我在想是否是集羣本身出現了問題:

查看kubelet的日誌,發現了以下報錯:

 W0701 15:05:59.697391    9931 watcher.go:87] Error while processing event ("/sys/fs/cgroup/devices/libcontainer_34389_systemd_test_default.slice": 0x40000100 == IN_CREATE|IN_ISDIR): inotify_add_watch /sys/fs/cgroup/devices/libcontainer_34389_systemd_test_default.slice: no such file or directory

該問題是由於docker的引擎與k8s的引擎不一致導致,解決辦法參考我的這一片博客:

《修復由於docker、k8s的引擎不一致導致的報錯: 調整爲cgroups》

https://blog.csdn.net/Jerry_Pan1990/article/details/103233485

問題解決後,kubelet不報錯了,但是超時的問題還是繼續,當時的心情真實崩潰的,上線的時間馬上到了,急地我嘴角長泡。

 

遇到問題,還是得冷靜下來,重新分析問題:

既然當前條件已經沒有新的已知條件了,那麼爲什麼不引入新的變量進行觀察?

我將另外一個系統遷移到這個k8s環境進行驗證,發現該系統運行竟然是良好的!!!

那麼說明什麼問題呢?

k8s環境是良好的,至少對於新引入的系統是這樣的。

但另一個問題就是:爲什麼對原系統來說,會偶發timed out 的問題?需要知道 timed out 就是網絡超時導致的。爲什麼有時候可以網絡通暢,有時候又不通?超時的觸發條件是什麼?

在這裏我又一次走了彎路,當時我在想會不會是coredns導致?

查看 coredns 日誌沒有發現異常。

因此我又在超時的調用者 A 容器中,添加了 新的監控,監控 curl B-service 的某個接口,查看是否出現了超時,結果是完全正常!!!  但是調用另外一個接口就會出現超時的情況。

到這裏,可以確定,超時只是出現在程序中某些應用某部分接口。

 

叫開發同學來一起看,他們完全沒有頭緒,只是告訴我代碼是一樣的,好吧,還是得我來搞定。

沒辦法,我就在想,能否進行抓包來分析?

第一步當然是安裝tcpdump工具,可以參考我這篇文章:

《封裝一個帶有tcpdump工具的鏡像,在容器中使用tcp抓包》

https://blog.csdn.net/Jerry_Pan1990/article/details/103234441

 

抓包後,使用wireshark進行分析:

發生超時,會出現 TCP Retranmision 超時。

進一步分析得知,原來是應用訪問的數據庫在 6 網段,而我的k8s集羣部署在 8 網段,

在建立數據庫連接時,應用的jdbc會進行tcp握手,具體的網絡路由如下:

容器內應用 ---> 宿主機物理網卡 (暢通)

宿主機物理網卡 ----> 數據庫IP:8066 (偶爾阻塞)

物理機發送tcp連接時,使用的是動態端口是通過如下文件指定的:

vi /proc/sys/net/ipv4/ip_local_port_range

 

而網絡上 8 網段物理機 到 6 網段物理機 部分端口是沒有開通入站規則的。

這就導致在 32768 - 60999 動態端口範圍內,如果剛好落在開通的端口範圍內,則可以訪問通暢,如果落在未開通的端口範圍,則會出現數據連接超時,從而導致應用訪問超時。

解決方法:

   調整 ip_local_port_range 到指定開通的端口範圍;

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章