vmware 搭建k8s无法ping通子节点_一波四折 —— 记一次K8S集群应用故障排查
一個周四的下午,客戶的報障打破了微信群的平靜。
“我們部署在自建K8S集群上的應(yīng)用突然無法正常訪問了,現(xiàn)在業(yè)務(wù)受到了影響!”
收到客戶的報障,我們立刻響應(yīng),向客戶了解了問題現(xiàn)象和具體報錯信息。
客戶反饋K8S集群部署在云主機上,K8S的應(yīng)用pod example-app通過訪問外部域名example-api.com調(diào)用接口,同時訪問云數(shù)據(jù)庫做數(shù)據(jù)查詢后將結(jié)果返回客戶端。客戶排查應(yīng)用pod日志,日志中有如下報錯:
可以看到最關(guān)鍵的信息是Name or service not known。該報錯一般為域名無法解析導(dǎo)致的。
由于客戶的應(yīng)用pod只訪問example-api.com這一個外部域名,因此判斷應(yīng)該是pod解析該域名時出現(xiàn)異常。為了進一步驗證,我們執(zhí)行kubectl exec -it example-app /bin/sh命令進入pod內(nèi)執(zhí)行ping example-api.com命令,果然出現(xiàn)了相同的報錯。
因此可以確認應(yīng)用日志中的報錯是域名解析失敗導(dǎo)致的。
執(zhí)行kubectl get pod example-app -o yaml|grep dnsPolicy查看pod的dns策略,是ClusterFirst模式,也就是pod使用K8S集群的kube-dns服務(wù)做域名解析。
執(zhí)行命令kubectl get svc kube-dns -n kube-system,確認kube-dns服務(wù)的clusterIP是192.168.0.10 查看pod內(nèi)的/etc/resolv.conf文件,nameserver設(shè)置的正是該IP。再執(zhí)行kubectl describe svc kube-dns -n kube-system|grep Endpoints,可以看到dns服務(wù)關(guān)聯(lián)了一個coredns pod作為后端。
執(zhí)行kubectl get pods -n kube-system|grep coredns看到kube-dns關(guān)聯(lián)的coredns pod處于running狀態(tài)。
再執(zhí)行kubectl logs coredns –n kube-system,看到pod日志中有大量和客戶配置的外部dns服務(wù)器IP地址通訊超時的報錯。
10.16.16.16和172.16.16.16為客戶自建DNS服務(wù)器的IP地址
。為了確認是否是DNS服務(wù)器有問題,我們在example-app pod中分別執(zhí)行nslookup example-api.com 10.16.16.16和nslookup example-api.com 172.16.16.16,均能解析出正確的IP地址。
因此判斷問題應(yīng)該出在coredns pod上。此時我們發(fā)現(xiàn),coredns pod的狀態(tài)變成了crashloobbackoff,稍后又變成了running。
觀察一段時間后發(fā)現(xiàn)pod在這兩個狀態(tài)之間反復(fù)切換。鑒于整個集群只有一個coredns pod,我們修改了coredns的deploy,將pod副本數(shù)調(diào)至2,新擴的pod一直處于running狀態(tài),pod日志中也沒有出現(xiàn)和10.16.16.16、172.16.16.16的通信超時的報錯。而此時example-app pod也可以正常解析域名了!可以確認之前是集群唯一的coredns pod狀態(tài)異常導(dǎo)致集群DNS服務(wù)不可用。
那么coredns pod為什么會出現(xiàn)異常呢?
再次查看異常的pod日志,發(fā)現(xiàn)除了和外部DNS服務(wù)器有通訊超時的記錄,還有和集群api-server通訊超時的記錄。因此有必要懷疑是pod所處的網(wǎng)絡(luò)有問題。在客戶的K8S集群網(wǎng)絡(luò)規(guī)劃中,pod使用和集群node不同的子網(wǎng)通訊。通過在K8S節(jié)點云主機上綁定pod子網(wǎng)的彈性網(wǎng)卡,在網(wǎng)卡上給節(jié)點的pod在pod子網(wǎng)中分配IP,實現(xiàn)pod的網(wǎng)絡(luò)可達。
由于example-app pod是可以與外部通訊的,因此pod子網(wǎng)層面是沒有問題的。我們將焦點移至coredns pod使用的彈性網(wǎng)卡上。彈性網(wǎng)卡在節(jié)點云主機操作系統(tǒng)中的設(shè)備名是eth1,pod子網(wǎng)網(wǎng)關(guān)是10.176.96.1在節(jié)點上執(zhí)行ping -I eth1 10.176.96.1,結(jié)果如圖:
可見云主機無法通過eth1 ping通子網(wǎng)網(wǎng)關(guān),而且找不到eth1設(shè)備。執(zhí)行ifconfig命令發(fā)現(xiàn)eth1設(shè)備沒有被系統(tǒng)識別到。而彈性網(wǎng)卡底層是被正常掛載到云主機上的。
手動執(zhí)行echo 1 > /sys/bus/pci/rescan命令重新掃描彈性網(wǎng)卡,發(fā)現(xiàn)eth1出現(xiàn)了,此時執(zhí)行ping -I eth1 10.176.96.1也可以ping通了!而異常的coredns pod也恢復(fù)了正常。判斷之前應(yīng)該是系統(tǒng)異常導(dǎo)致的網(wǎng)卡沒有被識別到導(dǎo)致。
通過這一問題也提醒我們?nèi)绻盒枰褂胟ube-dns服務(wù),coredns的pod一定要配置多副本,以免單個pod異常導(dǎo)致集群DNS不可用。
Part2?一波剛平一波又起域名解析的問題解決,本以為已經(jīng)結(jié)案,誰知新的問題接踵而來。客戶調(diào)用應(yīng)用,不再報錯域名解析失敗。但是仍然不能正常返回結(jié)果。排查應(yīng)用日志,報錯如下:
通過報錯判斷是應(yīng)用pod連接云數(shù)據(jù)庫超時導(dǎo)致。排查云數(shù)據(jù)庫所在子網(wǎng)的路由、ACL和白名單設(shè)置,均無異常。連接pod后可以ping通數(shù)據(jù)庫域名,判斷pod與數(shù)據(jù)庫的網(wǎng)絡(luò)鏈路是正常的。但是pod內(nèi)無法telnet通數(shù)據(jù)庫域名的3306端口,判斷這就是導(dǎo)致連接數(shù)據(jù)庫超時的原因了!
排查pod內(nèi)的防火墻,沒有開啟。pod所在的子網(wǎng)ACL,沒有限制。表面的分析沒有任何線索,于是只能祭出網(wǎng)絡(luò)問題排查的經(jīng)典手段——tcpdump抓包!
由于pod內(nèi)的容器一般CPU、內(nèi)存、網(wǎng)絡(luò)資源和存儲空間有限,在pod內(nèi)抓包會占用大量資源和存儲空間,抓包結(jié)束后數(shù)據(jù)包取出也比較繁瑣。而且有的容器鏡像是無法安裝tcpdump工具的。所以通常我們不會在容器內(nèi)抓包。
基于K8S集群的網(wǎng)絡(luò)架構(gòu),pod的網(wǎng)絡(luò)通訊是通過所在節(jié)點云主機的輔助彈性網(wǎng)卡收發(fā)數(shù)據(jù)的。因此我們只要在pod所在節(jié)點云主機上對相應(yīng)的網(wǎng)卡進行抓包即可。
在客戶的場景下,應(yīng)用pod使用所在節(jié)點的eth1網(wǎng)卡,所以pod telnet云數(shù)據(jù)庫的3306端口時,我們直接在節(jié)點上抓取eth1網(wǎng)卡上與云數(shù)據(jù)庫IP交互的數(shù)據(jù)包即可。
pod的IP是10.176.98.29,云數(shù)據(jù)庫的IP是10.176.46.4。在pod的容器內(nèi)執(zhí)行telnet 10.176.46.4 3306,同時在節(jié)點上執(zhí)行tcpdump -i eth1 host 10.176.46.4 -w /tmp/mysql.cap。pod內(nèi)telnet超時后,我們結(jié)束抓包,將cap文件取出后發(fā)現(xiàn)居然一片空白,一個包都沒有抓到!
這不科學(xué)!
之前pod內(nèi)可以ping通云數(shù)據(jù)庫,說明一定有數(shù)據(jù)包從pod所在云主機發(fā)出并收到了回包。為了驗證pod telnet請求的包是否正常發(fā)出,我們干脆不把抓包范圍局限在eth1網(wǎng)卡,而是使用tcpdump -i any host 10.176.46.4 -w /tmp/mysql.cap對云主機所有網(wǎng)絡(luò)接口抓包。這次終于抓到了數(shù)據(jù)包,發(fā)現(xiàn)telnet發(fā)出后,沒有收到數(shù)據(jù)庫的任何回包。
在telnet的同時,集群中有其他pod可以正常連接云數(shù)據(jù)庫,所以因為云數(shù)據(jù)庫側(cè)異常導(dǎo)致沒有回包的可能性不大。云主機可以和外界通訊的網(wǎng)卡只有eth0和eth1,莫非……為了驗證我們的猜想,在telnet時,節(jié)點上執(zhí)行tcpdump -i eth0 host 10.176.46.4,果然看到了pod發(fā)出的到云數(shù)據(jù)庫的數(shù)據(jù)包!
所以pod 容器telnet不通云數(shù)據(jù)庫3306端口的原因也真相大白了。因為pod telnet云數(shù)據(jù)庫的數(shù)據(jù)包沒有走eth1,而是走了eth0,數(shù)據(jù)包發(fā)送至云數(shù)據(jù)庫后,云數(shù)據(jù)庫的回包發(fā)給了pod的子網(wǎng)網(wǎng)關(guān)。
SDN網(wǎng)絡(luò)OVS判斷來包是從node子網(wǎng)網(wǎng)關(guān)發(fā)出(eth0),而回包卻是發(fā)往pod子網(wǎng)(eth1)源和目的地址不一致,因此將數(shù)據(jù)包丟棄。pod也就無法收到數(shù)據(jù)庫的回包了。之前可以ping通是因為ICMP協(xié)議是代答的,即使源和目的地址不一致,也可以正常收到回包。
那么,pod的所有網(wǎng)絡(luò)請求正常是應(yīng)該通過云主機上的輔助網(wǎng)卡收發(fā)的,為什么走了云主機主網(wǎng)卡了呢?正常的K8S集群節(jié)點上配置了table 2路由規(guī)則,定義了pod的網(wǎng)絡(luò)請求默認路由的下一跳是pod子網(wǎng)網(wǎng)關(guān),并且走輔助網(wǎng)卡,如下圖所示:
而在客戶的應(yīng)用pod所在節(jié)點執(zhí)行ip r show table 2,我們看到的結(jié)果和第一次抓包一樣,空空如也。。。
路由是由K8S集群的網(wǎng)絡(luò)插件維護,路由缺失問題在網(wǎng)絡(luò)插件日志中沒有發(fā)現(xiàn)任何線索,具體原因不得而知。當(dāng)務(wù)之急是修復(fù)問題。
可以通過重啟ipamd容器恢復(fù)table 2路由。
執(zhí)行docker ps | grep ipamd | grep sh找到ipamd的容器ID。
然后執(zhí)行docker restart 容器ID重啟容器。
再次執(zhí)行ip r show table 2,終于看到了路由規(guī)則!
Finally,此時在應(yīng)用pod內(nèi)測試可以telnet通云數(shù)據(jù)庫的3306端口。客戶的應(yīng)用調(diào)用也終于可以成功返回結(jié)果。
然鵝,如果各位看官覺得這個case到這里就結(jié)束了,那就和當(dāng)時排障的攻城獅一樣圖樣圖森破了。
Part3慢=不可用
就在攻城獅以為一切都恢復(fù)正常時,客戶的追加反饋表明這個問題只是進入了下一個階段。
客戶反饋應(yīng)用雖然可以正常調(diào)用,但是一次調(diào)用要超過一分鐘才能有返回結(jié)果,之前正常的速度是僅需幾秒就可以返回結(jié)果。現(xiàn)在這樣的速度完全不能滿足業(yè)務(wù)要求,相當(dāng)于還是不可用的。
問題尚未解決,攻城獅仍需努力!
分析應(yīng)用調(diào)用返回慢的問題,一是著眼于應(yīng)用流程的各個環(huán)節(jié),如客戶端,服務(wù)端對業(yè)務(wù)請求的處理時間,另外一個就是排查數(shù)據(jù)傳輸鏈路是否有延遲。在客戶的場景下,就是確認pod和云數(shù)據(jù)庫在處理請求上是否有瓶頸,還有就是pod到云數(shù)據(jù)庫之間的網(wǎng)絡(luò)傳輸是否有延遲。在pod內(nèi)ping云數(shù)據(jù)庫IP,沒有超時丟包,延遲很低。
要想確認pod和云數(shù)據(jù)庫在處理請求時的時長,還是要依靠tcpdump工具抓包分析。于是我們在pod對數(shù)據(jù)庫發(fā)起一次完整的請求過程中,依然使用tcpdump -i eth1 host 10.176.46.4 -w /tmp/mysql.cap命令在pod所在節(jié)點抓包。將數(shù)據(jù)包取出后分析發(fā)現(xiàn),一次完整的業(yè)務(wù)請求,pod會對數(shù)據(jù)庫做13次查詢。對比第一次查詢和最后一次查詢的時間,如圖所示:
可以發(fā)現(xiàn)13次請求用了1分鐘左右,與業(yè)務(wù)調(diào)用耗時吻合。排查云數(shù)據(jù)庫監(jiān)控,發(fā)現(xiàn)內(nèi)存
使用接近100%
同時實例慢查詢?nèi)罩局杏写罅柯齭ql記錄,可以看到幾乎每次查詢都耗時較長
可見如果業(yè)務(wù)調(diào)用的13次請求,每次都是慢查詢,耗時4秒左右,就會導(dǎo)致我們看到的完整請求耗時一分鐘左右。
因此判斷瓶頸應(yīng)該主要在云數(shù)據(jù)庫上,建議客戶對數(shù)據(jù)庫慢查詢進行優(yōu)化,降低內(nèi)存負載。然后觀察應(yīng)用調(diào)用時長是否恢復(fù)正常。
part4 問題的真相只有一個!
當(dāng)我們天真地以為優(yōu)化完數(shù)據(jù)庫慢查詢后,一切就都塵埃落定時。客戶的反饋幾乎讓人崩潰——優(yōu)化慢查詢后,數(shù)據(jù)庫內(nèi)存使用已降至30%,慢日志中也幾乎沒有慢sql記錄。而應(yīng)用的調(diào)用時長仍然沒有縮短!
一定還有哪個環(huán)節(jié)有疏漏。
為了完整了解應(yīng)用pod在應(yīng)用調(diào)用過程中都產(chǎn)生了哪些數(shù)據(jù)交互,我們決定再次抓包分析,但焦點不再集中在云數(shù)據(jù)庫上,而是以pod維度進行抓包。使用tcpdump -i eth1 host -w /tmp/app.cap命令在pod所在節(jié)點抓取所有和pod相關(guān)的包,分析數(shù)據(jù)包后果然有了新的發(fā)現(xiàn):pod與100.64.249.132這個地址有文件傳輸交互。
查看數(shù)據(jù)包詳細數(shù)據(jù)發(fā)現(xiàn)這個地址是OSS對象存儲解析到的域名!pod還會與oss傳輸文件這個重要環(huán)節(jié)在此前是不知道的,客戶也沒有主動告知。
這也提醒我們在分析應(yīng)用問題時,務(wù)必要搞清完整的業(yè)務(wù)調(diào)用流程,應(yīng)用架構(gòu)和涉及到的產(chǎn)品環(huán)節(jié),否則擠牙膏似的信息輸出和被問題現(xiàn)象牽著鼻子走,會浪費大量時間,甚至嚴重阻礙問題排查。
我們在pod內(nèi)測試ping 100.64.249.132,延時非常感人。
與客戶確認,客戶反饋OSS域名解析的IP貌似不對。在業(yè)務(wù)架構(gòu)規(guī)劃時,為了保證客戶pod與oss的網(wǎng)絡(luò)性能,配置了通過專線連接oss。當(dāng)前解析的IP沒有走專線網(wǎng)段,而是走了普通的網(wǎng)段,無法滿足性能要求。正常走專線的域名解析IP應(yīng)該是10.219.226.2。
但是域名解析為什么會出現(xiàn)問題呢?
各位童鞋是否還記得part1中我們提到客戶的pod使用的是kube-dns提供的dns解析,而kube-dns配置的上游服務(wù)器是客戶自建的dns服務(wù)器?經(jīng)過客戶測試發(fā)現(xiàn),自建dns服務(wù)器對oss域名的解析就是100.64.249.132。應(yīng)該是近期客戶側(cè)維護dns服務(wù)器的時候誤操作修改了解析導(dǎo)致的。。。將自建dns服務(wù)器的域名解析地址修改回正確地址后。再次在pod內(nèi)測試,結(jié)果如下:
再次測試應(yīng)用調(diào)用,終于恢復(fù)到了正常的時長!可喜可賀!
?至此客戶的問題卍解,總結(jié)問題排查過程,有幾點值得分享:
1、? k8s集群如果使用kube-dns服務(wù),coredns pod務(wù)必配置多副本,避免單點故障導(dǎo)致集群dns服務(wù)不可用。
2、? 排查K8S集群pod網(wǎng)絡(luò)問題時,可以在pod所在節(jié)點抓取pod使用的輔助網(wǎng)卡的相應(yīng)網(wǎng)絡(luò)數(shù)據(jù)包,避免直接在pod內(nèi)抓包。
3、? 應(yīng)用系統(tǒng)性能排查涉及到各個節(jié)點設(shè)備和網(wǎng)絡(luò)傳輸,務(wù)必了解清楚完整的系統(tǒng)架構(gòu),調(diào)用流程,再針對涉及的每個環(huán)節(jié)逐一分析。
以上就是一次“波折”的K8S應(yīng)用問題排查過程,感謝各位童鞋閱讀,如果能夠?qū)Υ蠹矣兴鶐椭?#xff0c;歡迎點贊轉(zhuǎn)發(fā)評論。關(guān)注我們的公眾號,更多精彩內(nèi)容會持續(xù)放送!
總結(jié)
以上是生活随笔為你收集整理的vmware 搭建k8s无法ping通子节点_一波四折 —— 记一次K8S集群应用故障排查的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java大牛的一些总结,献给对未来还在迷
- 下一篇: 什么人适合学习Java编程?编程好学吗?