全部產品
Search
文件中心

Container Service for Kubernetes:DNS解析異常問題排查

更新時間:Mar 08, 2024

本文介紹關於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服務。

異常診斷流程

故障手冊流程.png

  1. 判斷當前的異常原因。具體資訊,請參見常見用戶端報錯

    • 如果異常原因是網域名稱不存在,請參見排查思路《按解析異常的網域名稱類型》

    • 如果異常原因是無法串連至網域名稱伺服器,請參見排查思路《按解析異常出現頻次》

  2. 如果以上排查無果,請按以下步驟排查。

  3. 如果以上排查無果,請排查。

常見用戶端報錯

用戶端

報錯日誌

可能異常

ping

ping: xxx.yyy.zzz: Name or service not known

網域名稱不存在或無法串連網域名稱伺服器。如果解析延遲大於5秒,一般是無法串連網域名稱伺服器。

curl

curl: (6) Could not resolve host: xxx.yyy.zzz

PHP HTTP用戶端

php_network_getaddresses: getaddrinfo failed: Name or service not known in xxx.php on line yyy

Golang HTTP用戶端

dial tcp: lookup xxx.yyy.zzz on 100.100.2.136:53: no such host

網域名稱不存在。

dig

;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: xxxxx

Golang HTTP用戶端

dial tcp: lookup xxx.yyy.zzz on 100.100.2.139:53: read udp 192.168.0.100:42922->100.100.2.139:53: i/o timeout

無法串連網域名稱伺服器。

dig

;; connection timed out; no servers could be reached

排查思路

排查思路

排查依據

問題及解決方案

按解析異常的網域名稱類型排查

叢集內外網域名稱都異常

僅叢集外部網域名稱異常

叢集外部網域名稱解析異常

僅PrivateZone 、vpc-proxy網域名稱解析異常

PrivateZone網域名稱解析異常

僅Headless類型服務網域名稱異常

按解析異常出現頻次排查

完全無法解析

異常僅出現在業務高峰時期

異常出現頻次非常高

異常出現頻次非常低

異常僅出現在節點擴縮容或CoreDNS縮容時

IPVS缺陷導致解析異常

常見檢查方法

檢查業務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

參數

描述

f

持續輸出。

tail=500

輸出最後500行日誌。

timestamps

同時顯示日誌列印的時間。

coredns-xxxxxxxxx-xxxxx

CoreDNS Pod副本的名稱。

檢查CoreDNS DNS查詢請求日誌

命令

DNS查詢請求日誌僅會在開啟CoreDNS的Log外掛程式後,才會列印到容器日誌中。關於開啟Log外掛程式的具體操作,請參見CoreDNS配置說明

命令與檢查CoreDNS作業記錄相同,請參見檢查CoreDNS作業記錄

檢查CoreDNS Pod的網路連通性

操作步驟

  1. 登入CoreDNS Pod所在叢集節點。

  2. 執行ps aux | grep coredns,查詢CoreDNS的進程ID。

  3. 執行nsenter -t <pid> -n bash,進入CoreDNS所在容器網路命名空間,其中pid為上一步得到的進程ID。

  4. 測試網路連通性。

    1. 運行telnet <apiserver_clusterip> 6443,測試Kubernetes API Server的連通性。

      其中apiserver_clusterip為default命名空間下Kubernetes服務的IP地址。

    2. 運行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的網路連通性

