NodeLocal DNSCache einrichten


Auf dieser Seite wird erläutert, wie Sie die DNS-Lookup-Latenz in einem GKE-Cluster (Google Kubernetes Engine) mithilfe von NodeLocal DNSCache verbessern.

Hinweis: Für GKE Autopilot-Cluster ist NodeLocal DNSCache standardmäßig aktiviert und kann nicht überschrieben werden.

Architektur

NodeLocal DNSCache ist ein GKE-Add-on, das Sie neben kube-dns ausführen können.

GKE implementiert NodeLocal DNSCache als DaemonSet, das auf jedem Knoten in Ihrem Cluster einen DNS-Cache ausführt.

Wenn ein Pod eine DNS-Anfrage stellt, wird die Anfrage an den DNS-Cache gesendet, der auf demselben Knoten wie der Pod ausgeführt wird. Wenn der Cache die DNS-Anfrage nicht auflösen kann, leitet er die Anfrage basierend auf dem Abfrageziel an einen der folgenden Orte weiter:

  • kube-dns: Alle Abfragen für die Cluster-DNS-Domain (cluster.local) werden an kube-dns weitergeleitet. Die node-local-dns-Pods verwenden den kube-dns-upstream-Dienst, um auf kube-dns-Pods zuzugreifen. Im folgenden Diagramm lautet die IP-Adresse des kube-dns-Dienstes 10.0.0.10:53.
  • Benutzerdefinierte Stub-Domains oder Upstream-Nameserver: Abfragen werden direkt von NodeLocal DNSCache-Pods weitergeleitet.
  • Cloud DNS: Alle anderen Abfragen werden an den lokalen Metadatenserver weitergeleitet, der auf demselben Knoten wie der Pod ausgeführt wird, von dem die Abfrage stammt. Der lokale Metadatenserver greift auf Cloud DNS zu.

Der Pfad einer DNS-Anfrage, wie im vorherigen Abschnitt beschrieben.

Wenn Sie NodeLocal DNSCache in einem vorhandenen Cluster aktivieren, erstellt GKE alle Clusterknoten mit GKE-Version 1.15 und höher gemäß dem Knotenaktualisierungsprozess neu.

Nachdem GKE die Knoten neu erstellt hat, fügt GKE den Knoten automatisch das Label addon.gke.io/node-local-dns-ds-ready=true hinzu. Sie dürfen dieses Label den Clusterknoten nicht manuell hinzufügen.

Vorteile von NodeLocal DNSCache

NodeLocal DNSCache bietet folgende Vorteile:

  • Kürzere durchschnittliche DNS-Lookup-Zeit
  • Verbindungen von Pods zu ihrem lokalen Cache erstellen keine Tabelleneinträge vom Typ conntrack. Dadurch werden unterbrochene und abgelehnte Verbindungen aufgrund von erschöpften conntrack-Tabellen und Race-Bedingungen verhindert.
  • Sie können NodeLocal DNSCache mit Cloud DNS for GKE verwenden.
  • DNS-Abfragen für externe URLs (URLs, die nicht auf Clusterressourcen verweisen) werden direkt an den lokalen Cloud DNS-Metadatenserver weitergeleitet, wobei kube-dns umgangen wird.
  • Die lokalen DNS-Caches übernehmen automatisch Stub-Domains und Upstream-Nameserver, die in der kube-dns ConfigMap angegeben sind.

