国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

18143453325 在線咨詢 在線咨詢
18143453325 在線咨詢
所在位置: 首頁 > 營銷資訊 > 建站知識 > 一次K8s中的Pod解析外網(wǎng)域名錯誤的問題排查

一次K8s中的Pod解析外網(wǎng)域名錯誤的問題排查

時間:2023-02-22 04:03:01 | 來源:建站知識

時間:2023-02-22 04:03:01 來源:建站知識

一次K8s中的Pod解析外網(wǎng)域名錯誤的問題排查:

1、故障現(xiàn)象

我們一個agent代理服務(wù),發(fā)布到k8s集群之后,pod狀態(tài)是Running,但是server一直無法收到心跳信號,因此到集群內(nèi)部去排查日志,發(fā)現(xiàn)該服務(wù)日志中出現(xiàn)大量的連接某一個ip地址tcp timeout

2、故障排查過程

通過查看日志發(fā)現(xiàn)是大量的錯誤日志,連接某個ip地址產(chǎn)生i/o timeout,因此排查服務(wù)的業(yè)務(wù)邏輯,該服務(wù)只會去連接server端,在服務(wù)的環(huán)境變量里配置了server端的域名,懷疑是不是有可能server端掛掉,在本地和集群宿主機上調(diào)用server的地址,發(fā)現(xiàn)是可以通的,因此排除掉了server端本身的問題

因為server端連接地址在我本地和集群宿主機上是可以正常調(diào)用,因此懷疑服務(wù)pod到server端地址不通,進入到pod中進行測試,發(fā)現(xiàn)的確不能調(diào)用,使用ping域名也是可以通的,但是發(fā)現(xiàn)ping解析出來的ip地址并不是我們server端的外網(wǎng)ip地址;因此懷疑到了dns解析的問題上,使用nsloopup命令進行排除(通常服務(wù)都沒有該命令需要手動安裝apt-get install dnsutils,yum install bind-utils,或者使用kubectl-debug工具來共享容器排查),解析出來的發(fā)現(xiàn)很詭異的name,域名最后面帶了一個HOST

進一步查看/etc/resolv.conf,發(fā)現(xiàn)搜索域中有一個HOST搜索域,因此解析域名會帶上HOST

又測試了幾個域名,只要最后帶HOST,都會解析到一個ip地址上,上網(wǎng)一搜,才知道這個HOST是個頂級域名,還會泛解析到某個ip上



至此,導(dǎo)致本次故障的原因,已定位到,是由于pod中的搜索域中帶了一個頂級域名HOST,產(chǎn)生的泛解析到了一個不是我們server端的地址上

3、故障原因分析

首先我們需要知道在k8s中的pod是如何進行服務(wù)之間域名調(diào)用,是如何解析的?

Kubernetes 中的域名解析分析

在 Kubernetes 中,比如服務(wù) a 訪問服務(wù) b,對于同一個 Namespace下,可以直接在 pod 中,通過 curl b 來訪問。對于跨 Namespace 的情況,服務(wù)名后邊對應(yīng) Namespace即可。比如 curl b.devops。那么,使用者這里邊會有幾個問題:

①:服務(wù)名是什么?②:為什么同一個 Namespace 下,直接訪問服務(wù)名即可?不同 Namespace 下,需要帶上 Namespace 才行?③:為什么內(nèi)部的域名可以做解析,原理是什么?

DNS 如何解析,依賴容器內(nèi) resolv 文件的配置

cat /etc/resolv.confnameserver 10.68.0.2search devops.svc.cluster.local. svc.cluster.local. cluster.local.這個文件中,配置的 DNS Server,一般就是 K8S 中,kubedns 的 Service 的 ClusterIP,這個IP是虛擬IP,無法ping,但可以訪問。