操作步驟

  1. 選擇以下任意一種方式,進入用戶端Pod容器網路。

    • 方法一:使用kubectl exec命令。

    • 方法二:

      1. 登入業務Pod所在叢集節點。

      2. 執行ps aux | grep <業務進程名>命令,查詢業務容器的進程ID。

      3. 執行nsenter -t <pid> -n bash命令,進入業務Pod所在容器網路命名空間。

        其中pid為上一步得到的進程ID。

    • 方法三:如果頻繁重啟,請按以下步驟操作。

      1. 登入業務Pod所在叢集節點。

      2. 執行docker ps -a | grep <業務容器名>命令,查詢k8s_POD_ 開頭的沙箱容器,記錄容器ID。

      3. 執行docker inspect <沙箱容器 ID> | grep netns命令,查詢/var/run/docker/netns/xxxx的容器網路命名空間路徑。

      4. 執行nsenter -n<netns 路徑> bash命令,進入容器網路命名空間。

        其中netns 路徑為上一步得到的路徑。

        說明

        -n<netns 路徑>之間不加空格。

  2. 測試網路連通性。

    1. 執行dig <domain> @<kube_dns_svc_ip>命令,測試業務Pod到CoreDNS服務kube-dns解析查詢的連通性。

      其中<domain>為測試網域名稱,<kube_dns_svc_ip>為kube-system命名空間中kube-dns的服務IP。

    2. 執行ping <coredns_pod_ip>命令,測試業務Pod到CoreDNS容器副本的連通性。

      其中<coredns_pod_ip>為kube-system命名空間中CoreDNS Pod的IP。

    3. 執行dig <domain> @<coredns_pod_ip>命令,測試業務Pod到CoreDNS容器副本解析查詢的連通性。

      其中<domain>為測試網域名稱,<coredns_pod_ip>為kube-system命名空間中CoreDNS Pod的IP。

常見問題

現象

原因

處理方案

業務Pod無法通過CoreDNS服務kube-dns解析

機器負載高、kube-proxy沒有正常運行、安全性群組沒有放開UDP協議53連接埠等。

檢查安全性群組是否放開UDP 53連接埠,若已放開請排查。

業務Pod無法連通CoreDNS容器副本

容器網路異常或安全性群組沒有放開ICMP。

檢查安全性群組是否放開ICMP,若已放開請排查。

業務Pod無法通過CoreDNS容器副本解析

機器負載高、安全性群組沒有放開UDP協議53連接埠等。

檢查安全性群組是否放開UDP 53連接埠,若已放開請排查。

抓包

當無法定位問題時,需要抓包進行輔助診斷。

  1. 登入出現異常的業務Pod、CoreDNS Pod所在節點。

  2. 在ECS(非容器內)執行以下命令,可以將最近所有的53連接埠資訊抓取到檔案中。

    tcpdump -i any port 53 -C 20 -W 200 -w /tmp/client_dns.pcap
  3. 結合業務日誌的報錯定位到精準的報錯時間的報文資訊。

    說明
    • 在正常情況下,抓包對業務無影響,僅會增加小部分的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查詢請求日誌中顯示叢集外部網域名稱返回為NXDOMAINSERVFAILREFUSED時,說明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運行狀態和作業記錄。

常見異常日誌及處理方案

日誌中字樣

原因

處理方案

/etc/coredns/Corefile:4 - Error during parsing: Unknown directive 'ready'

設定檔和CoreDNS不相容,Unknown directive代表當前啟動並執行CoreDNS版本不支援ready外掛程式。

從kube-system命名空間中CoreDNS配置項中刪除ready外掛程式,其它報錯同理。

pkg/mod/k8s.io/client-go@v0.18.3/tools/cache/reflector.go:125: Failed to watch *v1.Pod: Get "https://192.168.0.1:443/api/v1/": dial tcp 192.168.0.1:443: connect: connection refused

日誌出現時間段內,API Server中斷。

如果是日誌出現時間和異常不吻合,可以排除該原因,否則請檢查CoreDNS Pod網路連通性。具體操作,請參見檢查CoreDNS Pod的網路連通性

[ERROR] plugin/errors: 2 www.aliyun.com. A: read udp 172.20.6.53:58814->100.100.2.136:53: i/o timeout

日誌出現時間段內,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外掛程式。

  1. 執行kubectl -n kube-system edit configmap coredns命令,開啟CoreDNS設定檔。

  2. 刪除autopath @kubernetes一行後儲存退出。

  3. 檢查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未生效

問題現象

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配置說明