Anforderungen und Einschränkungen

  • NodeLocal DNSCache verbraucht Rechenressourcen auf jedem Knoten Ihres Clusters.
  • NodeLocal DNSCache wird mit Windows Server-Knotenpools nicht unterstützt.
  • Für NodeLocal DNSCache ist eine GKE Version ab 1.15 erforderlich.
  • NodeLocal DNSCache greift über TCP auf kube-dns-Pods zu.
  • NodeLocal DNSCache greift über TCP und UDP auf GKE-Versionen 1.18 oder höher auf upstreamServers und stubDomains zu. Der DNS-Server muss über TCP und UDP erreichbar sein.
  • DNS-Einträge werden für die folgenden Zeiträume im Cache gespeichert:
    • Die Gültigkeitsdauer (TTL) des Eintrags oder 30 Sekunden, wenn die TTL mehr als 30 Sekunden beträgt.
    • 5 Sekunden, wenn die DNS-Antwort NXDOMAIN lautet.
  • NodeLocal DNSCache-Pods überwachen Port 53, 9253, 9353 und 8080 auf den Knoten. Wenn Sie einen anderen hostNetwork-Pod ausführen oder mit diesen Ports ein hostPorts konfigurieren, schlägt NodeLocal DNSCache fehl und DNS-Fehler treten auf. NodeLocal DNSCache-Pods verwenden nicht den Modus hostNetwork, wenn Sie GKE Dataplane V2 und Cloud DNS for GKE verwenden.
  • Der lokale DNS-Cache wird nur in Knotenpools mit GKE-Versionen ab 1.15 ausgeführt. Wenn Sie NodeLocal DNSCache in einem Cluster mit Knoten aktivieren, auf denen niedrigere Versionen laufen, verwenden Pods auf diesen Knoten kube-dns.

NodeLocal DNSCache aktivieren

Für Autopilot-Cluster ist NodeLocal DNSCache standardmäßig aktiviert und kann nicht überschrieben werden.

Bei Standardclustern können Sie NodeLocal DNSCache in neuen oder vorhandenen Clustern mithilfe der Google Cloud CLI aktivieren. Sie können NodeLocal DNSCache in neuen Clustern mit der Google Cloud Console aktivieren.

gcloud

NodeLocal DNSCache in einem neuen Cluster aktivieren

Verwenden Sie das Flag --addons mit dem Argument NodeLocalDNS, um NodeLocal DNSCache in einem neuen Cluster zu aktivieren:

gcloud container clusters create CLUSTER_NAME \
    --location=COMPUTE_LOCATION \
    --addons=NodeLocalDNS

Dabei gilt:

NodeLocal DNSCache in einem vorhandenen Cluster aktivieren

Verwenden Sie das Flag --update-addons mit dem Argument NodeLocalDNS=ENABLED, um NodeLocal DNSCache in einem vorhandenen Cluster zu aktivieren:

gcloud container clusters update CLUSTER_NAME \
    --update-addons=NodeLocalDNS=ENABLED

Dabei gilt:

  • CLUSTER_NAME: Der Name Ihres Clusters.

Console

Führen Sie die folgenden Schritte aus, um NodeLocal DNSCache in einem neuen Cluster zu aktivieren:

  1. Rufen Sie in der Google Cloud Console die Seite Google Kubernetes Engine auf.

    Zur Seite "Google Kubernetes Engine"

  2. Klicken Sie neben "Standard" auf Konfigurieren.

  3. Konfigurieren Sie den Cluster wie gewünscht.

  4. Klicken Sie im Navigationsbereich auf Netzwerk.

  5. Klicken Sie im Bereich Erweiterte Netzwerkoptionen das Kästchen NodeLocal DNSCache aktivieren an.

  6. Klicken Sie auf Erstellen.

Prüfen, ob NodeLocal DNSCache aktiviert ist

Rufen Sie eine Liste der node-local-dns-Pods ab, um festzustellen, ob NodeLocal DNSCache ausgeführt wird:

kubectl get pods -n kube-system -o wide | grep node-local-dns

Die Ausgabe sieht etwa so aus:

node-local-dns-869mt    1/1   Running   0   6m24s   10.128.0.35   gke-test-pool-69efb6b8-5d7m   <none>   <none>
node-local-dns-htx4w    1/1   Running   0   6m24s   10.128.0.36   gke-test-pool-69efb6b8-wssk   <none>   <none>
node-local-dns-v5njk    1/1   Running   0   6m24s   10.128.0.33   gke-test-pool-69efb6b8-bhz3   <none>   <none>

Die Ausgabe zeigt einen node-local-dns-Pod für jeden Knoten, auf dem eine GKE-Version ab 1.15 ausgeführt wird.

NodeLocal DNSCache deaktivieren

Sie können NodeLocal DNSCache mit dem folgenden Befehl deaktivieren:

gcloud container clusters update CLUSTER_NAME \
    --update-addons=NodeLocalDNS=DISABLED

Dabei gilt:

  • CLUSTER_NAME: der Name des Clusters, der deaktiviert werden soll.

Probleme bei NodeLocal DNSCache beheben

