排解 GKE 中的 Cloud DNS 問題


如果 Pod 無法連線至服務,且 Google Kubernetes Engine (GKE) 叢集使用 Cloud DNS 做為 DNS 供應商,您可能會遇到 dial tcp: i/o timeoutno 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 記錄正確無誤。

如要驗證這些設定,請完成下列指令:

  1. 檢查 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 已正確啟用

  2. 確認受管理區域存在:

    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 說明文件中的私人區域

  3. 驗證服務的 DNS 記錄:

    gcloud dns record-sets list --zone ZONE_NAME | grep SERVICE_NAME
    

    更改下列內容:

    • ZONE_NAME:私人區域的名稱。
    • SERVICE_NAME:服務名稱。

    輸出結果大致如下:

    dns-test.default.svc.cluster.local.                A     30     10.47.255.11
    

    這項輸出內容顯示 Cloud DNS 含有網域的 A 記錄 dns-test.default.svc.cluster.local.,且叢集的 IP 位址為 10.47.255.11

    如果記錄有誤,請參閱 Cloud DNS 說明文件中的「修補資源記錄集」一節,瞭解如何更新記錄。

驗證回覆政策

確認回覆政策存在且名稱正確:

  1. 查看所有回覆政策的清單:

    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- 前置字元。

  2. 查看特定私有區域中的回應政策:

    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 私人區域中是否已建立任何新記錄。如果叢集突然發生 DNS 解析失敗的情況,這項功能就很有幫助。

如要檢查是否有新記錄,請完成下列步驟:

  1. 前往 Google Cloud 控制台的「Logs Explorer」頁面。

    前往記錄檔探索工具

  2. 在查詢窗格中,輸入下列查詢:

    resource.type="dns_managed_zone"
    protoPayload.request.change.additions.name="headless-svc-stateful.default.svc.cluster.local."
    protoPayload.methodName="dns.changes.create"
    
  3. 點選「執行查詢」

  4. 查看輸出內容。如果發現變更與您首次發現錯誤的時間相符,請考慮還原變更。

驗證自訂存根網域和名稱伺服器

如果您使用 GKE Standard 叢集,並搭配自訂存根網域或上游名稱伺服器,請檢查 ConfigMap 並確認值正確無誤。

Cloud DNS 會將 stubDomainsupstreamNameservers 值轉換為 Cloud DNS 轉送區域。這些資源由 Google 管理,因此如果發現任何錯誤,請與 Cloud Customer Care 團隊聯絡,尋求協助。

與 Cloud Customer Care 聯絡

如果已完成上述各節的步驟,但仍無法診斷問題原因,請與 Cloud Customer Care 團隊聯絡

解決特定錯誤

如果遇到特定錯誤或問題,請參閱下列各節的建議。

問題:無法從 Compute Engine VM 解析 GKE 叢集服務

如果無法從 Compute Engine VM 解析 GKE 叢集服務,請確認叢集的 Cloud DNS 範圍

您在 Cloud DNS 中使用的範圍會決定可解析的資源:

  • 叢集範圍:DNS 解析僅限於 Kubernetes 叢集「內」的資源 (Pod 和服務)。這是預設設定,如果您不需要解析 Kubernetes 叢集或 GKE 虛擬私有雲 (VPC) 外部的資源,就適合使用這項設定。

  • 虛擬私有雲範圍:DNS 解析會擴展至整個虛擬私有雲,包括 Compute Engine VM 等資源。這樣一來,叢集就能解析 GKE 叢集外部但位於同一虛擬私有雲內的資源 (例如 Google Cloud 虛擬機器) 的內部 DNS 記錄。

如要驗證叢集的 Cloud DNS 範圍,請完成下列步驟:

  1. 在 Google Cloud 控制台中,前往「Kubernetes clusters」(Kubernetes 叢集) 頁面。

    前往 Kubernetes 叢集

  2. 按一下發生 DNS 問題的叢集名稱。

  3. 在叢集詳細資料頁面的「叢集網路」部分,查看「DNS 供應商」列中的資訊。

  4. 如果看到「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 以上版本 (適用於使用 VPC 範圍的叢集),或是 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 配額錯誤的指南操作。

錯誤:無法繫結回應政策

當回應政策繫結至叢集網路,且 GKE 適用的 Cloud DNS 嘗試將回應政策繫結至網路時,會發生下列事件:

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.

如要解決這個問題,請完成下列步驟:

  1. 取得繫結至網路的回應政策:

    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"
       }
    ]
    
  2. 使用 IAM 政策分析器,取得具有 dns.networks.bindDNSResponsePolicy 權限的專案清單。

  3. 檢查每個專案是否都有繫結至網路的回應政策:

    gcloud dns response-policies list --filter='networks.networkUrl:NETWORK_URL' \
        --project=PROJECT_NAME
    
  4. 刪除回應政策

錯誤:kube-dns 中指定的設定無效

套用不適用於 Cloud DNS for GKE 的自訂 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 位址。

後續步驟