如何對使用 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。
完成下列步驟:
-
取得 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 狀態。
-
確認安全群組或網路存取控制清單 (network ACL) 在 Pod 與 CoreDNS 通訊時未封鎖 Pod。
如需詳細資訊,請參閱為什麼我的 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 區域的 CPU 使用率
Amazon EKS CoreDNS 附加元件只為 CoreDNS Pod 的記憶體增加 170Mi 限制。CoreDNS 網站不定義 CPU 限制,因此容器可以使用它執行的節點上的所有可用 CPU 資源。如果節點 CPU 使用率達到 100%,則 Amazon EKS 應用程式日誌中可能會出現 DNS 逾時錯誤。這是因為 CoreDNS Pod 沒有足夠的 CPU 資源來處理所有 DNS 查詢。
連線至應用程式 Pod 以疑難排解 DNS 問題
完成下列步驟:
-
若要在應用程式 Pod 內執行命令,請執行下列命令以存取執行中 Pod 內的 Shell:
$ kubectl exec -it your-pod-name -- sh
如果應用程式 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
若要偵錯,請更新在清單檔案中使用的映像檔以取得其他映像檔,例如 Docker 網站上的 busybox 映像檔。
-
確認 kube-dns 服務的叢集 IP 地址是否位於 Pod 站的 /etc/resolv.conf 檔案中。在 Pod 內的 shell 中執行以下命令:
cat /etc/resolv.conf
下列範例 resolv.conf 檔案顯示設定為針對 DNS 請求指向 10.100.0.10 的 Pod。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 組態。如果未填入此欄位,則預設會使用 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
-
確認您的網域是否可以使用 CoreDNS Pod的 IP 地址直接解析。在 Pod 內的 shell 中執行下列命令:
nslookup kubernetes COREDNS_POD_IP nslookup amazon.com COREDNS_POD_IP
**注意:**將 COREDNS_POD_IP 取代為 kubectl get 端點中的一個端點 IP 地址。
從 CoreDNS Pod 取得更詳細的日誌以進行偵錯
完成下列步驟:
-
開啟 CoreDNS Pod 的偵錯日誌,然後將日誌外掛程式新增至 CoreDNS ConfigMap:
kubectl -n kube-system edit configmap coredns
**注意:**如需詳細資訊,請參閱 CoreDNS 網站上的日誌外掛程式。
-
在輸出中出現的編輯器畫面中,新增日誌字串:
kind: ConfigMap apiVersion: v1 data: Corefile: | .:53 { log # Enabling CoreDNS Logging errors health kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure upstream fallthrough in-addr.arpa ip6.arpa } ... ...
**注意:**重新載入組態 CoreDNS 需要幾分鐘。若要立即套用變更,請逐一重新啟動 POD。
-
檢查 CoreDNS 日誌是否失敗或從應用程序區域中獲得任何點擊:
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.10 search 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 表示找不到網域記錄,而 NOERROR 表示找到網域記錄。
在最後針對絕對網域進行最終呼叫之前,每個搜尋網域都冠上了 amazon.com。在結尾附加點 (.) 的最終網域名稱是一個完全合格的域名。因此,對於每個外部網域名稱查詢,可能會有四到五個額外的呼叫,這可能會讓 CoreDNS Pod 不堪重負。
若要解決此問題,請將 ndots 變更為 1,就只要尋找單一個點。或者,在您查詢或使用的網域末尾附加一個點 (.):
nslookup example.com.
考慮 VPC 解析程式 (AmazonProvidedDNS) 限制
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 連線至正在執行 CoreDNS Pod 的工作節點,然後安裝 tcpdump 工具:
sudo yum install tcpdump –y
-
尋找工作節點上的 CoreDNS Pod 程序 ID:
ps ax | grep coredns
-
從工作節點,在 CoreDNS Pod 網路上執行封包擷取,以監控 UDP 連接埠 53 上的網路流量:
sudo nsenter -n -t PID tcpdump udp port 53
-
從單獨的終端,取得 CoreDNS 服務和 Pod IP 地址:
kubectl describe svc kube-dns -n kube-system
注意:記下位於 IP 欄位中的服務 IP,以及位於端點欄位中的 Pod IP。
-
啟動 Pod 來測試 DNS 服務。下列範例使用 Ubuntu 容器映像檔:
kubectl run ubuntu --image=ubuntu sleep 1d kubectl exec -it ubuntu sh
-
使用 nslookup 工具針對一個網域執行 DNS 查詢,如 amazon.com:
nslookup amazon.com
針對 CoreDNS 服務 IP 地址明確執行相同的查詢:
nslookup amazon.com COREDNS_SERVICE_IP
針對每個 CoreDNS Pod IP 地址執行查詢:
nslookup amazon.com COREDNS\_POD\_IP
**注意:**如果您有多個 CoreDNS Pod 在執行,請執行多個查詢,以便至少將一個查詢傳送至您要從中擷取流量的 Pod。
-
檢閱封包擷取結果。
如果您受監控的 CoreDNS Pod 遇到 DNS 查詢逾時,而且您在封包擷取中看不到查詢,請檢查您的網路連線。請務必檢查工作節點之間的網路連線能力。
如果您看到針對未擷取的 Pod IP 地址的 DNS 查詢逾時,請在相關工作節點上執行另一個封包擷取。
若要儲存封包擷取的結果,請在 tcpdump 命令中新增 -w FILE_NAME 旗標。下列範例會將結果寫入名為 capture.pcap 的檔案:
tcpdump -w capture.pcap udp port 53
相關資訊
適用於 Kubernetes 叢集 DNS 的 CoreDNS GA
(Kubernetes 網站上)
相關內容
- 已提問 4 個月前lg...
- AWS 官方已更新 1 年前
- AWS 官方已更新 2 年前
- AWS 官方已更新 2 年前
- AWS 官方已更新 2 年前