Allgemeine Informationen zur Diagnose von Kubernetes DNS-Problemen finden Sie unter Debugging bei der DNS-Auflösung.

NodeLocal DNSCache ist nicht sofort aktiviert

Wenn Sie NodeLocal DNSCache in einem vorhandenen Cluster aktivieren, aktualisiert GKE die Knoten möglicherweise nicht sofort, wenn der Cluster ein konfiguriertes Wartungsfenster oder einen Ausschluss hat. Weitere Informationen finden Sie unter Hinweise: Neuerstellung und Wartungsfenster von Knoten.

Wenn Sie nicht warten möchten, können Sie die Änderungen manuell auf die Knoten anwenden. Dazu rufen Sie den Befehl gcloud container clusters upgrade auf und übergeben das Flag --cluster-version mit der GKE-Version, die vom Knotenpool bereits ausgeführt wird. Für diese Problemumgehung muss die Google Cloud CLI verwendet werden.

NodeLocal DNSCache mit Cloud DNS

Wenn Sie NodeLocal DNSCache mit Cloud DNS verwenden, verwendet der Cluster die Nameserver-IP-Adresse 169.254.20.10, wie im folgenden Diagramm dargestellt:

Architektur von NodeLocal DNSCache mit Cloud DNS

Daher kann die IP-Adresse des kube-dns-Dienstes von der Nameserver-IP-Adresse abweichen, die Ihre Pods verwenden. Dieser Unterschied bei den IP-Adressen ist zu erwarten, da die IP-Adresse des Nameservers 169.254.20.10 erforderlich ist, damit Cloud DNS ordnungsgemäß funktioniert.

Prüfen Sie die IP-Adressen mit den folgenden Befehlen:

  1. Rufen Sie die IP-Adresse des kube-dns-Dienstes auf:

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

    Die Ausgabe ist die IP-Adresse von kube-dns, z. B. 10.0.0.10:53.

  2. Öffnen Sie eine Shell-Sitzung im Pod:

    kubectl exec -it POD_NAME -- /bin/bash
    
  3. Lesen Sie in der Pod-Shell-Sitzung den Inhalt der Datei /etc/resolv.conf:

    cat /etc/resolv.conf
    

    Die Ausgabe ist 169.254.20.10

Netzwerkrichtlinie mit NodeLocal DNSCache

Wenn Sie Netzwerkrichtlinien mit NodeLocal DNSCache verwenden und nicht Cloud DNS oder GKE Dataplane V2 einsetzen, müssen Sie Regeln konfigurieren, damit Ihre Arbeitslasten und die node-local-dns-Pods DNS-Abfragen senden können.

Verwenden Sie eine ipBlock-Regel in Ihrem Manifest, um die Kommunikation zwischen -Pods und kube-dns zu ermöglichen.

Das folgende Manifest beschreibt eine Netzwerkrichtlinie, die eine ipBlock-Regel verwendet:

spec:
  egress:
  - ports:
    - port: 53
      protocol: TCP
    - port: 53
      protocol: UDP
    to:
    - ipBlock:
        cidr: KUBE_DNS_SVC_CLUSTER_IP/32
  podSelector: {}
  policyTypes:
    - Egress

Ersetzen Sie KUBE_DNS_SVC_CLUSTER_IP durch die IP-Adresse des Dienstes "kube-dns". Sie können die IP-Adresse des Dienstes "kube-dns" mit dem folgenden Befehl abrufen:

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

Bekannte Probleme

DNS-Zeitlimit in ClusterFirstWithHostNet dnsPolicy bei Verwendung von NodeLocal DNSCache und GKE Dataplane V2

In Clustern, in denen GKE Dataplane V2 und NodeLocal DNSCache verwendet werden, können Pods, bei denen hostNetwork auf true und dnsPolicy auf ClusterFirstWithHostNet festgelegt sind, keine Cluster-DNS-Back-Ends erreichen. DNS-Logs können Einträge wie die folgenden enthalten:

nslookup: write to 'a.b.c.d': Operation not permitted

;; connection timed out; no servers could be reached

Die Ausgabe gibt an, dass die DNS-Anfragen die Backend-Server nicht erreichen können.

Das Problem lässt sich dadurch umgehen, dass Sie dnsPolicy und dnsConfig für hostNetwork-Pods festlegen:

