Wie behebe ich DNS-Fehler bei Amazon EKS?

Lesedauer: 9 Minute
0

Die Anwendungen oder Pods, die CoreDNS in meinem Amazon Elastic Kubernetes Service (Amazon EKS)-Cluster verwenden, schlagen bei internen oder externen DNS-Namensauflösungen fehl.

Kurzbeschreibung

Pods, die innerhalb des Amazon-EKS-Clusters ausgeführt werden, verwenden die CoreDNS-Cluster-IP-Adresse als Nameserver, um interne und externe DNS-Einträge abzufragen. Wenn es Probleme mit den CoreDNS-Pods, der Dienstkonfiguration oder der Konnektivität gibt, kann die DNS-Auflösung im Rahmen von Anwendungen fehlschlagen.

Ein Serviceobjekt namens kube-dns abstrahiert die CoreDNS-Pods. Um Probleme mit Ihren CoreDNS-Pods zu beheben, überprüfen Sie den Betriebsstatus aller Komponenten des kube-dns-Dienstes, z. B. die Service-Endpunkt-Optionen und die iptables-Regeln.

Lösung

Die folgende Lösung gilt für die CoreDNS-ClusterIP 10.100.0.10.

Führen Sie die folgenden Schritte aus:

  1. Rufen Sie die ClusterIP Ihres CoreDNS-Dienstes ab:

    kubectl get service kube-dns -n kube-system
  2. Stellen Sie sicher, dass die DNS-Endpunkte verfügbar sind und auf CoreDNS-Pods verweisen:

    kubectl -n kube-system get endpoints kube-dns

    Beispiel für eine Ausgabe:

    NAME       ENDPOINTS                                                        AGE
    kube-dns   192.168.2.218:53,192.168.3.117:53,192.168.2.218:53 + 1 more...   90d

    Hinweis: Wenn die Endpunktliste leer ist, überprüfen Sie den Pod-Status der CoreDNS-Pods.

  3. Stellen Sie sicher, dass keine Sicherheitsgruppe oder Netzwerk-Zugriffssteuerungsliste (Netzwerk-ACL) die Pods blockiert, wenn sie mit CoreDNS kommunizieren.

    Weitere Informationen finden Sie unter Warum verbinden sich meine Pods nicht mit anderen Pods in Amazon EKS?

Sicherstellen, dass der kube-proxy-Pod funktioniert

Überprüfen Sie die Protokolle auf Timeout-Fehler auf der Steuerebene, um sicherzustellen, dass der kube-proxy-Pod Zugriff auf API-Server für Ihren Cluster hat. Suchen Sie außerdem nach dem Fehlercode 403 – „Unauthorized“.

Rufen Sie die kube-proxy-Protokolle ab:

kubectl logs -n kube-system --selector 'k8s-app=kube-proxy'

Hinweis: Der kube-proxy ruft die Endpunkte von der Steuerebene ab und erstellt die iptables-Regeln auf jedem Knoten.

Überprüfen der CPU-Auslastung der CoreDNS-Pods zum Zeitpunkt des Problems

Das CoreDNS-Add-On für Amazon EKS fügt dem Speicher des CoreDNS-Pods nur das 170-Mi-Limit hinzu. Der CoreDNS-Pod definiert kein CPU-Limit, sodass der Container alle verfügbaren CPU-Ressourcen auf dem Knoten nutzen kann, auf dem er ausgeführt wird. Wenn die CPU-Auslastung des Knotens 100 % erreicht, erhalten Sie möglicherweise DNS-Timeout-Fehler in den Protokollen Ihrer Amazon-EKS-Anwendungen. Grund dafür ist, dass der CoreDNS-Pod nicht über ausreichend CPU-Ressourcen verfügt, um alle DNS-Abfragen zu verarbeiten.

Herstellen einer Verbindung zum Anwendungs-Pod, um das DNS-Problem zu beheben