root@other-8-67:~# kubectl get svc -n kube-system |grep dnskube-dns ClusterIP 10.68.0.2 <none> 53/UDP,53/TCP,9153/TCP 106d所以,所有域名的解析,其實都要經(jīng)過 kubedns 的虛擬IP 10.68.0.2 進行解析,不論是 Kubernetes 內(nèi)部域名還是外部的域名。Kubernetes 中,域名的全稱,必須是 service-name.namespace.svc.cluster.local 這種模式,服務(wù)名,就是Kubernetes中 Service 的名稱,所以,當(dāng)我們執(zhí)行下面的命令時:

curl b必須得有一個 Service 名稱為 b,這是前提。

在容器內(nèi),會根據(jù) /etc/resolve.conf 進行解析流程。選擇 nameserver 10.68.0.2 進行解析,然后,用字符串 “b”,依次帶入 /etc/resolve.conf 中的 search 域,進行DNS查找,分別是:

// search 內(nèi)容類似如下(不同的pod,第一個域會有所不同)search devops.svc.cluster.local svc.cluster.local cluster.localb.devops.svc.cluster.local -> b.svc.cluster.local -> b.cluster.local ,直到找到為止。

所以,我們執(zhí)行 curl b,或者執(zhí)行 curl b.devops,都可以完成DNS請求,這2個不同的操作,會分別進行不同的DNS

// curl b,可以一次性找到(b +devops.svc.cluster.local)b.devops.svc.cluster.local// curl b.devops,第一次找不到( b.devops + devops.svc.cluster.local)b.devops.devops.svc.cluster.local// 第二次查找( b.devops + svc.cluster.local),可以找到b.devops.svc.cluster.local因此curl b,要比 curl b.devops 效率高,因為 curl b.devops,多經(jīng)過了一次 DNS 查詢。

訪問外部域名走 search 域嗎,看情況,可以說,大部分情況要走 search 域。我們以請求 http://baidu.com 為例,通過抓包的方式,看一看在某個容器中訪問 http://baidu.com,進行的DNS查找的過程,都產(chǎn)生了什么樣的數(shù)據(jù)包。注意:我們要抓DNS容器的包,就得先進入到DNS容器的網(wǎng)絡(luò)中(而不是發(fā)起DNS請求的那個容器)。

由于DNS容器往往不具備bash,所以無法通過 docker exec 的方式進入容器內(nèi)抓包,我們采用其他的方式:

// 1、找到容器ID,并打印它的NS IDdocker inspect --format "{{.State.Pid}}" 16938de418ac// 2、進入此容器的網(wǎng)絡(luò)Namespacensenter -n -t 54438// 3、抓DNS包tcpdump -i eth0 udp dst port 53|grep baidu.com在其他的容器中,進行 http://baidu.com 域名查找

nslookup baidu.com 114.114.114.114注意:nslookup命令的最后指定DNS服務(wù)容器的IP,是因為,如果不指定,且DNS服務(wù)的容器存在多個的話,那么DNS請求,可能會均分到所有DNS服務(wù)的容器上,我們?nèi)绻蛔ツ硢蝹€DNS服務(wù)容器抓到的包,可能就不全了,指定IP后,DNS的請求,就必然只會打到單個的DNS容器。抓包的數(shù)據(jù)才完整。

可以看到類似如下結(jié)果:

11:46:26.843118 IP srv-device-manager-7595d6795c-8rq6n.60857 > kube-dns.kube-system.svc.cluster.local.domain: 19198+ A? baidu.com.devops.svc.cluster.local. (49)11:46:26.843714 IP srv-device-manager-7595d6795c-8rq6n.35998 > kube-dns.kube-system.svc.cluster.local.domain: 53768+ AAAA? baidu.com.devops.svc.cluster.local. (49)11:46:26.844260 IP srv-device-manager-7595d6795c-8rq6n.57939 > kube-dns.kube-system.svc.cluster.local.domain: 48864+ A? baidu.com.svc.cluster.local. (45)11:46:26.844666 IP srv-device-manager-7595d6795c-8rq6n.35990 > kube-dns.kube-system.svc.cluster.local.domain: 43238+ AAAA? baidu.com.svc.cluster.local. (45)11:46:26.845153 IP srv-device-manager-7595d6795c-8rq6n.58745 > kube-dns.kube-system.svc.cluster.local.domain: 59086+ A? baidu.com.cluster.local. (41)11:46:26.845543 IP srv-device-manager-7595d6795c-8rq6n.32910 > kube-dns.kube-system.svc.cluster.local.domain: 30930+ AAAA? baidu.com.cluster.local. (41)11:46:26.845907 IP srv-device-manager-7595d6795c-8rq6n.55367 > kube-dns.kube-system.svc.cluster.local.domain: 58903+ A? baidu.com. (27)11:46:26.861714 IP srv-device-manager-7595d6795c-8rq6n.32900 > kube-dns.kube-system.svc.cluster.local.domain: 58394+ AAAA? baidu.com. (27)我們可以看到,在真正解析 http://baidu.com 之前,經(jīng)歷了 baidu.com.devops.svc.cluster.local. -> baidu.com.svc.cluster.local. -> baidu.com.cluster.local. -> baidu.com.