spec:
 dnsPolicy: "None"
 dnsConfig:
   nameservers:
     - KUBE_DNS_UPSTREAM
   searches:
     - cluster.local
     - svc.cluster.local
     - NAMESPACE.svc.cluster.local
     - c.PROJECT_ID.internal
     - google.internal
   options:
     - name: ndots
       value: "5"

Dabei gilt:

  • NAMESPACE ist der Namespace des Pods hostNetwork.
  • PROJECT_ID ist die ID Ihres Google Cloud-Projekts.
  • KUBE_DNS_UPSTREAM ist die ClusterIP des Upstream-kube-dns-Dienstes. Sie können diesen Wert mit dem folgenden Befehl abrufen:

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

DNS-Anfragen vom Pod können jetzt kube-dns erreichen und NodeLocal DNSCache umgehen.

NodeLocal DNSCache-Zeitüberschreitungsfehler

In Clustern mit aktiviertem NodeLocal DNSCache können die Logs Einträge wie die folgenden enthalten:

[ERROR] plugin/errors: 2 <hostname> A: read tcp <node IP: port>-><kubedns IP>:53: i/o timeout

Die Ausgabe enthält die IP-Adresse des Cluster-IP-Dienstes kube-dns-upstream. In diesem Beispiel wurde innerhalb von zwei Sekunden keine Antwort auf eine DNS-Anfrage von kube-dns empfangen. Dies könnte einen der folgenden Gründe haben:

  • Ein zugrunde liegendes Problem mit der Netzwerkverbindung.
  • Erhebliche Erhöhung der DNS-Abfragen von der Arbeitslast oder aufgrund einer Skalierung des Knotenpools

Daher können die vorhandenen kube-dns-Pods nicht alle Anfragen gleichzeitig verarbeiten. Die Problemumgehung besteht darin, die Anzahl der kube-dns-Replikate zu erhöhen. Optimieren Sie dazu die Autoscaling-Parameter.

kube-dns hochskalieren

Sie können einen niedrigeren Wert für nodesPerReplica verwenden, damit mehr kube-dns-Pods erstellt werden, wenn Clusterknoten vertikal skaliert werden. Es wird dringend empfohlen, einen expliziten max-Wert festzulegen, damit die GKE-Steuerungsebenen-VM (Virtuelle Maschine) aufgrund der großen Anzahl von kube-dns-Pods, die die Kubernetes API überwachen, nicht überlastet ist.

Sie können max auf die Anzahl der Knoten im Cluster festlegen. Wenn der Cluster mehr als 500 Knoten hat, legen Sie max auf 500 fest.

Bei Standardclustern können Sie die Anzahl der kube-dns-Replikate ändern. Bearbeiten Sie dazu die ConfigMap kube-dns-autoscaler. Diese Konfiguration wird in Autopilot-Clustern nicht unterstützt.

kubectl edit configmap kube-dns-autoscaler --namespace=kube-system

Die Ausgabe sieht in etwa so aus:

linear: '{"coresPerReplica":256, "nodesPerReplica":16,"preventSinglePointFailure":true}'

Die Anzahl der kube-dns-Replikate wird mit der folgenden Formel berechnet:

replicas = max(ceil(kerns × 1/coresPerReplica), ceil(nodes × 1/nodesPerReplica), maxValue)

Ändern Sie zum Hochskalieren nodesPerReplica in einen kleineren Wert und fügen Sie einen max-Wert ein.

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"preventSinglePointFailure":true}'

Mit der Konfiguration wird ein kube-dns-Pod pro acht Knoten im Cluster erstellt. Ein Cluster mit 24 Knoten hat 3 Replikate und ein Cluster mit 40 Knoten hat 5 Replikate. Wenn der Cluster über 120 Knoten hat, steigt die Anzahl der kube-dns-Replikate nicht über 15 (max-Wert) an.

Legen Sie eine Mindestanzahl von Replikat für kube-dns fest, um eine grundlegende DNS-Verfügbarkeit in Ihrem Cluster zu gewährleisten.

Die ConfigMap-Ausgabe kube-dns-autoscaler mit dem Feld min würde in etwa so aussehen:

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"min": 5,"preventSinglePointFailure":true}'

Nächste Schritte