Führen Sie die folgenden Schritte aus:

  1. Um Befehle in den Anwendungs-Pods auszuführen, greifen Sie mit folgendem Befehl auf eine Shell innerhalb des ausgeführten Pods zu:

    $ kubectl exec -it your-pod-name -- sh

    Wenn im Anwendungs-Pod keine Shell-Binärdatei verfügbar ist, erhalten Sie eine Fehlermeldung wie die folgende:

    "OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown command terminated with exit code 126

    Aktualisieren Sie zum Debuggen das Image, das in der Manifestdatei für ein anderes Image verwendet wird, z. B. das busybox-Image auf der Docker-Website.

  2. Stellen Sie sicher, dass sich die Cluster-IP-Adresse des kube-dns-Dienstes in der Datei /etc/resolv.conf Ihres Pods befindet. Führen Sie den folgenden Befehl in der Shell aus, die sich im Pod befindet:

    cat /etc/resolv.conf

    Die folgende Beispieldatei resolv.conf zeigt einen Pod, der so konfiguriert ist, dass er für DNS-Anfragen auf 10.100.0.10 verweist. Die IP-Adresse muss mit der ClusterIP Ihres kube-dns-Dienstes übereinstimmen:

    nameserver 10.100.0.10
    search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal
    options ndots:5

    Hinweis: Sie können die DNS-Konfiguration des Pods mit dem Feld dnsPolicy in der Pod-Spezifikation verwalten. Wenn dieses Feld nicht ausgefüllt ist, wird standardmäßig die DNS-Richtlinie ClusterFirst verwendet. Weitere Informationen zur DNS-Richtlinie ClusterFirst finden Sie unter Pod’s DNS policy auf der Kubernetes-Website.

  3. Um zu überprüfen, ob der Pod zur Auflösung einer internen Domain die standardmäßige ClusterIP verwenden kann, führen Sie den folgenden Befehl in der Shell innerhalb des Pods aus:

    nslookup kubernetes.default 10.100.0.10

    Beispiel für eine Ausgabe:

    Server:     10.100.0.10
    Address:    10.100.0.10#53
    Name:       kubernetes.default.svc.cluster.local
    Address:    10.100.0.1
  4. Um zu überprüfen, ob der Pod zur Auflösung einer externen Domain die standardmäßige ClusterIP verwenden kann, führen Sie den folgenden Befehl in der Shell innerhalb des Pods aus:

    nslookup amazon.com 10.100.0.10

    Beispiel für eine Ausgabe:

    Server:     10.100.0.10
    Address:    10.100.0.10#53
    Non-authoritative answer:
    Name:   amazon.com
    Address: 176.32.98.166
    Name:    amazon.com
    Address: 205.251.242.103
    Name:    amazon.com
    Address: 176.32.103.205
  5. Stellen Sie sicher, dass Ihr Pod die IP-Adresse des CoreDNS-Pods zur direkten Auflösung verwenden kann. Führen Sie die folgenden Befehle in der Shell aus, die sich im Pod befindet:

    nslookup kubernetes COREDNS_POD_IP
    
    nslookup amazon.com COREDNS_POD_IP

    **Hinweis:**Ersetzen Sie COREDNS_POD_IP durch eine der Endpunkt-IP-Adressen der kubectl-GET-Endpunkte.

Abfragen detaillierterer Protokolle von CoreDNS-Pods zum Debuggen