這也就意味著有3次DNS請求,是浪費的無意義的請求。這是因為,在 Kubernetes 中,其實 /etc/resolv.conf 這個文件,并不止包含 nameserver 和 search 域,還包含了非常重要的一項:ndots。

/prometheus $ cat /etc/resolv.confnameserver 10.66.0.2search monitor.svc.cluster.local. svc.cluster.local. cluster.local. options ndots:5ndots:5,表示:如果查詢的域名包含的點“.”,不到5個,那么進行DNS查找,將使用非完全限定名稱(或者叫絕對域名),如果你查詢的域名包含點數(shù)大于等于5,那么DNS查詢,默認(rèn)會使用絕對域名進行查詢。舉例來說:

如果我們請求的域名是,a.b.c.d.e,這個域名中有4個點,那么容器中進行DNS請求時,會使用非絕對域名進行查找,使用非絕對域名,會按照 /etc/resolv.conf 中的 search 域,走一遍追加匹配:

a.b.c.d.e.devops.svc.cluster.local. ->a.b.c.d.e.svc.cluster.local. ->a.b.c.d.e.cluster.local.直到找到為止。如果走完了search域還找不到,則使用 a.b.c.d.e. ,作為絕對域名進行DNS查找。

我們通過抓包分析一個具體案例:域名中點數(shù)少于5個的情況:

// 對域名 a.b.c.d.com 進行DNS解析請求 root@srv-xxx-7595d6795c-8rq6n:/go/bin# nslookup a.b.c.d.comServer: 10.68.0.2Address: 10.68.0.2#53** server can't find a.b.c.d.com: NXDOMAIN// 抓包數(shù)據(jù)如下:root@srv-device-manager-7595d6795c-8rq6n:/go/bin# tcpdump -i eth0 udp dst port 53 -c 20 |grep a.b.c.d.comtcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes20 packets captured16:14:40.053575 IP srv-device-manager-7595d6795c-8rq6n.37359 > kube-dns.kube-system.svc.cluster.local.domain: 29842+ A? a.b.c.d.com.cluster.local. (43)16:14:40.054083 IP srv-device-manager-7595d6795c-8rq6n.34813 > kube-dns.kube-system.svc.cluster.local.domain: 19104+ AAAA? a.b.c.d.com.cluster.local. (43)25 packets received by filter16:14:40.054983 IP srv-device-manager-7595d6795c-8rq6n.37303 > kube-dns.kube-system.svc.cluster.local.domain: 53902+ A? a.b.c.d.com.devops.svc.cluster.local. (51)16:14:40.055465 IP srv-device-manager-7595d6795c-8rq6n.40766 > kube-dns.kube-system.svc.cluster.local.domain: 34453+ AAAA? a.b.c.d.com.devops.svc.cluster.local. (51)0 packets dropped by kernel16:14:40.055946 IP srv-device-manager-7595d6795c-8rq6n.35443 > kube-dns.kube-system.svc.cluster.local.domain: 24829+ A? a.b.c.d.com.svc.cluster.local. (47)16:14:40.057698 IP srv-device-manager-7595d6795c-8rq6n.44180 > kube-dns.kube-system.svc.cluster.local.domain: 23046+ AAAA? a.b.c.d.com.svc.cluster.local. (47)16:14:40.058062 IP srv-device-manager-7595d6795c-8rq6n.56986 > kube-dns.kube-system.svc.cluster.local.domain: 42008+ A? a.b.c.d.com. (29)16:14:40.075579 IP srv-device-manager-7595d6795c-8rq6n.55738 > kube-dns.kube-system.svc.cluster.local.domain: 32284+ AAAA? a.b.c.d.com. (29)// 結(jié)論:// 點數(shù)少于5個,先走search域,最后將其視為絕對域名進行查詢域名中點數(shù)>=5個的情況:

