如果 Pod 無法連線至服務,且 Google Kubernetes Engine (GKE) 叢集使用 Cloud DNS 做為 DNS 供應商,您可能會遇到 dial tcp: i/o timeout 或 no such host 等錯誤。這類錯誤通常表示 Cloud DNS 設定有問題,例如私人區域設定錯誤或 Cloud DNS 範圍不正確。
本頁面說明如何診斷及解決使用 GKE 代管型 Cloud DNS 服務時的常見問題,確保工作負載的 DNS 解析作業穩定可靠。
平台管理員和營運人員,以及設定及管理 GKE 和 Cloud DNS 整合的網路專家,都必須瞭解這項資訊。如果應用程式開發人員遇到服務探索問題,這項工具也很有幫助。如要進一步瞭解我們在 Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見的 GKE 使用者角色和工作」。
找出 Cloud DNS 的 DNS 問題來源
以下各節有助於診斷 Cloud DNS 無法解析查詢的原因。
確認基本設定
如果 Pod 無法解析 DNS 查詢,請確認 Cloud DNS 的設定符合需求。本節將協助您確認是否使用 Cloud DNS、確認 GKE 叢集是否有私人 DNS 區域,以及確保目標服務的 DNS 記錄正確無誤。
如要驗證這些設定,請完成下列指令:
查看 Pod 使用的 DNS 伺服器:
kubectl exec -it POD_NAME -- cat /etc/resolv.conf | grep nameserver將
POD_NAME替換為 DNS 解析發生問題的 Pod 名稱。如果您使用的是 Cloud DNS,輸出內容如下:
nameserver 169.254.169.254如果看到其他值,表示您並未使用 Cloud DNS。確認 Cloud DNS 已正確啟用。
確認受管理區域是否存在:
gcloud dns managed-zones list --format list輸出結果會與下列內容相似:
- creationTime: 2021-02-12T19:24:37.045Z description: Private zone for GKE cluster "" with cluster suffix "CLUSTER_DOMAIN" in project "PROJECT_ID" dnsName: CLUSTER_DOMAIN. id: 5887499284756055830 kind: dns#managedZone name: gke-CLUSTER_NAME-aa94c1f9-dns nameServers: ['ns-gcp-private.googledomains.com.'] privateVisibilityConfig: {'kind': 'dns#managedZonePrivateVisibilityConfig'} visibility: private這項輸出內容包含下列值:
CLUSTER_DOMAIN:系統自動指派給叢集的 DNS 網域字尾。PROJECT_ID:您的專案 ID。CLUSTER_NAME:具有私人區域的叢集名稱。
在這個輸出內容中,「
name」欄位的值顯示Google Cloud 已建立名為gke-CLUSTER_NAME-aa94c1f9-dns的區域。如果沒有看到代管區域,表示叢集未建立私人區域,或您可能未正確通過驗證。如要排解問題,請參閱 Cloud DNS 說明文件中的「私人區域」。
驗證服務的 DNS 記錄:
gcloud dns record-sets list --zone ZONE_NAME | grep SERVICE_NAME更改下列內容:
ZONE_NAME:私人區域的名稱。SERVICE_NAME:Service 的名稱。
輸出內容大致如下:
dns-test.default.svc.cluster.local. A 30 10.47.255.11這項輸出內容顯示 Cloud DNS 包含網域
dns-test.default.svc.cluster.local.的 A 記錄,且叢集的 IP 位址為10.47.255.11。如果記錄有誤,請參閱 Cloud DNS 說明文件中的「修補資源記錄集」,更新記錄。
驗證回應政策
確認回應政策存在且名稱正確:
查看所有回應政策的清單:
gcloud dns response-policies list --format="table(responsePolicyName, description)"輸出結果會與下列內容相似:
RESPONSE_POLICY_NAME DESCRIPTION gke-CLUSTER_NAME-52c8f518-rp Response Policy for GKE cluster "CLUSTER_NAME" with cluster suffix "cluster.local." in project "gke-dev" with scope "CLUSTER_SCOPE".在這個輸出內容中,
gke-CLUSTER_NAME-52c8f518-rp表示Google Cloud 建立名為gke-CLUSTER_NAME-aa94c1f9-rp的私人區域。Google Cloud 建立的回應政策會加上gke-前置字元。查看特定私人區域中的回應政策:
gcloud dns response-policies rules list ZONE_NAME \ --format="table(localData.localDatas[0].name, localData.localDatas[0].rrdatas[0])"將
ZONE_NAME替換為發生問題的私人區域名稱。輸出結果會與下列內容相似:
1.240.27.10.in-addr.arpa. kubernetes.default.svc.cluster.local. 52.252.27.10.in-addr.arpa. default-http-backend.kube-system.svc.cluster.local. 10.240.27.10.in-addr.arpa. kube-dns.kube-system.svc.cluster.local. 146.250.27.10.in-addr.arpa. metrics-server.kube-system.svc.cluster.local.第一欄會顯示規則比對的 IP 位址或網域名稱模式。第二欄是與 IP 位址相關聯的主機名稱。
如果發現這些指令的輸出內容有任何問題,請參閱 Cloud DNS 說明文件中的「更新回應政策規則」一節。
使用記錄、資訊主頁和指標進行調查
Cloud DNS 提供多種記錄和監控選項,協助您進一步調查 DNS 問題:
如要查看區域和記錄等資源的記錄,請啟用 Cloud DNS 的 Cloud Logging。
如要查看 DNS 查詢圖表,以及私人區域的錯誤率、每秒查詢次數和第 99 個百分位數延遲時間資料,請使用 Cloud DNS 監控資訊主頁。
如要以視覺化方式呈現 DNS 查詢的延遲時間和成功率,請在 Metrics Explorer 中使用
query/latencies和query/response_count指標。
查看是否有新記錄
查看記錄,確認代管 Cloud DNS 私人區域中是否建立任何新記錄。如果叢集突然發生 DNS 解析失敗的情況,這項功能就很有幫助。
如要檢查是否有新記錄,請完成下列步驟:
前往 Google Cloud 控制台的「Logs Explorer」頁面。
在查詢窗格中,輸入下列查詢:
resource.type="dns_managed_zone" protoPayload.request.change.additions.name="headless-svc-stateful.default.svc.cluster.local." protoPayload.methodName="dns.changes.create"點選「執行查詢」。
查看輸出內容。如果發現變更與您首次注意到錯誤的時間相符,請考慮還原這些變更。
驗證自訂虛設常式網域和名稱伺服器
如果您使用 GKE Standard 叢集,並搭配自訂存根網域或上游名稱伺服器,請檢查 ConfigMap 並確認值是否正確。
Cloud DNS 會將 stubDomains 和 upstreamNameservers 值轉換為 Cloud DNS 轉送區域。這些資源由 Google 管理,因此如果發現任何錯誤,請與 Cloud Customer Care 團隊聯絡,尋求協助。
與 Cloud Customer Care 團隊聯絡
如果已完成上述各節的步驟,但仍無法診斷問題原因,請與 Cloud Customer Care 團隊聯絡。
解決特定錯誤
如果遇到特定錯誤或問題,請參考下列各節的建議。
問題:無法從 Compute Engine VM 解析 GKE 叢集 Service
如果無法從 Compute Engine VM 解析 GKE 叢集服務,請確認叢集的 Cloud DNS 範圍。
您在 Cloud DNS 中使用的範圍會決定可解析的資源:
叢集範圍:DNS 解析僅限於 Kubernetes 叢集「內」的資源 (Pod 和服務)。這是預設設定,如果您不需要解析 Kubernetes 叢集或 GKE 虛擬私有雲 (VPC) 外部的資源,就適合使用這項設定。
虛擬私有雲範圍:DNS 解析會擴展到整個虛擬私有雲,包括 Compute Engine VM 等資源。這樣一來,叢集就能解析 GKE 叢集外部,但位於相同虛擬私有雲內資源 (例如 Google Cloud VM) 的內部 DNS 記錄。
如要驗證叢集的 Cloud DNS 範圍,請完成下列步驟:
前往 Google Cloud 控制台的「Kubernetes clusters」(Kubernetes 叢集) 頁面。
按一下發生 DNS 問題的叢集名稱。
在叢集詳細資料頁面的「Cluster networking」(叢集網路) 部分,查看「DNS provider」(DNS 供應商) 列中的資訊。
如果看到「Cloud DNS (cluster scope)」(Cloud DNS (叢集範圍)),代表您使用的是叢集範圍。如要變更 DNS 範圍,請使用適當的 DNS 範圍重新建立叢集。
問題:啟用 Cloud DNS 後,Pod 仍使用 kube-dns
如果 Pod 在現有叢集啟用 Cloud DNS 後仍使用 kube-dns,請確認您在叢集啟用 Cloud DNS 後,已升級或重新建立節點集區。完成這個步驟前,Pod 會繼續使用 kube-dns。
問題:無法更新現有叢集,或建立已啟用 Cloud DNS 的叢集
請確認您使用的是正確版本。如要使用 Cloud DNS for GKE,叢集必須採用虛擬私有雲範圍,且 GKE 版本為 1.19 以上,或採用叢集範圍,且 GKE 版本為 1.24.7-gke.800、1.25.3-gke.700 以上。
問題:在叢集上啟用 Cloud DNS 後,節點上的 DNS 查詢失敗
如果您在具有自訂存根網域或上游名稱伺服器的 GKE 叢集中啟用叢集範圍 Cloud DNS,自訂設定會同時套用至叢集中的節點和 Pod,因為 Cloud DNS 無法區分 Pod 和節點 DNS 要求。如果自訂上游伺服器無法解析查詢,節點上的 DNS 查詢可能會失敗。
問題:無法更新或建立已啟用 Cloud DNS 附加型虛擬私有雲範圍的叢集
請確認您使用的是正確版本。Cloud DNS 附加型虛擬私有雲範圍需要 GKE 1.28 以上版本。
錯誤:Cloud DNS 已停用
停用 Cloud DNS API 時,會發生下列事件:
Warning FailedPrecondition service/default-http-backend
Failed to send requests to Cloud DNS: Cloud DNS API Disabled. Please enable the Cloud DNS API in your project PROJECT_NAME: Cloud DNS API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/dns.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
發生這項錯誤的原因是 Cloud DNS API 預設為停用。您必須手動啟用 Cloud DNS API。
如要解決這個問題,請啟用 Cloud DNS API。
錯誤:無法傳送要求至 Cloud DNS:超出 API 頻率限制。
如果專案超出 Cloud DNS 配額或限制,就會發生下列事件:
kube-system 27s Warning InsufficientQuota
managedzone/gke-cluster-quota-ee1bd2ca-dns Failed to send requests to Cloud DNS: API rate limit exceeded. Contact Google Cloud support team to request a quota increase for your project PROJECT_NAME: Quota exceeded for quota metric 'Write requests' and limit 'Write limit for a minute for a region' of service 'dns.googleapis.com' for consumer 'project_number:PROJECT_NUMBER.
如要解決這個問題,請查看「Cloud DNS 配額」和「Compute Engine 配額與限制」。您可以使用 Google Cloud 控制台提高配額。
錯誤:由於先前發生錯誤,無法將要求傳送至 Cloud DNS
如果錯誤導致連鎖性故障,就會發生下列事件:
kube-system 27s Warning InsufficientQuota
managedzone/gke-cluster-quota-ee1bd2ca-dns Failed to send requests to Cloud DNS: API rate limit exceeded. Contact Google Cloud support team to request a quota increase for your project PROJECT_NAME: Quota exceeded for quota metric 'Write requests' and limit 'Write limit for a minute for a region' of service 'dns.googleapis.com' for consumer 'project_number:PROJECT_NUMBER.
kube-system 27s Warning FailedPrecondition service/default-http-backend Failed to send requests to Cloud DNS due to a previous error. Please check the cluster events.
如要解決這個問題,請查看叢集事件,找出原始錯誤的來源,並按照操作說明解決根本問題。
在上述範例中,代管區域的 InsufficientQuota 錯誤觸發了連鎖故障。第二個 FailedPrecondition 錯誤表示先前發生錯誤,也就是初始配額不足的問題。如要解決這個範例問題,請按照 Cloud DNS 配額錯誤的指引操作。
錯誤:無法繫結回應政策
當回應政策繫結至叢集網路,且 Cloud DNS for GKE 嘗試將回應政策繫結至網路時,會發生下列事件:
kube-system 9s Warning FailedPrecondition responsepolicy/gke-2949673445-rp
Failed to bind response policy gke-2949673445-rp to test. Please verify that another Response Policy is not already associated with the network: Network 'https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/global/networks/NETWORK_NAME' cannot be bound to this response policy because it is already bound to another response policy.
kube-system 9s Warning FailedPrecondition service/kube-dns
Failed to send requests to Cloud DNS due to a previous error. Please check the cluster events.
如要解決這個問題,請完成下列步驟:
取得繫結至網路的回應政策:
gcloud dns response-policies list --filter='networks.networkUrl: NETWORK_URL'將
NETWORK_URL替換為錯誤中的網路網址,例如https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/NETWORK_NAME。如果輸出內容為空白,回應政策可能不在同一個專案中。 請前往下一個步驟,搜尋回應政策。
如果輸出內容與下列內容相似,請跳至步驟 4,刪除回應政策。
[ { "description": "Response Policy for GKE cluster \"CLUSTER_NAME\" with cluster suffix \"cluster.local.\" in project \"PROJECT_ID\" with scope \"CLUSTER_SCOPE\".", ... "kind": "dns#responsePolicy", "responsePolicyName": "gke-CLUSTER_NAME-POLICY_ID-rp" } ]使用 IAM 政策分析工具,取得具備
dns.networks.bindDNSResponsePolicy權限的專案清單。檢查各項專案是否有繫結至網路的回應政策:
gcloud dns response-policies list --filter='networks.networkUrl:NETWORK_URL' \ --project=PROJECT_NAME
錯誤:kube-dns 中指定的設定無效
套用不適用於 GKE Cloud DNS 的自訂 kube-dns ConfigMap 時,會發生下列事件:
kube-system 49s Warning FailedValidation configmap/kube-dns
Invalid configuration specified in kube-dns: error parsing stubDomains for ConfigMap kube-dns: dnsServer [8.8.8.256] validation: IP address "8.8.8.256" invalid
如要解決這個問題,請查看 ConfigMap 無效部分的錯誤詳細資料。在上述範例中,8.8.8.256 不是有效的 IP 位址。
後續步驟
如需診斷 Kubernetes DNS 問題的一般資訊,請參閱「偵錯 DNS 解析」。
請參閱「排解 Cloud DNS 問題」。
如果無法在文件中找到問題的解決方案,請參閱「取得支援」一文,取得進一步協助,包括下列主題的建議:
- 與 Cloud Customer Care 聯絡,建立客服案件。
- 在 StackOverflow 提問,並使用
google-kubernetes-engine標記搜尋類似問題,向社群尋求支援。你也可以加入#kubernetes-engineSlack 頻道,取得更多社群支援。 - 使用公開 Issue Tracker 提出問題或功能要求。