如何對使用 Amazon EKS 時的 DNS 失敗進行疑難排解?
在我的 Amazon Elastic Kubernetes Service (Amazon EKS) 叢集中,使用 CoreDNS 的應用程式或 Pod 無法完成內部或外部 DNS 名稱解析。
簡短說明
在 Amazon EKS 叢集內執行的 Pod 會使用 CoreDNS 叢集 IP 位址作為名稱伺服器,以查詢內部與外部 DNS 記錄。如果 CoreDNS Pod、服務組態或連線能力發生問題,應用程式可能會無法進行 DNS 解析。
kube-dns 服務物件會抽象化 CoreDNS Pod。若要對 CoreDNS Pod 的問題進行疑難排解,請確認所有 kube-dns 服務元件的運作狀態,例如服務端點選項與 iptables 規則。
解決方法
**注意:**在以下解決方法中,CoreDNS 的 ClusterIP 值為 10.100.0.10。
若要檢查您的 DNS 組態,請完成以下步驟:
-
若要取得 CoreDNS 服務的 ClusterIP,請執行以下命令:
kubectl get service kube-dns -n kube-system -
若要確認 DNS 端點已公開且指向 CoreDNS Pod,請執行以下命令:
kubectl -n kube-system get endpoints kube-dns輸出範例:
NAME ENDPOINTS AGE kube-dns 192.168.2.218:53,192.168.3.117:53,192.168.2.218:53 + 1 more... 90d**注意:**如果端點清單是空的,請檢查 CoreDNS Pod 的 Pod 狀態。
-
請確認您的安全群組與網路存取控制清單 (網路 ACL) 不會在 Pod 與 CoreDNS 通訊時進行封鎖。
如需詳細資訊,請參閱為什麼我的 Pod 無法在 Amazon EKS 中連線至其他 Pod?
確認 kube-proxy Pod 正常運作
若要檢查 kube-proxy Pod 是否可存取叢集的 API 伺服器,請在日誌中檢查是否出現連線至控制平面的逾時錯誤。同時也請檢查是否出現 403 未授權錯誤。
若要取得 kube-proxy 的日誌,請執行以下命令:
kubectl logs -n kube-system --selector 'k8s-app=kube-proxy'
**注意:**kube-proxy 會從控制平面取得端點,並在每個節點上建立 iptables 規則。
檢查發生問題當下 CoreDNS Pod 的 CPU 使用量
Amazon EKS CoreDNS 附加元件只為 CoreDNS Pod 的記憶體新增 170 MiB 的配額。CoreDNS Pod 未定義 CPU 配額,因此容器可以使用其執行所在節點上的所有可用 CPU 資源。如果節點的 CPU 使用率達到 100%,您可能會在 Amazon EKS 應用程式日誌中看到 DNS 逾時錯誤。這是因為 CoreDNS Pod 沒有足夠的 CPU 資源來處理所有 DNS 查詢。
若要檢查 CoreDNS Pod 目前的 CPU 與記憶體使用量,請執行以下命令:
kubectl top pods -n kube-system -l k8s-app=kube-dns
若要檢查 Amazon EKS 叢集節點目前的 CPU 與記憶體使用量,請執行以下命令:
kubectl top nodes
連線至應用程式 Pod 以疑難排解 DNS 問題
請完成以下步驟:
-
若要在您的應用程式 Pod 內執行命令,請執行以下命令:
kubectl exec -it your-pod-name -- sh**注意:**請將 your-pod-name 替換為您的 Pod 名稱。
上述命令可讓您存取執行中 Pod 內的 Shell。如果應用程式 Pod 沒有可用的 Shell 二進位檔,您會收到類似以下範例的錯誤:
「OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown command terminated with exit code 126」
若要解決此問題,請在您的 pod-manifest.yaml 資訊清單檔案中,將所使用的映像更新為其他映像。其中一個範例映像是 Docker 網站上的 busybox。 -
若要確認 kube-dns 服務的叢集 IP 位址存在於您 Pod 的 /etc/resolv.conf 檔案中,請在 Pod Shell 內執行以下命令:
cat /etc/resolv.conf以下 resolv.conf 檔案範例顯示一個 Pod,其已設定將 10.100.0.10 作為 DNS 請求的目標。此 IP 位址必須與您的 kube-dns 服務的 ClusterIP 值相符:
nameserver 10.100.0.10 search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal options ndots:5**注意:**您可以使用 Pod 規格中的 dnsPolicy 欄位來管理 Pod 的 DNS 組態。如果您未填入此欄位,Amazon EKS 會預設使用 ClusterFirst DNS 政策。如需有關 ClusterFirst DNS 政策的詳細資訊,請參閱 Kubernetes 網站上的 Pod 的 DNS 政策。
-
若要確認您的 Pod 是否可使用預設的 ClusterIP 值來解析內部網域,請在 Pod Shell 內執行以下命令:
nslookup kubernetes.default 10.100.0.10輸出範例:
Server: 10.100.0.10 Address: 10.100.0.10#53 Name: kubernetes.default.svc.cluster.local Address: 10.100.0.1 -
若要確認您的 Pod 是否可使用預設的 ClusterIP 值來解析外部網域,請在 Pod Shell 內執行以下命令:
nslookup amazon.com 10.100.0.10輸出範例:
Server: 10.100.0.10 Address: 10.100.0.10#53 Non-authoritative answer: Name: amazon.com Address: 176.32.98.166 Name: amazon.com Address: 205.251.242.103 Name: amazon.com Address: 176.32.103.205 -
若要取得 kube-dns 端點,請執行以下命令:
kubectl get endpoints kube-dns -n kube-system -
若要確認您的 Pod 是否可直接使用 CoreDNS Pod IP 位址進行解析,請在 Pod Shell 內執行以下命令:
nslookup kubernetes COREDNS_POD_IP nslookup amazon.com COREDNS_POD_IP**注意:**請將 COREDNS_POD_IP 替換為 kube-dns 端點 IP 位址。
取得 CoreDNS Pod 更詳細的日誌以進一步偵錯問題
請完成以下步驟:
- 若要啟用 CoreDNS Pod 的偵錯日誌,並將 log 外掛程式新增至 CoreDNS ConfigMap,請執行以下命令:
**注意:**如需詳細資訊,請參閱 CoreDNS 網站上的日誌。kubectl -n kube-system edit configmap coredns - 在命令輸出的編輯器畫面中,新增以下日誌字串:
**注意:**CoreDNS 組態需要數分鐘才能重新載入。若要立即套用變更,請逐一重新啟動 Pod。kind: ConfigMap apiVersion: v1 data: Corefile: | .:53 { log # Activating CoreDNS Logging errors health kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure upstream fallthrough in-addr.arpa ip6.arpa } ... ... - 若要檢查 CoreDNS 日誌是否失敗或是否收到來自應用程式 Pod 的流量,請執行以下命令:
kubectl logs --follow -n kube-system --selector 'k8s-app=kube-dns'
更新 ndots 值
ndots 值是在進行初始絕對查詢之前,必須出現在網域名稱中才能解析查詢的點數。例如,您可以將非完整網域名稱的 ndots 設為預設的 5。在此情境中,所有不屬於 cluster.local 內部網域的外部網域,會在查詢前附加至搜尋網域。
以下範例顯示應用程式 Pod 的 /etc/resolv.conf 檔案設定:
nameserver 10.100.0.10search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal options ndots:5
在上述範例組態中,CoreDNS 會在查詢的網域中尋找五個點。如果 Pod 針對 amazon.com 進行 DNS 解析呼叫,您的日誌會類似以下範例:
[INFO] 192.168.3.71:33238 - 36534 "A IN amazon.com.default.svc.cluster.local. udp 54 false 512" NXDOMAIN qr,aa,rd 147 0.000473434s[INFO] 192.168.3.71:57098 - 43241 "A IN amazon.com.svc.cluster.local. udp 46 false 512" NXDOMAIN qr,aa,rd 139 0.000066171s [INFO] 192.168.3.71:51937 - 15588 "A IN amazon.com.cluster.local. udp 42 false 512" NXDOMAIN qr,aa,rd 135 0.000137489s [INFO] 192.168.3.71:52618 - 14916 "A IN amazon.com.ec2.internal. udp 41 false 512" NXDOMAIN qr,rd,ra 41 0.001248388s [INFO] 192.168.3.71:51298 - 65181 "A IN amazon.com. udp 28 false 512" NOERROR qr,rd,ra 106 0.001711104s
**注意:**NXDOMAIN 表示 Pod 未找到網域記錄。NOERROR 表示 Pod 已成功找到網域記錄。
在進行最後一次對絕對網域的呼叫之前,每個搜尋網域都會先附加 amazon.com 首碼。在結尾附加一個點 (.) 的最終網域名稱屬於完整網域名稱。每一次外部網域名稱查詢,可能會產生四到五次額外呼叫,進而讓 CoreDNS Pod 負載過高。
若要解決此問題,請將 ndots 變更為 1,只尋找一個點。或者,在您查詢或使用的網域結尾附加一個點。範例:
nslookup example.com.
檢查 AmazonProvidedDNS VPC 解析器配額
Amazon Virtual Private Cloud (Amazon VPC) 解析器對每個彈性網路介面,在一秒內可接受的最大配額為 1024 個封包。如果多個 CoreDNS Pod 位於同一個節點上,外部網域查詢時可能會達到此配額。
若要使用 PodAntiAffinity 規則將 CoreDNS Pod 排程至不同的執行個體,請在 CoreDNS 部署中新增以下選項:
podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: k8s-app operator: In values: - kube-dns topologyKey: kubernetes.io/hostname weight: 100
**注意:**如需 PodAntiAffinity 的詳細資訊,請參閱 Kubernetes 網站上的 Pod 之間的親和性與反親和性。
使用 tcpdump 從 Amazon EKS 工作節點擷取 CoreDNS 封包
若要診斷 DNS 解析問題,請完成以下步驟,使用 tcpdump 工具進行封包擷取:
-
若要找出正在執行 CoreDNS Pod 的工作節點,請執行以下命令:
kubectl get pod -n kube-system -l k8s-app=kube-dns -o wide -
若要使用 SSH 連線至工作節點並安裝 tcpdump 工具,請執行以下命令:
sudo yum install tcpdump - y -
若要在工作節點上找出 CoreDNS Pod 的程序 ID,請執行以下命令:
ps ax | grep coredns -
在工作節點上,請執行以下命令,以在 UDP 連接埠 53 上擷取 CoreDNS Pod 網路流量的封包:
sudo nsenter -n -t PID tcpdump udp port 53 -
在另一個終端中,請執行以下命令以取得 CoreDNS 服務與 Pod IP 位址:
kubectl describe svc kube-dns -n kube-system**注意:**請記下 IP 欄位中的服務 IP 位址,以及 Endpoints 欄位中的 Pod IP 位址。
-
啟動一個 Pod 以測試 DNS 服務。以下範例使用 Ubuntu 容器映像:
kubectl run ubuntu --image=ubuntu sleep 1d kubectl exec -it ubuntu sh -
請執行以下命令,使用 nslookup 工具對 amazon.com 網域執行 DNS 查詢:
nslookup amazon.com若要明確對 CoreDNS 服務 IP 位址執行相同的查詢,請執行以下命令:
nslookup amazon.com COREDNS_SERVICE_IP**注意:**請將 COREDNS_SERVICE_IP 替換為您的 CoreDNS 服務 IP 位址。
若要對每個 CoreDNS Pod IP 位址執行查詢,請執行以下命令:nslookup amazon.com COREDNS_POD_IP**注意:**請將 COREDNS_POD_IP 替換為您的 CoreDNS Pod IP 位址。如果您執行多個 CoreDNS Pod,請執行多次查詢。如此一來,Amazon EKS 會至少將一個查詢傳送至您正在擷取流量的 Pod。
-
檢視封包擷取結果。
如果 CoreDNS Pod 發生 DNS 查詢逾時,且您在封包擷取中未看到該查詢,請檢查您的網路連線。檢查工作節點之間的網路可達性。
如果您在未擷取的 Pod IP 位址上看到 DNS 查詢逾時,請在相關的工作節點上執行另一個封包擷取。
若要儲存封包擷取結果,請在 tcpdump 命令中加入 -w FILE_NAME 旗標。以下範例會將結果寫入 capture.pcap 檔案:tcpdump -w capture.pcap udp port 53
相關資訊
Kubernetes 網站上的 Kubernetes 叢集 DNS 的 CoreDNS 正式推出
- 語言
- 中文 (繁體)

相關內容
- 已提問 3 年前
- 已提問 2 年前
