跳至內容

如何在 EKS 叢集中安裝 NodeLocalDNS 並疑難排解問題?

5 分的閱讀內容
0

我想在 Amazon Elastic Kubernetes Service (Amazon EKS) 叢集中安裝 NodeLocalDNS 並疑難排解問題。

解決方法

必要條件:

安裝 NodeLocalDNS

NodeLocalDNS 會使用連結本機 IP 位址,在每個節點上提供 DNS 快取。連結本機位址是位於 169.254.0.0/16 範圍內的 IP 位址,僅在網路區段內有效。

**注意:**NodeLocalDNS 的標準連結本機 IP 位址為 169.254.20.10。除非您的環境中有特定衝突,否則不要變更此值。

若要在您的 Amazon EKS 叢集中安裝 NodeLocalDNS,請完成以下步驟:

  1. 執行以下 curl 命令,從 Kubernetes 儲存庫下載 NodeLocalDNS 資訊清單:

    curl -Lo nodelocaldns.yaml.template https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
  2. 若要擷取您叢集的 kube-dns 服務 IP 位址,請執行以下命令:

    kubectl get svc kube-dns -n kube-system -o jsonpath='{.spec.clusterIP}'

    **注意:**請記下輸出中的 IP 位址。

  3. 若要擷取您叢集的網域,請執行以下命令:

    kubectl get configmap coredns -n kube-system -o yaml | grep 'kubernetes'

    輸出會顯示您的叢集網域。

  4. 若要判斷您的 kube-proxy 模式,請執行以下命令:

    kubectl get configmap kube-proxy-config -n kube-system -o yaml | grep mode

    輸出會顯示模式值為 iptables 或 ipvs。

  5. 根據您的 kube-proxy 模式編輯 NodeLocalDNS 資訊清單。

    對於 iptables 模式,請使用以下命令編輯資訊清單:

    # Set environment variables for node-local-dns
    kubedns=$(kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP})
    domain=cluster.local
    localdns=`169.254.20.10`
    
    # Update the manifest with your cluster's specific values:
    sed "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns.yaml.template > nodelocaldns.yaml

    **注意:**若您的叢集使用不同的網域,請將 cluster.local 替換為步驟 3 中的叢集網域。若不同,請將 169.254.20.10 替換為您叢集的連結本機 IP 位址。

    對於 IPVS 模式,請使用以下命令編輯資訊清單:

    # Set environment variables for node-local-dns
    kubedns=$(kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP})
    domain=cluster.local
    localdns=169.254.20.10
    
    # Update the manifest with your cluster's specific values:
    sed "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/,__PILLAR__DNS__SERVER__//g; s/__PILLAR__CLUSTER__DNS__/$kubedns/g" nodelocaldns.yaml.template > nodelocaldns.yaml

    **注意:**若您的叢集使用不同的網域,請將 cluster.local 替換為步驟 3 中的叢集網域。若不同,請將 169.254.20.10 替換為您叢集的連結本機 IP 位址。在 IPVS 模式中,您必須設定 Pod 使用 NodeLocalDNS。請參閱「設定 Pod 使用 NodeLocalDNS (僅限 IPVS 模式)」一節。

  6. 若要套用 NodeLocalDNS 資訊清單,請執行以下命令:

    kubectl apply -f nodelocaldns.yaml
  7. 若要驗證 NodeLocalDNS Pod 處於 Running (執行中) 狀態,請執行以下命令:

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

設定 Pod 使用 NodeLocalDNS (僅限 IPVS 模式)

**重要:**本節僅適用於您的叢集對 kube-proxy 使用 IPVS 模式的情況。如果您的叢集使用 iptables 模式,DNS 流量會自動重新導向至 NodeLocalDNS。

對於 IPVS 模式叢集,您必須手動設定 Pod 使用 NodeLocalDNS。若要將您的 Pod 導向 NodeLocalDNS,您可以設定個別 Pod,或使用 kubelet 設定叢集。

設定個別 Pod

若要設定個別 Pod,請將以下組態新增至您的 Pod 規格:

