本文档采用自动化机器翻译技术翻译。 尽管我们力求提供准确的译文,但不对翻译内容的完整性、准确性或可靠性作出任何保证。 若出现任何内容不一致情况,请以原始 英文 版本为准,且原始英文版本为权威文本。

DNS

本页面列出的命令/步骤可用于检查集群中的名称解析问题。

确保您配置了正确的 kubeconfig(例如,export KUBECONFIG=$PWD/kube_config_cluster.yml 用于 Rancher HA),或者通过 UI 使用嵌入式 kubectl。

在运行 DNS 检查之前,请确保 覆盖网络正常工作,因为这也可能是 DNS 解析(部分)失败的原因。

检查 DNS pod 是否正在运行

kubectl -n kube-system get pods -l k8s-app=kube-dns

使用 CoreDNS 时的示例输出:

NAME                       READY   STATUS    RESTARTS   AGE
coredns-799dffd9c4-6jhlz   1/1     Running   0          76m

使用 kube-dns 时的示例输出:

NAME                        READY   STATUS    RESTARTS   AGE
kube-dns-5fd74c7488-h6f7n   3/3     Running   0          4m13s

检查 DNS 服务是否存在且具有正确的 cluster-ip

kubectl -n kube-system get svc -l k8s-app=kube-dns
NAME               TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
service/kube-dns   ClusterIP   10.43.0.10   <none>        53/UDP,53/TCP   4m13s

检查域名是否正在解析

检查内部集群名称是否正在解析(在此示例中为 kubernetes.default),在 Server: 后显示的 IP 应与 CLUSTER-IP 服务中的 kube-dns 相同。

kubectl run -it --rm --restart=Never busybox --image=busybox:1.28 -- nslookup kubernetes.default

示例输出:

Server:    10.43.0.10
Address 1: 10.43.0.10 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes.default
Address 1: 10.43.0.1 kubernetes.default.svc.cluster.local
pod "busybox" deleted

