排查 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: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 文档中的修补资源记录集部分,更新这些记录。

验证响应政策

验证您的回复政策是否存在且命名正确:

  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 虚拟机解析 GKE 集群服务

如果您无法从 Compute Engine 虚拟机解析 GKE 集群服务,请验证集群的 Cloud DNS 范围

您在 Cloud DNS 中使用的范围决定了可以解析哪些资源:

  • 集群范围:DNS 解析仅限于 Kubernetes 集群的资源(Pod 和 Service)。这是默认设置,适用于您无需解析 Kubernetes 集群或 GKE Virtual Private Cloud (VPC) 之外的外部资源的情况。

  • VPC 范围:DNS 解析会扩展到整个 VPC,包括 Compute Engine 虚拟机等资源。这样,集群就可以解析 GKE 集群外部但位于同一 VPC 内的资源的内部 DNS 记录,例如 Google Cloud VM。

如需验证集群的 Cloud DNS 范围,请完成以下步骤:

  1. 在 Google Cloud 控制台中,前往 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 要求使用 VPC 范围的集群使用 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 额外的 VPC 范围的集群

请确保您使用的版本正确无误。Cloud DNS 额外的 VPC 范围需要 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.

如需解决此问题,请完成以下步骤:

  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 Policy Analyzer 获取具有 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 地址。

后续步骤