本文介紹關於DNS解析異常的診斷流程、排查思路、常見解決方案和排查方法。
索引
類別 | 內容 |
診斷流程 | |
排查思路 | |
常見排查方法 | |
常見問題及解決方案 |
診斷流程
基本概念
叢集內部網域名稱:CoreDNS會將叢集中的服務暴露為叢集內部網域名稱,預設以
.cluster.local
結尾,這類網域名稱的解析通過CoreDNS內部緩衝完成,不會從上遊DNS伺服器查詢。叢集外部網域名稱:在第三方DNS服務商、阿里雲DNS雲解析、PrivateZone等產品註冊的權威解析,這類網域名稱由CoreDNS的上遊DNS伺服器負責解析,CoreDNS僅做解析請求轉寄。
業務Pod:您部署在Kubernetes叢集中的容器Pod,不包含Kubernetes自身系統組件的容器。
接入CoreDNS的業務Pod:容器內DNS伺服器指向了CoreDNS的業務Pod。
接入NodeLocal DNSCache的業務Pod:叢集中安裝了NodeLocal DNSCache外掛程式後,通過自動或手動方式注入DNSConfig的業務Pod。這類Pod在解析網域名稱時,會優先訪問本機快取組件。如果訪問本機快取組件不通時,會訪問CoreDNS提供的kube-dns服務。
異常診斷流程
判斷當前的異常原因。具體資訊,請參見常見用戶端報錯。
如果以上排查無果,請按以下步驟排查。
檢查業務Pod的DNS配置,是否已經接入CoreDNS。具體操作,請參見檢查業務Pod的DNS配置。
如果沒有接入CoreDNS,則考慮是用戶端負載原因或Conntrack表滿導致解析失敗。具體操作,請參見用戶端負載原因導致解析失敗和Conntrack表滿。
如果接入了CoreDNS,則按以下步驟排查。
通過檢查CoreDNS Pod運行狀態進行診斷。具體操作,請參見檢查CoreDNS Pod運行狀態和CoreDNS Pod運行狀態異常。
通過檢查CoreDNS作業記錄進行診斷。具體操作,請參見檢查CoreDNS作業記錄和叢集外部網域名稱解析異常。
確認異常是否能夠穩定複現。
如果異常穩定複現,請參見檢查CoreDNS DNS查詢請求日誌和檢查業務Pod到CoreDNS的網路連通性。
如果異常不能穩定複現,請參見抓包。
如果使用了NodeLocal DNSCache,請參見NodeLocal DNSCache未生效和PrivateZone網域名稱解析異常。
常見用戶端報錯
用戶端 | 報錯日誌 | 可能異常 |
ping |
| 網域名稱不存在或無法串連網域名稱伺服器。如果解析延遲大於5秒,一般是無法串連網域名稱伺服器。 |
curl |
| |
PHP HTTP用戶端 |
| |
Golang HTTP用戶端 |
| 網域名稱不存在。 |
dig |
| |
Golang HTTP用戶端 |
| 無法串連網域名稱伺服器。 |
dig |
|
排查思路
排查思路 | 排查依據 | 問題及解決方案 |
按解析異常的網域名稱類型排查 | 叢集內外網域名稱都異常 | |
僅叢集外部網域名稱異常 | ||
僅PrivateZone 、vpc-proxy網域名稱解析異常 | ||
僅Headless類型服務網域名稱異常 | ||
按解析異常出現頻次排查 | 完全無法解析 | |
異常僅出現在業務高峰時期 | ||
異常出現頻次非常高 | ||
異常出現頻次非常低 | ||
異常僅出現在節點擴縮容或CoreDNS縮容時 |
常見檢查方法
檢查業務Pod的DNS配置
命令
#查看foo容器的YAML配置,並確認DNSPolicy欄位是否符合預期。 kubectl get pod foo -o yaml #當DNSPolicy符合預期時,可以進一步進入Pod容器中,查看實際生效的DNS配置。 #通過bash命令進入foo容器,若bash不存在可使用sh代替。 kubectl exec -it foo bash #進入容器後,可以查看DNS配置,nameserver後面為DNS伺服器位址。 cat /etc/resolv.conf
DNS Policy配置說明
DNS Policy樣本如下所示。
apiVersion: v1 kind: Pod metadata: name: <pod-name> namespace: <pod-namespace> spec: containers: - image: <container-image> name: <container-name> #預設情境下的DNS Policy。 dnsPolicy: ClusterFirst #使用了NodeLocal DNSCache時的DNS Policy。 dnsPolicy: None dnsConfig: nameservers: - 169.254.20.10 - 172.21.0.10 options: - name: ndots value: "3" - name: timeout value: "1" - name: attempts value: "2" searches: - default.svc.cluster.local - svc.cluster.local - cluster.local securityContext: {} serviceAccount: default serviceAccountName: default terminationGracePeriodSeconds: 30
DNSPolicy欄位值
使用的DNS伺服器
Default
只適用於不需要訪問叢集內部服務的情境。Pod建立時會從ECS節點/etc/resolv.conf檔案繼承DNS伺服器列表。
ClusterFirst
此為DNSPolicy預設值,Pod會將CoreDNS提供的kube-dns服務IP作為DNS伺服器。開啟HostNetwork的Pod,如果選擇ClusterFirst模式,效果等同於Default模式。
ClusterFirstWithHostNet
開啟HostNetwork的Pod,如果選擇ClusterFirstWithHostNet模式,效果等同於ClusterFirst。
None
配合DNSConfig欄位,可用於自訂DNS伺服器和參數。在NodeLocal DNSCache開啟注入時,DNSConfig會將DNS伺服器指向本機快取IP及CoreDNS提供的kube-dns服務IP。
檢查CoreDNS Pod運行狀態
命令
執行以下命令,查看容器組資訊。
kubectl -n kube-system get pod -o wide -l k8s-app=kube-dns
預期輸出:
NAME READY STATUS RESTARTS AGE IP NODE coredns-xxxxxxxxx-xxxxx 1/1 Running 0 25h 172.20.6.53 cn-hangzhou.192.168.0.198
執行以下命令,查看Pod的即時資源使用方式。
kubectl -n kube-system top pod -l k8s-app=kube-dns
預期輸出:
NAME CPU(cores) MEMORY(bytes) coredns-xxxxxxxxx-xxxxx 3m 18Mi
如果Pod不處於Running狀態,可以通過
kubectl -n kube-system describe pod <CoreDNS Pod名稱>
命令,查詢問題原因。
檢查CoreDNS作業記錄
命令
執行以下命令,檢查CoreDNS作業記錄。
kubectl -n kube-system logs -f --tail=500 --timestamps coredns-xxxxxxxxx-xxxxx
參數 | 描述 |
| 持續輸出。 |
| 輸出最後500行日誌。 |
| 同時顯示日誌列印的時間。 |
| CoreDNS Pod副本的名稱。 |
檢查CoreDNS DNS查詢請求日誌
命令
DNS查詢請求日誌僅會在開啟CoreDNS的Log外掛程式後,才會列印到容器日誌中。關於開啟Log外掛程式的具體操作,請參見CoreDNS配置說明。
命令與檢查CoreDNS作業記錄相同,請參見檢查CoreDNS作業記錄。
檢查CoreDNS Pod的網路連通性
操作步驟
登入CoreDNS Pod所在叢集節點。
執行
ps aux | grep coredns
,查詢CoreDNS的進程ID。執行
nsenter -t <pid> -n bash
,進入CoreDNS所在容器網路命名空間,其中pid
為上一步得到的進程ID。測試網路連通性。
運行
telnet <apiserver_clusterip> 6443
,測試Kubernetes API Server的連通性。其中
apiserver_clusterip為default命名空間下Kubernetes服務的IP地址。
運行
dig <domain> @<upstream_dns_server_ip>
,測試CoreDNS Pod到上遊DNS伺服器的連通性。其中
domain
為測試網域名稱,upstream_dns_server_ip
為上遊DNS伺服器位址,預設為100.100.2.136和100.100.2.138。
常見問題
現象 | 原因 | 處理方案 |
CoreDNS無法連通Kubernetes API Server | APIServer異常、機器負載高、kube-proxy 沒有正常運行等。 | |
CoreDNS無法連通上遊DNS伺服器 | 機器負載高、CoreDNS配置錯誤、專線路由問題等。 |
檢查業務Pod到CoreDNS的網路連通性
操作步驟
選擇以下任意一種方式,進入用戶端Pod容器網路。
方法一:使用
kubectl exec
命令。方法二:
登入業務Pod所在叢集節點。
執行
ps aux | grep <業務進程名>
命令,查詢業務容器的進程ID。執行
nsenter -t <pid> -n bash
命令,進入業務Pod所在容器網路命名空間。其中
pid
為上一步得到的進程ID。
方法三:如果頻繁重啟,請按以下步驟操作。
登入業務Pod所在叢集節點。
執行
docker ps -a | grep <業務容器名>
命令,查詢k8s_POD_
開頭的沙箱容器,記錄容器ID。執行
docker inspect <沙箱容器 ID> | grep netns
命令,查詢/var/run/docker/netns/xxxx的容器網路命名空間路徑。執行
nsenter -n<netns 路徑> bash
命令,進入容器網路命名空間。其中
netns 路徑
為上一步得到的路徑。說明-n
和<netns 路徑>
之間不加空格。
測試網路連通性。
執行
dig <domain> @<kube_dns_svc_ip>
命令,測試業務Pod到CoreDNS服務kube-dns解析查詢的連通性。其中
<domain>
為測試網域名稱,<kube_dns_svc_ip>
為kube-system命名空間中kube-dns的服務IP。執行
ping <coredns_pod_ip>
命令,測試業務Pod到CoreDNS容器副本的連通性。其中
<coredns_pod_ip>
為kube-system命名空間中CoreDNS Pod的IP。執行
dig <domain> @<coredns_pod_ip>
命令,測試業務Pod到CoreDNS容器副本解析查詢的連通性。其中
<domain>
為測試網域名稱,<coredns_pod_ip>
為kube-system命名空間中CoreDNS Pod的IP。
常見問題
現象 | 原因 | 處理方案 |
業務Pod無法通過CoreDNS服務kube-dns解析 | 機器負載高、kube-proxy沒有正常運行、安全性群組沒有放開UDP協議53連接埠等。 | |
業務Pod無法連通CoreDNS容器副本 | 容器網路異常或安全性群組沒有放開ICMP。 | |
業務Pod無法通過CoreDNS容器副本解析 | 機器負載高、安全性群組沒有放開UDP協議53連接埠等。 |
抓包
當無法定位問題時,需要抓包進行輔助診斷。
登入出現異常的業務Pod、CoreDNS Pod所在節點。
在ECS(非容器內)執行以下命令,可以將最近所有的53連接埠資訊抓取到檔案中。
tcpdump -i any port 53 -C 20 -W 200 -w /tmp/client_dns.pcap
結合業務日誌的報錯定位到精準的報錯時間的報文資訊。
說明在正常情況下,抓包對業務無影響,僅會增加小部分的CPU負載和磁碟寫入。
以上命令會對抓取到的包進行rotate,最多可以寫200個20 MB的.pcap檔案。
叢集外部網域名稱解析異常
問題現象
業務Pod可以正常解析叢集內部網域名稱,但無法解析某些叢集外部網域名稱。
問題原因
上遊伺服器網域名稱解析返回異常。
解決方案
檢查CoreDNS DNS查詢請求日誌。
常見請求日誌
CoreDNS接收到請求並回複用戶端後會列印一行日誌,樣本如下:
# 其中包含狀態代碼RCODE NOERROR,代表解析結果正常返回。
[INFO] 172.20.2.25:44525 - 36259 "A IN redis-master.default.svc.cluster.local. udp 56 false 512" NOERROR qr,aa,rd 110 0.000116946s
常見返回碼RCODE
關於返回碼RCODE定義的具體資訊,請參見規範。
返回碼RCODE | 含義 | 原因 |
NXDOMAIN | 網域名稱不存在 | 容器內請求網域名稱時,會被拼接上search尾碼,若拼接的結果網域名稱不存在,則會出現該請求碼。如果確認日誌中請求的網域名稱內容存在,則說明存在異常。 |
SERVFAIL | 上遊伺服器異常 | 常見於無法串連上遊DNS伺服器等情況。 |
REFUSED | 拒絕應答 | 常見於CoreDNS配置或叢集節點/etc/resolv.conf檔案指向的上遊DNS伺服器無法處理該網域名稱的情況,請排查CoreDNS設定檔。 |
當CoreDNS DNS查詢請求日誌中顯示叢集外部網域名稱返回為NXDOMAIN
、SERVFAIL
、REFUSED
時,說明CoreDNS的上遊DNS伺服器返回異常。
預設情況下,叢集中CoreDNS的上遊DNS伺服器是VPC提供的DNS伺服器(100.100.2.136 和 100.100.2.138)。您可以提交工單至Elastic Compute Service產品。提交工單時請註明以下資訊。
欄位 | 含義 | 樣本 |
受損網域名稱 | CoreDNS日誌中返回碼RCODE異常的叢集外部網域名稱 | www.aliyun.com |
解析返回碼RCODE | 具體解析報錯(NXDOMAIN、SERVFAIL、REFUSED) | NXDOMAIN |
受損時間 | 日誌出現的時間(精確到秒) | 2022-12-22 20:00:03 |
受損ECS | CoreDNS各副本Pod所處的ECS執行個體ID | i-xxxxx i-yyyyy |
新增Headless類型網域名稱無法解析
問題現象
接入CoreDNS的業務Pod無法解析新增的Headless類型網域名稱。
問題原因
1.7.0以前版本CoreDNS會在API Server抖動時異常退出,導致Headless網域名稱停止更新。
解決方案
升級CoreDNS至1.7.0以上。具體操作,請參見【組件升級】CoreDNS升級公告。
升級CoreDNS後Headless類型網域名稱無法解析
問題現象
部分較低版本開源組件(低版本etcd、nacos、kafka等)在K8s 1.20及以上版本和 CoreDNS 1.8.4及以上版本的環境中無法正常工作。
問題原因
1.8.4及以上版本的CoreDNS優先使用EndpointSlice API同步K8s內服務IP資訊。一些開源組件在初始化階段會使用Endpoint API 提供的註解service.alpha.kubernetes.io/tolerate-unready-endpoints
來發布尚未就緒的服務。該註解在EndpointSlice API中已經廢棄,並被publishNotReadyAddresses
所替代。因此CoreDNS升級後,無法發布未就緒的服務,導致這些組件無法進行服務發現。
解決方案
檢查開源組件的YAML或Helm Chart中是否包含service.alpha.kubernetes.io/tolerate-unready-endpoints
註解,如果包含則可能無法正常工作,您需要升級開源組件或諮詢開源組件社區。
StatefulSets Pod網域名稱無法解析
問題現象
Headless服務無法通過Pod網域名稱解析。
問題原因
StatefulSets Pod YAML中ServiceName必須和其暴露SVC的名字一致,否則無法訪問Pod網域名稱(例如pod.headless-svc.ns.svc.cluster.local),只能訪問到服務網域名稱(例如headless-svc.ns.svc.cluster.local)。
解決方案
修改StatefulSets Pod YAML中ServiceName名稱。
安全性群組、交換器ACL配置錯誤
問題現象
部分節點或全部節點上接入CoreDNS的業務,Pod解析網域名稱持久性失敗。
問題原因
修改了ECS或容器使用的安全性群組(或交換器ACL),攔截了UDP協議下53連接埠的通訊。
解決方案
恢複安全性群組、交換器ACL的配置,放開其以UDP協議對53連接埠的通訊。
容器網路連通性異常
問題現象
部分節點或全部節點上接入CoreDNS的業務,Pod解析網域名稱持久性失敗。
問題原因
由於容器網路或其它原因導致的UDP協議53連接埠持久性不通。
解決方案
CoreDNS Pod負載高
問題現象
部分節點或全部節點接入CoreDNS的業務,Pod解析網域名稱的延遲增加、機率性或持久性失敗。
檢查CoreDNS Pod運行狀態發現各副本CPU、Memory使用量接近其資源限制。
問題原因
由於CoreDNS副本數不足、業務請求量高等情況導致的CoreDNS負載高。
解決方案
考慮採用NodeLocal DNSCache緩衝方案,提升DNS解析效能,降低CoreDNS負載。具體操作,請參見使用NodeLocal DNSCache。
適當擴充CoreDNS副本數,使每個Pod的峰值CPU始終低於節點空閑CPU數。
CoreDNS Pod負載不均
問題現象
部分接入CoreDNS的業務Pod解析網域名稱的延遲增加、機率性或持久性失敗。
檢查CoreDNS Pod運行狀態發現各副本CPU使用量負載不均衡。
CoreDNS副本數少於兩個,或多個CoreDNS副本位於同節點上。
問題原因
由於CoreDNS副本調度不均、Service親和性設定導致CoreDNS Pod負載不均衡。
解決方案
擴容並打散CoreDNS副本到不同的節點上。
負載不均衡時,可禁用kube-dns服務的親和性屬性。具體操作,請參見配置Kube-DNS服務。
CoreDNS Pod運行狀態異常
問題現象
部分接入CoreDNS的業務Pod解析網域名稱的延遲增加、機率性或持久性失敗。
CoreDNS副本狀態Status不處於Running狀態,或重啟次數RESTARTS持續增加。
CoreDNS作業記錄中出現異常。
問題原因
由於CoreDNS YAML模板、設定檔等導致CoreDNS運行異常。
解決方案
檢查CoreDNS Pod運行狀態和作業記錄。
常見異常日誌及處理方案
日誌中字樣 | 原因 | 處理方案 |
| 設定檔和CoreDNS不相容, | 從kube-system命名空間中CoreDNS配置項中刪除ready外掛程式,其它報錯同理。 |
| 日誌出現時間段內,API Server中斷。 | 如果是日誌出現時間和異常不吻合,可以排除該原因,否則請檢查CoreDNS Pod網路連通性。具體操作,請參見檢查CoreDNS Pod的網路連通性。 |
| 日誌出現時間段內,CoreDNS無法串連到上遊DNS伺服器。 |
用戶端負載原因導致解析失敗
問題現象
業務高峰期間或突然偶發的解析失敗,ECS監控顯示機器網卡重傳率、CPU負載有異常。
問題原因
接入CoreDNS的業務Pod所在ECS負載達到100%等情況導致UDP報文丟失。
解決方案
考慮採用NodeLocal DNSCache緩衝方案,提升DNS解析效能,降低CoreDNS負載。具體操作,請參見使用NodeLocal DNSCache。
Conntrack表滿
問題現象
部分節點或全部節點上接入CoreDNS的業務,Pod解析網域名稱在業務高峰時間段內出現大批量網域名稱解析失敗,高峰結束後失敗消失。
運行
dmesg -H
,滾動到問題對應時段的日誌,發現出現conntrack full
字樣的報錯資訊。
問題原因
Linux內Conntrack表條目有限,無法進行新的UDP或TCP請求。
解決方案
增加Conntrack表限制。具體操作,請參見如何提升Linux串連跟蹤Conntrack數量限制?。
AutoPath外掛程式異常
問題現象
解析叢集外部網域名稱時,機率性解析失敗或解析到錯誤的IP地址,解析叢集內部網域名稱無異常。
高頻建立容器時,叢集內部服務網域名稱解析到錯誤的IP地址。
問題原因
CoreDNS處理缺陷導致AutoPath無法正常工作。
解決方案
按照以下步驟,關閉AutoPath外掛程式。
執行
kubectl -n kube-system edit configmap coredns
命令,開啟CoreDNS設定檔。刪除
autopath @kubernetes
一行後儲存退出。檢查CoreDNS Pod運行狀態和作業記錄,作業記錄中出現
reload
字樣後說明修改成功。
A記錄和AAAA記錄並發解析異常
問題現象
接入CoreDNS的業務Pod解析網域名稱機率性失敗。
從抓包或檢查CoreDNS DNS查詢請求日誌可以發現,A和AAAA通常在同一時間的出現,並且請求的源連接埠一致。
問題原因
並發A和AAAA的DNS請求觸發Linux核心Conntrack模組缺陷,導致UDP報文丟失。
解決方案
考慮採用NodeLocal DNSCache緩衝方案,提升DNS解析效能,降低CoreDNS負載。具體操作,請參見使用NodeLocal DNSCache。
CentOS、Ubuntu等基礎鏡像,可以通過
options timeout:2 attempts:3 rotate single-request-reopen
等參數最佳化。如果容器鏡像是以Alpine製作的,建議更換基礎鏡像。更多資訊,請參見Alpine。
PHP類應用短串連解析問題較多,如果使用的是PHP Curl的調用,可以使用
CURL_IPRESOLVE_V4
參數僅發送IPv4解析。更多資訊,請參見函數說明。
IPVS缺陷導致解析異常
問題現象
當叢集節點擴縮容、節點關機、CoreDNS縮容時,出現機率性解析失敗,通常時間長度在五分鐘左右。
問題原因
若您叢集的kube-proxy負載平衡模式為IPVS,在CentOS、Alibaba Cloud Linux 2核心版本小於4.19.91-25.1.al7.x86_64的節點上,摘除IPVS UDP類型後端後,一段時間內若新發起的UDP報文源連接埠衝突,該報文會被丟棄。
解決方案
考慮採用NodeLocal DNSCache緩衝方案,可以容忍IPVS丟包。具體操作,請參見使用NodeLocal DNSCache。
最佳化IPVS UDP逾時時間。具體操作,請參見配置IPVS類型叢集的UDP逾時時間。
NodeLocal DNSCache未生效
問題現象
NodeLocal DNSCache沒有流量進入,所有請求仍在CoreDNS上。
問題原因
未配置DNSConfig注入,業務Pod實際仍配置了CoreDNS kube-dns服務IP作為DNS伺服器位址。
業務Pod採用Alpine作為基礎鏡像,Alpine基礎鏡像會並發請求所有nameserver,包括本機快取和CoreDNS。
解決方案
配置DNSConfig自動注入。具體操作,請參見使用NodeLocal DNSCache。
如果容器鏡像是以Alpine製作的,建議更換基礎鏡像。更多資訊,請參見Alpine。
PrivateZone網域名稱解析異常
問題現象
對於接入NodeLocal DNSCache的業務,Pod無法解析PrivateZone上註冊的網域名稱,或無法解析包含vpc-proxy字樣的阿里雲雲產品API網域名稱,或解析結果不正確。
問題原因
PrivateZone不支援TCP協議,需要使用UDP協議訪問。
解決方案
在CoreDNS中配置prefer_udp
。具體操作,請參見CoreDNS配置說明。