检查外部名称是否正在解析(在此示例中为 www.google.com

kubectl run -it --rm --restart=Never busybox --image=busybox:1.28 -- nslookup www.google.com

示例输出:

Server:    10.43.0.10
Address 1: 10.43.0.10 kube-dns.kube-system.svc.cluster.local

Name:      www.google.com
Address 1: 2a00:1450:4009:80b::2004 lhr35s04-in-x04.1e100.net
Address 2: 216.58.211.100 ams15s32-in-f4.1e100.net
pod "busybox" deleted

如果您想检查所有主机上的域名解析,请执行以下步骤:

  1. 将以下文件保存为 ds-dnstest.yml

     apiVersion: apps/v1
     kind: DaemonSet
     metadata:
       name: dnstest
     spec:
       selector:
           matchLabels:
             name: dnstest
       template:
         metadata:
           labels:
             name: dnstest
         spec:
           tolerations:
           - operator: Exists
           containers:
           - image: busybox:1.28
             imagePullPolicy: Always
             name: alpine
             command: ["sleep", "infinity"]
             terminationMessagePath: /dev/termination-log
  2. 使用 kubectl create -f ds-dnstest.yml 启动它

  3. 等待直到 kubectl rollout status ds/dnstest -w 返回:daemon set "dnstest" successfully rolled out

  4. 将环境变量 DOMAIN 配置为主机应能够解析的完全限定域名(FQDN)(www.google.com 用作示例),并运行以下命令以让每个主机上的每个容器解析配置的域名(这是一个单行命令)。

     export DOMAIN=www.google.com; echo "=> Start DNS resolve test"; kubectl get pods -l name=dnstest --no-headers -o custom-columns=NAME:.metadata.name,HOSTIP:.status.hostIP | while read pod host; do kubectl exec $pod -- /bin/sh -c "nslookup $DOMAIN > /dev/null 2>&1"; RC=$?; if [ $RC -ne 0 ]; then echo $host cannot resolve $DOMAIN; fi; done; echo "=> End DNS resolve test"
  5. 当此命令完成运行时,指示一切正常的输出为:

     => Start DNS resolve test
     => End DNS resolve test

如果您在输出中看到错误,这意味着提到的主机无法解析给定的 FQDN。

主机 IP 为 209.97.182.150 的情况的示例错误输出,其中 UDP 端口被阻塞。

=> Start DNS resolve test
command terminated with exit code 1
209.97.182.150 cannot resolve www.google.com
=> End DNS resolve test

通过运行 kubectl delete ds/dnstest 清理 alpine DaemonSet。

CoreDNS 特定

检查 CoreDNS 日志

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

检查配置

CoreDNS 配置存储在名称空间 kube-system 内的 configmap coredns 中。

kubectl -n kube-system get configmap coredns -o go-template={{.data.Corefile}}

检查 resolv.conf 中的上游 DNS 服务器

默认情况下,主机上配置的 DNS 服务器(在 /etc/resolv.conf 中)将作为 CoreDNS 的上游 DNS 服务器。您可以在主机上检查此文件,或运行以下 Pod,将 dnsPolicy 设置为 Default,该 Pod 将继承其运行所在主机的 /etc/resolv.conf

kubectl run -i --restart=Never --rm test-${RANDOM} --image=ubuntu --overrides='{"kind":"Pod", "apiVersion":"v1", "spec": {"dnsPolicy":"Default"}}' -- sh -c 'cat /etc/resolv.conf'

启用查询日志记录

通过在 configmap coredns 的 Corefile 配置中启用 log 插件 来启用查询日志记录。您可以使用 kubectl -n kube-system edit configmap coredns,或使用下面的命令就地替换配置:

kubectl get configmap -n kube-system coredns -o json | sed -e 's_loadbalance_log\\n    loadbalance_g' | kubectl apply -f -

现在所有查询将被记录,并可以使用 检查 CoreDNS 日志 中的命令进行检查。

kube-dns 特定

检查 kubedns 容器中的上游 DNS 服务器

默认情况下,主机上配置的 DNS 服务器(在 /etc/resolv.conf 中)将作为 kube-dns 的上游 DNS 服务器。有时主机会运行一个本地缓存的 DNS 名称服务器,这意味着 /etc/resolv.conf 中的地址将指向环回范围内的地址(127.0.0.0/8),该地址将无法被容器访问。在 Ubuntu 18.04 中,这是通过 systemd-resolved 完成的。我们检测 systemd-resolved 是否正在运行,并将自动使用位于 /run/systemd/resolve/resolv.conf 的包含正确上游 DNS 服务器的 /etc/resolv.conf 文件。

使用以下命令检查 kubedns 容器使用的上游 DNS 服务器:

kubectl -n kube-system get pods -l k8s-app=kube-dns --no-headers -o custom-columns=NAME:.metadata.name,HOSTIP:.status.hostIP | while read pod host; do echo "Pod ${pod} on host ${host}"; kubectl -n kube-system exec $pod -c kubedns cat /etc/resolv.conf; done

示例输出:

Pod kube-dns-667c7cb9dd-z4dsf on host x.x.x.x
nameserver 1.1.1.1
nameserver 8.8.4.4

如果输出显示环回范围内的地址(127.0.0.0/8),您可以通过两种方式纠正此问题:

  • 请确保集群中各节点的 /etc/resolv.conf 中列出了正确的 DNS 服务器;有关操作方法,请查阅您的操作系统文档。确保在配置集群之前执行此操作,或者在进行修改后重启节点。

  • 配置 kubelet 使用不同的文件来解析名称,使用 extra_args 如下所示(其中 /run/resolvconf/resolv.conf 是包含正确 DNS 服务器的文件):

services:
  kubelet:
    extra_args:
      resolv-conf: "/run/resolvconf/resolv.conf"

由于 kubelet 在容器内运行,位于 /etc/usr 的文件路径在 /host/etc/host/usr 内部的 kubelet 容器中。

请参阅以 YAML 编辑集群的文档,了解如何应用此更改。当集群的配置完成后,您需要删除 kube-dns pod 以激活 pod 中的新设置:

kubectl delete pods -n kube-system -l k8s-app=kube-dns
pod "kube-dns-5fd74c7488-6pwsf" deleted

请再次尝试使用 检查域名是否解析 来验证名称解析情况。

如果您想检查集群中的 kube-dns 配置(例如,检查是否配置了不同的上游 DNS 服务器),可以运行以下命令列出 kube-dns 配置:

kubectl -n kube-system get configmap kube-dns -o go-template='{{range $key, $value := .data}}{{ $key }}{{":"}}{{ $value }}{{"\n"}}{{end}}'

示例输出:

upstreamNameservers:["1.1.1.1"]