跳至主要内容

DNS

本頁面列出的命令/步驟可用於檢查叢集中的名稱解析問題。

確保你配置了正確的 kubeconfig(例如,對於 Rancher HA,使用 export KUBECONFIG=$PWD/kube_config_cluster.yml),或透過 UI 使用嵌入式 kubectl。

在執行 DNS 檢查之前,請檢查叢集的預設 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 服務是否存在且具有正確的叢集 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 應該與 kube-dns 服務的 CLUSTER-IP 相同。

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 中的上游名稱伺服器​

預設情況下,主機上配置的名稱伺服器(在 /etc/resolv.conf 中)將用作 CoreDNS 的上游名稱伺服器。你可以在主機上檢查此檔案,或執行以下 Pod(將 dnsPolicy 設定為 Default),它將繼承其執行所在主機的 /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 容器中的上游名稱伺服器​

預設情況下,主機上配置的名稱伺服器(在 /etc/resolv.conf 中)將用作 kube-dns 的上游名稱伺服器。有時主機會執行本地快取 DNS 名稱伺服器,這表示 /etc/resolv.conf 中的地址將指向回環範圍(127.0.0.0/8)中的地址,容器將無法連線到該地址。在 Ubuntu 18.04 的情況下,這是由 systemd-resolved 完成的。我們會偵測 systemd-resolved 是否正在執行,並將自動使用具有正確上游名稱伺服器的 /etc/resolv.conf 檔案(位於 /run/systemd/resolve/resolv.conf)。

使用以下命令檢查 kubedns 容器使用的上游名稱伺服器:

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 中列出了正確的名稱伺服器,請參閱你的作業系統文件以了解如何執行此操作。確保在佈建叢集之前執行此操作,或在進行修改後重新啟動節點。
  • 透過使用如下所示的 extra_args 配置 kubelet 使用不同的檔案來解析名稱(其中 /run/resolvconf/resolv.conf 是具有正確名稱伺服器的檔案):
services:
kubelet:
extra_args:
resolv-conf: "/run/resolvconf/resolv.conf"
備註

由於 kubelet 在容器內執行,位於 /etc 和 /usr 中的檔案路徑在 kubelet 容器內為 /host/etc 和 /host/usr。

請參閱將叢集編輯為 YAML 以了解如何應用此變更。當叢集的佈建完成後,你必須移除 kube-dns pod 以啟用 pod 中的新設定:

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

使用檢查網域名稱是否正在解析再次嘗試解析名稱。

如果你想要檢查叢集中的 kube-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"]