spec:
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - [169.254.20.10]
    searches:
      - default.svc.cluster.local
      - svc.cluster.local
      - cluster.local
    options:
      - name: ndots
        value: "5"

**注意:**請將 169.254.20.10 替換為您叢集的連結本機 IP 位址。若您的叢集使用不同的網域,請將 cluster.local 替換為您的叢集網域。

使用 kubelet 設定叢集

在 IPVS 模式中,NodeLocalDNS 僅會在連結本機位址 169.254.20.10 上接聽。您必須修改 kubelet 組態,使其指向此連結本機位址。

若要將您叢集中的所有 Pod 設定為使用 NodeLocalDNS,並修改每個節點上的 kubelet 組態,請完成以下步驟:

  1. 編輯 kubelet 組態檔。新增以下組態:

    {  "clusterDNS": ["169.254.20.10"],
      "clusterDomain": "cluster.local"
    }

    **注意:**請將 169.254.20.10 替換為您叢集的連結本機 IP 位址。若您的叢集使用不同的網域,請將 cluster.local 替換為您的叢集網域。

  2. 若要在每個節點上重新啟動 kubelet 服務,請執行以下 sudo 命令:

    sudo systemctl restart kubelet
  3. 若要驗證 kubelet 組態,請執行以下命令:

    cat /etc/kubernetes/kubelet/config.json | grep clusterDNS

    **注意:**輸出會顯示 169.254.20.10 為 NodeLocalDNS 連結本機 IP 位址。

**注意:**對於自動化部署,您可以在啟動範本的 userdata 區段中修改 kubelet 組態。如需更多資訊,請參閱如何將自訂使用者資料搭配 AL2023 Amazon EKS 節點使用?

確認您已正確安裝 NodeLocalDNS

若要驗證 NodeLocalDNS 是否正常運作,請完成以下步驟:

  1. 若要建立測試 Pod,請執行以下命令:

    kubectl run test-dns --image=busybox:1.28 --restart=Never --rm -it -- nslookup kubernetes.default
  2. 如果 NodeLocalDNS Pod 處於 CrashLoopBackOff 狀態,且錯誤指出連接埠 53 已在使用中。接著檢閱輸出,以確認 DNS 查詢已正確解析。

  3. 若要驗證 DNS 查詢是否使用 NodeLocalDNS,請執行以下命令:

    kubectl logs -n kube-system -l k8s-app=node-local-dns --tail=50

    日誌會顯示 DNS 查詢由 NodeLocalDNS 處理。

    **注意:**預設情況下,NodeLocalDNS 中不會啟用記錄。若要檢視日誌,請在 node-local-dns ConfigMap 中啟用記錄。

    # kubectl edit configmaps -n kube-system node-local-dns
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: node-local-dns
      namespace: kube-system
    data:
      Corefile: |
        cluster.local:53 {
           log  # Enable logging
           errors
           cache 30
           ...
        }

疑難排解 NodeLocalDNS 問題

**注意:**如果您在執行 AWS Command Line Interface (AWS CLI) 命令時收到錯誤訊息,請參閱對 AWS CLI 錯誤進行疑難排解。此外,請確定您使用的是最新的 AWS CLI 版本

解決由連接埠衝突導致的 CrashLoopBackOff 錯誤

如果 NodeLocalDNS Pod 因連接埠 53 錯誤而進入 CrashLoopBackOff,則這是因為 Amazon EKS 自動模式節點會保留連接埠 53。若要解決此問題,請選擇以下其中一種方法:

方法 1: 新增節點同質規則以排除自動模式節點

請完成以下步驟:

  1. 編輯 NodeLocalDNS daemonset:

    kubectl edit daemonset node-local-dns -n kube-system
  2. 在 spec.template.spec 下新增以下同質組態:

    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: eks.amazonaws.com/compute-type
              operator: NotIn
              values:
              - auto
  3. 儲存變更,然後確認 Pod 已成功重新啟動。

方法 2: 修改 NodeLocalDNS ConfigMap 以變更運作狀態檢查連接埠