// 對域名 a.b.c.d.e.com 進行DNS解析請求 root@srv-xxx-7595d6795c-8rq6n:/go/bin# nslookup a.b.c.d.e.comServer: 10.68.0.2Address: 10.68.0.2#53** server can't find a.b.c.d.e.com: NXDOMAIN// 抓包數(shù)據(jù)如下:root@srv-device-manager-7595d6795c-8rq6n:/go/bin# tcpdump -i eth0 udp dst port 53 -c 20 |grep a.b.c.d.e.comtcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes16:32:39.624305 IP srv-device-manager-7595d6795c-8rq6n.56274 > kube-dns.kube-system.svc.cluster.local.domain: 43582+ A? a.b.c.d.e.com. (31)20 packets captured16:32:39.805470 IP srv-device-manager-7595d6795c-8rq6n.56909 > kube-dns.kube-system.svc.cluster.local.domain: 27206+ AAAA? a.b.c.d.e.com. (31)16:32:39.833203 IP srv-device-manager-7595d6795c-8rq6n.33370 > kube-dns.kube-system.svc.cluster.local.domain: 14881+ A? a.b.c.d.e.com.cluster.local. (45)21 packets received by filter16:32:39.833779 IP srv-device-manager-7595d6795c-8rq6n.40814 > kube-dns.kube-system.svc.cluster.local.domain: 43047+ AAAA? a.b.c.d.e.com.cluster.local. (45)16:32:39.834363 IP srv-device-manager-7595d6795c-8rq6n.53053 > kube-dns.kube-system.svc.cluster.local.domain: 17994+ A? a.b.c.d.e.com.iot.svc.cluster.local. (53)0 packets dropped by kernel16:32:39.834740 IP srv-device-manager-7595d6795c-8rq6n.47803 > kube-dns.kube-system.svc.cluster.local.domain: 15951+ AAAA? a.b.c.d.e.com.iot.svc.cluster.local. (53)16:32:39.835177 IP srv-device-manager-7595d6795c-8rq6n.60845 > kube-dns.kube-system.svc.cluster.local.domain: 38541+ A? a.b.c.d.e.com.svc.cluster.local. (49)16:32:39.835611 IP srv-device-manager-7595d6795c-8rq6n.36086 > kube-dns.kube-system.svc.cluster.local.domain: 49809+ AAAA? a.b.c.d.e.com.svc.cluster.local. (49)// 結(jié)論:// 點數(shù)>=5個,直接視為絕對域名進行查找,只有當(dāng)查詢不到的時候,才繼續(xù)走 search 域。

優(yōu)化方式1:使用全限定域名

其實最直接,最有效的優(yōu)化方式,就是使用 “fully qualified name”,簡單來說,使用“完全限定域名”(也叫絕對域名),你訪問的域名,必須要以 “.” 為后綴,這樣就會避免走 search 域進行匹配,我們抓包再試一次:

nslookup a.b.c.com.在DNS服務(wù)容器上抓到的包如下

root@srv-device-manager-7595d6795c-8rq6n:/go/bin# tcpdump -i eth0 udp dst port 53 -c 20 |grep a.b.c.com.tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes16:39:31.771615 IP srv-device-manager-7595d6795c-8rq6n.50332 > kube-dns.kube-system.svc.cluster.local.domain: 50829+ A? a.b.c.com. (27)20 packets captured16:39:31.793579 IP srv-device-manager-7595d6795c-8rq6n.51946 > kube-dns.kube-system.svc.cluster.local.domain: 25235+ AAAA? a.b.c.com. (27)并沒有多余的DNS請求

