排查从 Pod 内部出现的 DNS 解析故障,但不从工作节点进行排查。

本文讨论在尝试从 Microsoft Azure Kubernetes 服务 (AKS) 群集建立出站连接时,如何排查从 Pod 内部(而不是从辅助角色节点)发生的域名系统(DNS)解析失败问题。

先决条件

背景

对于 DNS 解析,Pod 会将请求发送到 kube-system 命名空间中的 CoreDNS 容器。

如果 DNS 查询用于内部组件(例如服务名称),则 CoreDNS Pod 会自行响应。 但是,如果请求适用于外部域,CoreDNS Pod 会将请求发送到上游 DNS 服务器。

上游 DNS 服务器基于运行 Pod 的工作节点的 resolv.conf 文件获取。 resolv.conf 文件 (/run/systemd/resolve/resolv.conf) 将根据运行工作器节点的虚拟网络的 DNS 设置更新 。

故障排除清单

若要从 Pod 中排查 DNS 问题,请使用以下部分中的说明。

步骤 1:排查 Pod 中的 DNS 故障

可以使用 kubectl 命令从 Pod 中排查 DNS 问题,如以下步骤所示:

  1. 验证 CoreDNS Pod 是否正在运行:

    kubectl get pods -l k8s-app=kube-dns -n kube-system
    
  2. 检查 CoreDNS 容器组是否超负荷运行。

    $ kubectl top pods -n kube-system -l k8s-app=kube-dns
    NAME                      CPU(cores)   MEMORY(bytes)
    coredns-dc97c5f55-424f7   3m           23Mi
    coredns-dc97c5f55-wbh4q   3m           25Mi
    
  3. 验证托管 CoreDNS Pod 的节点是否未过度使用。 此外,获取托管 CoreDNS Pod 的节点:

    kubectl get pods -n kube-system -l k8s-app=kube-dns -o jsonpath='{.items[*].spec.nodeName}'
    
  4. 检查这些节点的使用情况:

    kubectl top nodes
    
  5. 验证 CoreDNS Pod 的日志:

    kubectl logs -l k8s-app=kube-dns -n kube-system
    

注释

若要查看更多调试信息,请启用 CoreDNS 中的详细日志。 若要在 CoreDNS 中启用详细日志记录,请参阅 AKS 中的 CoreDNS 自定义疑难解答

步骤 2:创建测试“Pod”以运行命令

如果 DNS 解析失败,请执行以下步骤:

  1. 在与有问题的 Pod 相同的命名空间中运行测试 Pod

  2. 在集群中启动一个测试 Pod。

    kubectl run -it --rm aks-ssh --namespace <namespace> --image=debian:stable
    

    测试 Pod 运行时,你将获得对 Pod 的访问权限。

  3. 运行以下命令安装所需的包:

    apt-get update -y
    apt-get install dnsutils -y
    
  4. 验证 resolv.conf 文件是否具有正确的条目:

    cat /etc/resolv.conf
    search default.svc.cluster.local svc.cluster.local cluster.local 00idcnmrrm4edot5s2or1onxsc.bx.internal.cloudapp.net
    nameserver 10.0.0.10
    options ndots:5
    
  5. host使用命令确定 DNS 请求是否正在路由到上游服务器:

    $ host -a microsoft.com
    Trying "microsoft.com.default.svc.cluster.local"
    Trying "microsoft.com.svc.cluster.local"
    Trying "microsoft.com.cluster.local"
    Trying "microsoft.com.00idcnmrrm4edot5s2or1onxsc.bx.internal.cloudapp.net"
    Trying "microsoft.com"
    Trying "microsoft.com"
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62884
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 27, AUTHORITY: 0, ADDITIONAL: 5
    
    ;; QUESTION SECTION:
    ;microsoft.com.                 IN      ANY
    
    ;; ANSWER SECTION:
    microsoft.com.          30      IN      NS      ns1-39.azure-dns.com.
    ...
    ...
    ns4-39.azure-dns.info.  30      IN      A       13.107.206.39
    
    Received 2121 bytes from 10.0.0.10#53 in 232 ms
    
  6. 检查 Pod 中的上游 DNS 服务器,以确定 DNS 解析是否正常工作。 例如,对于 Azure DNS,请运行以下 nslookup 命令:

    $ nslookup microsoft.com 168.63.129.16
    Server:         168.63.129.16
    Address:        168.63.129.16#53
    ...
    ...
    Address: 20.81.111.85
    

步骤 3:在显式指定上游 DNS 服务器时,检查 DNS 请求是否正常工作