Führen Sie die folgenden Schritte aus:

  1. Schalten Sie das Debug-Protokoll der CoreDNS-Pods ein und fügen Sie das log-Plugin zur CoreDNS-ConfigMap hinzu:

    kubectl -n kube-system edit configmap coredns

    Hinweis: Weitere Informationen finden Sie unter Log-Plugin auf der CoreDNS-Website.

  2. Fügen Sie in dem Editor-Fenster, das in der Ausgabe erscheint, die Protokoll-Zeichenfolge hinzu:

    kind: ConfigMap
    apiVersion: v1
    data:
      Corefile: |
        .:53 {
            log    # Enabling CoreDNS Logging
            errors
            health
            kubernetes cluster.local in-addr.arpa ip6.arpa {
              pods insecure
              upstream
              fallthrough in-addr.arpa ip6.arpa
            }
            ...
    ...

    Hinweis: Das Neuladen der Konfigurations-CoreDNS dauert einige Minuten. Um die Änderungen sofort zu übernehmen, starten Sie die Pods nacheinander neu.

  3. Prüfen Sie, ob die CoreDNS-Protokolle fehlschlagen oder Treffer vom Anwendungs-Pod erhalten:

    kubectl logs --follow -n kube-system --selector 'k8s-app=kube-dns'

Aktualisieren des ndots-Werts

Der ndots-Wert gibt die Anzahl der Punkte an, die in einem Namen vorkommen müssen, um eine Abfrage vor der ersten absoluten Abfrage aufzulösen.

Beispielsweise können Sie die Option ndots in einem Domainnamen, der nicht vollständig qualifiziert ist, auf den Standardwert 5 setzen. Anschließend werden alle externen Domains, die nicht unter die interne Domain cluster.local fallen, an die Suchdomains angehängt, bevor sie Abfragen durchführen.

Das folgende Beispiel verwendet die Einstellung /etc/resolv.conf des Anwendungs-Pods:

nameserver 10.100.0.10
search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal
options ndots:5

CoreDNS sucht in der abgefragten Domain nach fünf Punkten. Wenn der Pod einen DNS-Auflösungsaufruf für amazon.com durchführt, sehen die Protokolle etwa wie folgt aus:

[INFO] 192.168.3.71:33238 - 36534 "A IN amazon.com.default.svc.cluster.local. udp 54 false 512" NXDOMAIN qr,aa,rd 147 0.000473434s
[INFO] 192.168.3.71:57098 - 43241 "A IN amazon.com.svc.cluster.local. udp 46 false 512" NXDOMAIN qr,aa,rd 139 0.000066171s
[INFO] 192.168.3.71:51937 - 15588 "A IN amazon.com.cluster.local. udp 42 false 512" NXDOMAIN qr,aa,rd 135 0.000137489s
[INFO] 192.168.3.71:52618 - 14916 "A IN amazon.com.ec2.internal. udp 41 false 512" NXDOMAIN qr,rd,ra 41 0.001248388s
[INFO] 192.168.3.71:51298 - 65181 "A IN amazon.com. udp 28 false 512" NOERROR qr,rd,ra 106 0.001711104s

Hinweis: NXDOMAIN bedeutet, dass der Domain-Datensatz nicht gefunden wurde, und NOERROR bedeutet, dass der Domain-Datensatz gefunden wurde.

Jede Suchdomain wird amazon.com vorangestellt, bevor der letztendliche Aufruf der absoluten Domain am Ende erfolgt. Ein endgültiger Domainname mit einem Punkt (.) am Ende ist ein voll qualifizierter Domainname. Deshalb können für jede externe Domainnamenabfrage vier bis fünf zusätzliche Aufrufe erfolgen, die den CoreDNS-Pod überlasten können.

Um dieses Problem zu beheben, setzen Sie entweder ndots auf 1, um nur nach einem einzigen Punkt zu suchen. Oder fügen Sie einen Punkt (.) am Ende der Domain an, die Sie abfragen oder verwenden:

nslookup example.com.

Berücksichtigen von Grenzwerten für den VPC-Resolver (AmazonProvidedDNS)

Der Amazon Virtual Private Cloud (Amazon VPC)-Resolver kann nur einen maximalen harten Grenzwert von 1024 Paketen pro Sekunde und Netzwerkschnittstelle akzeptieren. Wenn sich mehrere CoreDNS-Pods auf einem Knoten befinden, ist die Wahrscheinlichkeit höher, dass dieser Grenzwert bei externen Domainabfragen erreicht wird.

Um PodAntiAffinity-Regeln zu verwenden, um CoreDNS-Pods auf separaten Instances zu planen, fügen Sie der CoreDNS-Bereitstellung die folgenden Optionen hinzu:

podAntiAffinity:
  preferredDuringSchedulingIgnoredDuringExecution:
  - podAffinityTerm:
      labelSelector:
        matchExpressions:
        - key: k8s-app
          operator: In
          values:
          - kube-dns
      topologyKey: kubernetes.io/hostname
    weight: 100

**Hinweis:**Weitere Informationen zu PodAntiAffinity finden Sie unter Inter-Pod Affinität und Anti-Affinität auf der Kubernetes-Website.

Verwenden von tcpdump, um CoreDNS-Pakete von Amazon-EKS-Worker-Knoten zu erfassen

Verwenden Sie das Tool tcpdump, um mittels einer Paketerfassung DNS-Auflösungsprobleme zu diagnostizieren:

  1. Finden Sie einen Worker-Knoten, auf dem ein CoreDNS-Pod läuft:

    kubectl get pod -n kube-system -l k8s-app=kube-dns -o wide
  2. Verwenden Sie SSH, um eine Verbindung zu dem Worker-Knoten herzustellen, auf dem ein CoreDNS-Pod ausgeführt wird, und installieren Sie das Tool tcpdump:

    sudo yum install tcpdump –y
  3. Suchen Sie die Prozess-ID des CoreDNS-Pods auf dem Worker-Knoten:

    ps ax | grep coredns
  4. Führen Sie vom Worker-Knoten aus eine Paketerfassung im CoreDNS-Pod-Netzwerk durch, um den Netzwerk-Datenverkehr auf UDP-Port 53 zu überwachen:

    sudo nsenter -n -t PID tcpdump udp port 53
  5. Rufen Sie von einem separaten Terminal aus den CoreDNS-Dienst und die Pod-IP-Adresse ab:

    kubectl describe svc kube-dns -n kube-system

    Hinweis: Beachten Sie die Service-IP-Adresse im Feld IP und die Pod-IP-Adresse im Feld Endpunkte.

  6. Starten Sie einen Pod, von dem aus Sie den DNS-Dienst testen möchten. Das folgende Beispiel verwendet ein Ubuntu-Container-Image:

    kubectl run ubuntu --image=ubuntu sleep 1d
    
    kubectl exec -it ubuntu sh
  7. Verwenden Sie das Tool nslookup, um eine DNS-Abfrage an eine Domain wie amazon.com durchzuführen:

    nslookup amazon.com

    Führen Sie dieselbe Abfrage explizit für die IP-Adresse des CoreDNS-Dienstes durch:

    nslookup amazon.com COREDNS_SERVICE_IP

    Führen Sie die Abfrage für jede der CoreDNS-Pod-IP-Adressen durch:

    nslookup amazon.com COREDNS\_POD\_IP

    Hinweis: Wenn Sie mehrere CoreDNS-Pods ausführen, starten Sie mehrere Abfragen, damit mindestens eine Abfrage an den Pod gesendet wird, von dem Sie Datenverkehr erfassen.

  8. Überprüfen Sie die Ergebnisse der Paketerfassung.

    Wenn in Ihrem überwachten CoreDNS-Pod DNS-Abfrage-Timeouts auftreten und Sie die Abfrage in der Paketerfassung nicht sehen, überprüfen Sie Ihre Netzwerkverbindung. Prüfen Sie auch die Netzwerkerreichbarkeit zwischen den Worker-Knoten.

    Wenn Sie ein DNS-Abfrage-Timeout für eine Pod-IP-Adresse sehen, die Sie nicht erfassen, führen Sie eine weitere Paketerfassung auf dem zugehörigen Worker-Knoten durch.

    Um die Ergebnisse einer Paketerfassung zu speichern, fügen Sie dem Befehl tcpdump das Flag -w FILE_NAME hinzu. Im folgenden Beispiel werden die Ergebnisse in eine Datei mit dem Namen capture.pcap geschrieben:

    tcpdump -w capture.pcap udp port 53

Verwandte Informationen

CoreDNS GA für Kubernetes-Cluster-DNS

auf der Kubernetes-Website

AWS OFFICIAL
AWS OFFICIALAktualisiert vor 6 Monaten