優(yōu)化方式2:具體應(yīng)用配置特定的 ndots

其實,往往我們還真不太好用這種絕對域名的方式,有誰請求http://baidu.com的時候,還寫成 baidu.com. 呢?

在 Kubernetes 中,默認(rèn)設(shè)置了 ndots 值為5,是因為,Kubernetes 認(rèn)為,內(nèi)部域名,最長為5,要保證內(nèi)部域名的請求,優(yōu)先走集群內(nèi)部的DNS,而不是將內(nèi)部域名的DNS解析請求,有打到外網(wǎng)的機會,Kubernetes 設(shè)置 ndots 為5是一個比較合理的行為。

如果你需要定制這個長度,最好是為自己的業(yè)務(wù),單獨配置 ndots 即可(deployment為例)。

... spec: containers: - env: - name: GOENV value: DEV image: xxx/devops/srv-inner-proxy imagePullPolicy: IfNotPresent lifecycle: {} livenessProbe: failureThreshold: 3 httpGet: path: /health port: 8000 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 name: srv-inner-proxy ports: - containerPort: 80 protocol: TCP - containerPort: 8000 protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /health port: 8000 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsConfig: options: - name: timeout value: "2" - name: ndots value: "2" - name: single-request-reopen dnsPolicy: ClusterFirst ...在Kubernetes 中,有4種 DNS 策略

具體來說:

表示空的DNS設(shè)置

這種方式一般用于想要自定義 DNS 配置的場景,而且,往往需要和 dnsConfig 配合一起使用達到自定義 DNS 的目的。

有人說 Default 的方式,是使用宿主機的方式,這種說法并不準(zhǔn)確。

這種方式,其實是,讓 kubelet 來決定使用何種 DNS 策略。而 kubelet 默認(rèn)的方式,就是使用宿主機的 /etc/resolv.conf(可能這就是有人說使用宿主機的DNS策略的方式吧),但是,kubelet 是可以靈活來配置使用什么文件來進行DNS策略的,我們完全可以使用 kubelet 的參數(shù):–resolv-conf=/etc/resolv.conf 來決定你的DNS解析文件地址。

這種方式,表示 POD 內(nèi)的 DNS 使用集群中配置的 DNS 服務(wù),簡單來說,就是使用 Kubernetes 中 kubedns 或 coredns 服務(wù)進行域名解析。如果解析不成功,才會使用宿主機的 DNS 配置進行解析。

在某些場景下,我們的 POD 是用 HOST 模式啟動的(HOST模式,是共享宿主機網(wǎng)絡(luò)的),一旦用 HOST 模式,表示這個 POD 中的所有容器,都要使用宿主機的 /etc/resolv.conf 配置進行DNS查詢,但如果你想使用了 HOST 模式,還繼續(xù)使用 Kubernetes 的DNS服務(wù),那就將 dnsPolicy 設(shè)置為 ClusterFirstWithHostNet。

這幾種DNS策略,需要在Pod,或者Deployment、RC等資源中,設(shè)置 dnsPolicy 即可

4、結(jié)論

通過故障原因的分析,我們可以知道該故障比較好的解決辦法,就是在deployment中去設(shè)置dnsPolicy,在不影響集群內(nèi)服務(wù)直接調(diào)用的情況下,把ndots從默認(rèn)的5修改成了2,使代理服務(wù)pod在訪問server端域名的時候dns解析直接走絕對域名,這樣就會避免走 search 域進行匹配,可以正確匹配到ip地址。通過此次故障也讓我知其然知其所以然,在排查故障的過程中,需要去了解背后涉及到的知識點和根本原因。

參考文章:

https://cloud.tencent.com/developer/article/1804653

文章來源于運維開發(fā)故事,作者冬子先生

關(guān)鍵詞:錯誤

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點擊下載Chrome瀏覽器
關(guān)閉