如果在显式指定上游 DNS 服务器时来自 Pod 的 DNS 请求正常工作,请验证以下条件:

  1. 检查是否存在 CoreDNS 的自定义 ConfigMap:

    kubectl describe cm coredns-custom -n kube-system
    

    如果存在自定义 ConfigMap,请验证配置是否正确。 有关详细信息,请参阅 使用 Azure Kubernetes 服务自定义 CoreDNS

  2. 检查网络策略是否阻止用户数据报协议 (UDP) 端口 53 上的流量流向命名空间中的 kube-system CoreDNS Pod。

  3. 检查 CoreDNS Pod 是否位于不同的节点池(系统节点池)。 如果是,请检查网络安全组(NSG)是否与阻止 UDP 端口 53 上的流量的系统节点池相关联。

  4. 检查虚拟网络最近是否已更新以添加新的 DNS 服务器。

    如果发生虚拟网络更新,请检查是否也发生了以下事件之一:

    • 节点已重启。
    • 节点中的网络服务已重启。

    若要使 DNS 设置中的更新生效,必须重启节点上的网络服务和 CoreDNS Pod。 若要重启网络服务或 Pod,请使用以下方法之一:

    • 重启节点。

    • 扩展新节点。 (新节点将具有更新的配置。

    • 在节点中重启网络服务,然后重启 CoreDNS Pod。 执行以下步骤:

      1. 建立与节点的SSH连接。 有关详细信息,请参阅连接到 Azure Kubernetes 服务 (AKS) 群集节点以进行维护或故障排除

      2. 从节点内部重启网络服务:

        systemctl restart systemd-networkd
        
      3. 检查设置是否已更新:

        cat /run/systemd/resolve/resolv.conf
        
      4. 重启网络服务后,使用 kubectl 重启 CoreDNS Pod:

        kubectl delete pods -l k8s-app=kube-dns -n kube-system
        
  5. 检查是否在虚拟网络 DNS 设置中指定了多个 DNS 服务器。

    如果在 AKS 虚拟网络中指定了多个 DNS 服务器,则会发生以下序列之一:

    • AKS 节点将请求作为序列的一部分发送到上游 DNS 服务器。 在此序列中,请求将发送到虚拟网络中配置的第一个 DNS 服务器(如果 DNS 服务器可访问且正在运行)。 如果第一个 DNS 服务器无法访问且未响应,则请求将发送到下一个 DNS 服务器。

      AKS 节点使用 解析程序 命令将请求发送到 DNS 服务器。 可以在 AKS 节点中的 /run/systemd/resolve/resolve.conf 中找到此解析程序的配置文件。

      是否存在多个服务器? 在这种情况下,解析程序库按列出的顺序对其进行查询。 (使用的策略是首先尝试一个名称服务器。如果查询超时,则尝试下一个,依此类推,直到名称服务器列表用尽。然后,查询将继续尝试连接至名称服务器,直到达到最大重试次数为止。)

    • CoreDNS 使用 转发 插件将请求发送到上游 DNS 服务器。 此插件使用随机算法来选择上游 DNS 服务器。 在此序列中,请求可以转到虚拟网络中提及的任何 DNS 服务器。 例如,你可能会收到以下输出:

      $ kubectl describe cm coredns -n kube-system
      Name:         coredns
      Namespace:    kube-system
      Labels:       addonmanager.kubernetes.io/mode=Reconcile
                    k8s-app=kube-dns
                    kubernetes.io/cluster-service=true
      Annotations:  <none>
      
      Data
      ====
      Corefile:
      ----
      .:53 {
          errors
          ready
          health
          kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
          }
          prometheus :9153
          forward . /etc/resolv.conf                            # Here!
          cache 30
          loop
          reload
          loadbalance
          import custom/*.override
      }
      import custom/*.server
      
      
      BinaryData
      ====
      
      Events:  <none>
      

    在 CoreDNS forward 插件中,policy 指定用于选择上游服务器的策略。 下表中定义了这些策略。

    策略名称 DESCRIPTION
    random 实现随机上游选择的策略。 此策略是默认策略。
    round_robin 基于轮循机制排序选择主机的策略。
    sequential 基于顺序排序选择主机的策略。

    如果 AKS 虚拟网络包含多个 DNS 服务器,则来自 AKS 节点的请求可能会转到第一个 DNS 服务器。 但是,来自 Pod 的请求可能会转到第二个 DNS 服务器。

原因:DNS 请求的多个目标

如果指定了两个自定义 DNS 服务器,并且第三个 DNS 服务器被指定为 Azure DNS(168.63.129.16),则节点将请求发送到第一个自定义 DNS 服务器(如果正在运行且可访问)。 在此设置中,节点可以解析自定义域。 但是,来自 Pod 的某些 DNS 请求可能定向到 Azure DNS。 这是因为 CoreDNS 可以随机选择上游服务器。 在此方案中,无法解析自定义域。 因此,DNS 请求失败。

解决方案:从虚拟网络设置中删除 Azure DNS

建议不要将 Azure DNS 与虚拟网络设置中的自定义 DNS 服务器组合在一起。 如果要使用自定义 DNS 服务器,请在虚拟网络设置中仅添加自定义 DNS 服务器。 然后,在自定义 DNS 服务器的转发器设置中配置 Azure DNS。

有关详细信息,请参阅使用自己的 DNS 服务器的名称解析

第三方联系人免责声明

为了帮助您获取有关此主题的更多信息,Microsoft 提供了第三方的联系信息。 该联系信息可能会在不通知的情况下更改。 微软不保证第三方联系信息的准确性。

联系我们以获得帮助

如果您有任何疑问或需要帮助,可以创建支持请求,或咨询Azure社区支持。 您还可以向Azure反馈社区提交产品反馈。