請完成以下步驟:

  1. 若要檢視目前的 NodeLocalDNS ConfigMap,請執行以下命令:

    kubectl get configmap node-local-dns -n kube-system -o yaml
  2. 若要編輯 ConfigMap 以變更運作狀態檢查連接埠,請執行以下命令:

    kubectl edit configmap node-local-dns -n kube-system
  3. 在 ConfigMap 中,找出 health 外掛程式組態並修改連接埠。ConfigMap 結構如下:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: node-local-dns
      namespace: kube-system
    data:
      Corefile: |
        cluster.local:53 {
           errors
           cache {
              success 9984 30
              denial 9984 5
           }
           reload
           loop
           bind IP_ADDRESS
           forward. __PILLAR__CLUSTER__DNS__ {
              force_tcp
           }
           prometheus :9253
           health 169.254.20.10:8081
        }

    **注意:**將 health 行中的連接埠從 8081 替換為您想要的連接埠。若不同,請將 169.254.20.10 替換為您叢集的連結本機 IP 位址。

  4. 儲存變更。

  5. 若要重新啟動 NodeLocalDNS Pod,請執行以下命令:

    kubectl rollout restart daemonset node-local-dns -n kube-system
  6. 若要更新 daemonset 運作狀態檢查組態以符合新的連接埠,請執行以下命令:

    kubectl edit daemonset node-local-dns -n kube-system
  7. 找出 livenessProbereadinessProbe 區段,並將連接埠更新為符合新的運作狀態檢查連接埠。

解決 DNS 查詢逾時錯誤

如果您的 Pod 發生 DNS 查詢逾時,請確認您的安全群組和網路 ACL 允許連接埠 53 上的 TCP 與 UDP 流量。Pod 對 Pod 通訊需要此流量。

請完成以下步驟:

  1. 若要識別附加到您節點的安全群組,請執行以下 describe-instances AWS CLI 命令:

    aws ec2 describe-instances --filters "Name=tag:eks:cluster-name,Values=YOUR-CLUSTER-NAME" --query "Reservations[*].Instances[*].SecurityGroups[*].[GroupId,GroupName]" --output table

    **注意:**將 YOUR-CLUSTER-NAME 替換為您的 Amazon EKS 叢集名稱。

  2. 開啟 Amazon EC2 console (Amazon EC2 主控台)。

  3. 在導覽窗格中,選擇 Security Groups (安全群組)。

  4. 選取本節步驟 1 中識別出的安全群組。

  5. 選擇 Inbound rules (傳入規則) 索引標籤。

  6. 確認有規則可允許來自 Pod CIDR 範圍、連接埠 53 上的 TCP 與 UDP 流量。
    **注意:**如果規則不存在,請選擇 Edit inbound rules (編輯傳入規則)。接著,新增 TCP 與 UDP 的連接埠 53 規則,並將來源設為您的 Pod CIDR 範圍。

解決「Connection refused」錯誤訊息

如果 Pod 嘗試使用 NodeLocalDNS 時收到「Connection refused」錯誤訊息,請確認至少有一個 CoreDNS Pod 正在執行。

若要檢查 CoreDNS Pod 狀態,請執行以下命令:

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

如果沒有任何 CoreDNS Pod 正在執行,或 Pod 處於失敗狀態,請重新啟動 CoreDNS 部署。若要重新啟動部署,請執行以下命令:

kubectl rollout restart deployment coredns -n kube-system

若要確認 CoreDNS Pod 正在執行,請執行以下命令:

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

在 CoreDNS Pod 開始執行後,若要重新啟動 NodeLocalDNS daemonset,請執行以下命令:

kubectl rollout restart daemonset node-local-dns -n kube-system

相關資訊

Kubernetes 網站上的使用 CoreDNS 進行服務探索

Kubernetes 網站上的以 IPVS 模式執行 kube-proxy

使用 EKS 自動模式自動化叢集基礎結構

管理 Amazon EKS 叢集的網路附加元件

AWS 官方已更新 4 個月前