排解 GKE 中的 Cloud DNS 問題


本頁面說明如何解決 Google Kubernetes Engine (GKE) 中的 Cloud DNS 問題。

找出 Cloud DNS 中的 DNS 問題來源

如果發生 dial tcp: i/o timeoutno such hostCould not resolve host 等錯誤,通常表示 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

如果現有叢集啟用 Cloud DNS 後,Pod 仍使用 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 位址。

後續步驟