K8S – 優化dns解析時間


本篇博客記錄在實施K8S過程中遇到的dns解析慢和不穩定問題。

 

背景

服務上線K8S后,通過調用鏈trace發現接口95線響應時間惡化10倍以上,於是開始排查。

 

明確問題方向

從調用鏈trace系統,很容易看出接口的哪一個網絡請求拖慢了響應時間。

但是發現無論是http調用、mysql、redis的響應時間都嚴重變慢,所以懷疑是基礎層面的問題引起,因此有2個方向:

  • 虛擬化網絡慢
  • DNS解析慢

為了確定到底是哪個原因,最好是通過工具客觀分析,拿數據說話。

登錄到container內,創建如下的一個文件:

然后利用curl請求目標域名,就可以得到處理各個階段的耗時情況:

多執行幾次,會出現響應時間糟糕的情況,數據如下:

curl的展示策略是累計時間,因此可以看出dns查詢就占掉了0.124686秒,整個請求的總時間才0.146876,並且connect時間幾乎為0。

下面是響應時間正常的情況:

因此可以判定就是dns解析慢引起的,而網絡因素則可能性很低。

 

分析具體原因

K8S集群並沒有什么壓力,請求的域名IP是直接配置在coredns里的,理論上應該幾毫秒就返回結果的,那么是什么導致了偶爾的100+毫秒解析時間呢?

所以我在container內開啟了tcpdump抓包,監聽/etc/resolve.conf中的nameserver地址(其實就是coredns的service ip)的流量,同時通過上述curl命令發起請求,觀察耗時長的原因。

 透過tcpdump抓包發現,每一次curl請求都發出了2個DNS query,一個是A記錄,另外一個是AAAA記錄,也就是同時請求了IPV4和IPV6地址。

IPV4很快就返回了結果,而IPV6則經常花費上百毫秒時間,且最終返回NXDomain無IP結果。

這里有2個問題:

  • 為什么curl會同時請求IPV4和IPV6呢?實際上我們只有IPV4地址。
  • 為什么coredns響應IPV6這么慢呢?

第2個問題很容易回答,因為在coredns里我們只配置了對應的IPV4解析,而IPV6請求會被forward到upstream的DNS(在我這里就是公網DNS),所以IPV6的響應時間就不穩定了。

關於第1個問題,經過谷歌搜索后明確了原因,主要是因為curl走的是glibc的gethostbyname調用來解析域名,而這個函數默認是同時發出ipv4和ipv6請求的:

它不像后來linux推出的getaddrinfo函數,可以指定具體IPV4還是IPV4:

這些就不具體說明了。

總之,現在問題明確了,就是因為glibc發起了IPV6的請求,而IPV6地址我們沒有配置在coredns中所以請求被upstream到外網解析,從而導致了慢查詢。

 

優化方法

一共有3個工作要做,下面依次列出。

 

下掉ipv6內核模塊

glibc之所以發起ipv6查詢,其原因是kernel開啟了ipv6模塊導致的。

因為docker共享的是宿主機的linux kernel,所以我們需要在宿主機上關閉ipv6內核模塊,才能徹底禁用ipv6解析的行為。

做法如下:

 

在grud中配置ipv6.disable=1可以達到下線ipv6解析的效果,改后需要重啟宿主機。

該效果已得到驗證,還有一些其他選項應該不是必須的,大家可以酌情參考:https://blog.csdn.net/cjm712/article/details/87886614


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM