Configurer NodeLocal DNSCache


Cette page explique comment améliorer la latence de la résolution DNS dans un cluster Google Kubernetes Engine (GKE) à l'aide de NodeLocal DNSCache.

Pour les clusters GKE Autopilot, NodeLocal DNSCache est activé par défaut et ne peut pas être remplacé.

Architecture

NodeLocal DNSCache est un module complémentaire GKE que vous pouvez exécuter en plus de kube-dns.

GKE implémente NodeLocal DNSCache en tant que DaemonSet qui exécute un cache DNS sur chaque nœud de votre cluster.

Lorsqu'un pod effectue une requête DNS, celle-ci est envoyée au cache DNS exécuté sur le même nœud que le pod. Si le cache ne peut pas résoudre la requête DNS, il la transfère vers l'un des emplacements suivants en fonction de la destination de la requête :

  • kube-dns : toutes les requêtes pour le domaine DNS du cluster (cluster.local) sont transférées à kube-dns. Les pods node-local-dns utilisent le service kube-dns-upstream pour accéder aux pods kube-dns. Dans le schéma suivant, l'adresse IP du service kube-dns est 10.0.0.10:53.
  • Domaines de simulation personnalisés ou serveurs de noms en amont : les requêtes sont transférées directement à partir des pods NodeLocal DNSCache.
  • Cloud DNS : toutes les autres requêtes sont transférées au serveur de métadonnées local qui s'exécute sur le même nœud que le pod à l'origine de la requête. Le serveur de métadonnées local accède à Cloud DNS.

Schéma du chemin d'une requête DNS, comme décrit dans le paragraphe précédent

Lorsque vous activez NodeLocal DNSCache sur un cluster existant, GKE recrée tous les nœuds de cluster exécutant la version 1.15 ou ultérieure de GKE en fonction du processus de mise à niveau des nœuds.

Après avoir recréé les nœuds, GKE ajoute automatiquement l'étiquette addon.gke.io/node-local-dns-ds-ready=true aux nœuds. Vous ne devez pas ajouter cette étiquette manuellement aux nœuds du cluster.

Avantages de NodeLocal DNSCache

NodeLocal DNSCache offre les avantages suivants :

  • Durée moyenne de résolution DNS réduite
  • Les correspondances entre les pods et leur cache local ne créent pas d'entrées de table conntrack. Cela évite les correspondances supprimées et rejetées en raison de l'épuisement de la table conntrack et des conditions de concurrence.
  • Vous pouvez utiliser NodeLocal DNSCache avec Cloud DNS pour GKE.
  • Les requêtes DNS pour les URL externes (URL qui ne font pas référence aux ressources du cluster) sont transmises directement au serveur de métadonnées Cloud DNS local, et contournent ainsi kube-dns.
  • Les caches DNS locaux récupèrent automatiquement des domaines de simulation et des serveurs de noms en amont spécifiés dans le fichier ConfigMap de kube-dns.

Conditions requises et limites

  • NodeLocal DNSCache consomme des ressources de calcul sur chaque nœud de votre cluster.
  • NodeLocal DNSCache n'est pas compatible avec les pools de nœuds Windows Server.
  • NodeLocal DNSCache nécessite la version 1.15 ou ultérieure de GKE.
  • NodeLocal DNSCache accède aux pods kube-dns via TCP.
  • NodeLocal DNSCache accède à upstreamServers et stubDomains à l'aide du protocole TCP et UDP sur GKE version 1.18 ou ultérieure. Le serveur DNS doit être accessible via TCP et UDP.
  • Les enregistrements DNS sont mis en cache dans les périodes suivantes :
    • Valeur TTL (Time To Live) de l'enregistrement, ou 30 secondes si la valeur TTL est supérieure à 30 secondes.
    • 5 secondes si la réponse DNS est NXDOMAIN.
  • Les pods NodeLocal DNSCache écoutent les ports 53, 9253, 9353 et 8080 sur les nœuds. Si vous exécutez un autre pod hostNetwork ou configurez un hostPorts avec ces ports, NodeLocal DNSCache échoue et des erreurs DNS se produisent. Les pods NodeLocal DNSCache n'utilisent pas le mode hostNetwork lors de l'utilisation de GKE Dataplane V2 et de Cloud DNS pour GKE.
  • Le cache DNS local s'exécute uniquement sur les pools de nœuds exécutant les versions 1.15 et ultérieures de GKE. Si vous activez NodeLocal DNSCache dans un cluster dont certains nœuds exécutent des versions précédentes, les pods sur ces nœuds utilisent kube-dns.

Activer NodeLocal DNSCache

Pour les clusters Autopilot, NodeLocal DNSCache est activé par défaut et ne peut pas être remplacé.

Pour les clusters standards, vous pouvez activer NodeLocal DNSCache sur des clusters nouveaux ou existants à l'aide de Google Cloud CLI. Vous pouvez activer NodeLocal DNSCache dans les nouveaux clusters à l'aide de la console Google Cloud.

gcloud

Activer NodeLocal DNSCache dans un nouveau cluster

Pour activer NodeLocal DNSCache dans un nouveau cluster, utilisez l'option --addons avec l'argument NodeLocalDNS :

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

Remplacez les éléments suivants :

Activer NodeLocal DNSCache dans un cluster existant

Pour activer NodeLocal DNSCache dans un cluster existant, utilisez l'option --update-addons avec l'argument NodeLocalDNS=ENABLED :

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

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom du cluster

Console

Pour activer NodeLocal DNSCache sur un nouveau cluster, procédez comme suit :

  1. Accédez à la page Google Kubernetes Engine dans Google Cloud Console.

    Accéder à Google Kubernetes Engine

  2. À côté de "Standard", cliquez sur Configurer.

  3. Configurez le cluster comme vous le souhaitez.

  4. Dans le volet de navigation, cliquez sur Mise en réseau.

  5. Dans la section Options de mise en réseau avancées, cochez la case Activer NodeLocal DNSCache.

  6. Cliquez sur Créer.

Vérifier que NodeLocal DNSCache est activé

Vous pouvez vérifier que NodeLocal DNSCache est en cours d'exécution en répertoriant les pods node-local-dns.

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

Le résultat ressemble à ce qui suit :

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>

Le résultat affiche un pod node-local-dns pour chaque nœud exécutant la version 1.15 ou une version ultérieure de GKE.

Désactiver NodeLocal DNSCache

Vous pouvez désactiver NodeLocal DNSCache à l'aide de la commande suivante :

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

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom du cluster à désactiver

Résoudre les problèmes liés à NodeLocal DNSCache

Pour obtenir des informations générales sur l'analyse des problèmes de DNS de Kubernetes, consultez la section Déboguer la résolution DNS.

NodeLocal DNSCache n'est pas activé immédiatement

Lorsque vous activez NodeLocal DNSCache sur un cluster existant, GKE peut ne pas mettre à jour immédiatement les nœuds si le cluster dispose d'une exclusion ou d'un intervalle de maintenance configuré. Pour en savoir plus, consultez la section Mise en garde à propos des intervalles de recréation et de maintenance des nœuds.

Pour éviter d'attendre, vous pouvez appliquer manuellement les modifications aux nœuds en appelant la commande gcloud container clusters upgrade et en transmettant l'argument --cluster-version avec la même version de GKE que celle exécutée par le pool de nœuds. Vous devez utiliser Google Cloud CLI pour contourner ce problème.

NodeLocal DNSCache avec Cloud DNS

Si vous utilisez NodeLocal DNSCache avec Cloud DNS, le cluster utilise l'adresse IP du serveur de noms 169.254.20.10, comme indiqué dans le schéma suivant :

NodeLocal DNSCache avec l&#39;architecture Cloud DNS

Par conséquent, l'adresse IP du service kube-dns peut être différente de l'adresse IP du serveur de noms utilisé par vos pods. Cette différence d'adresses IP est attendue, car l'adresse IP du serveur de noms 169.254.20.10 est requise pour que Cloud DNS fonctionne correctement.

Pour vérifier les adresses IP, exécutez les commandes suivantes :

  1. Affichez l'adresse IP du service kube-dns :

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

    Le résultat correspond à l'adresse IP de kube-dns, par exemple 10.0.0.10:53.

  2. Ouvrez une session shell dans le pod :

    kubectl exec -it POD_NAME -- /bin/bash
    
  3. Dans la session shell du pod, lisez le contenu du fichier /etc/resolv.conf :

    cat /etc/resolv.conf
    

    Le résultat est 169.254.20.10.

Règle de réseau avec NodeLocal DNSCache

Si vous utilisez une règle de réseau avec NodeLocal DNSCache, et que vous n'utilisez pas Cloud DNS ou GKE Dataplane V2, vous devez configurer des règles pour autoriser vos charges de travail et les pods node-local-dns à envoyer des requêtes DNS.

Utilisez une règle ipBlock dans votre fichier manifeste pour autoriser la communication entre les pods et kube-dns.

Le fichier manifeste suivant décrit une règle de réseau qui utilise une règle ipBlock :

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

Remplacez KUBE_DNS_SVC_CLUSTER_IP par l'adresse IP du service kube-dns. Vous pouvez obtenir l'adresse IP du service kube-dns à l'aide de la commande suivante :

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

Problèmes connus

Délai avant expiration DNS dans ClusterFirstWithHostNet dnsPolicy lors de l'utilisation de NodeLocal DNSCache et GKE Dataplane V2

Sur les clusters utilisant GKE Dataplane V2 et NodeLocal DNSCache, les pods avec hostNetwork définis sur true et dnsPolicy définis sur ClusterFirstWithHostNet ne peuvent pas atteindre les backends DNS de cluster. Les journaux DNS peuvent contenir des entrées semblables à ce qui suit :

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

;; connection timed out; no servers could be reached

Le résultat indique que les requêtes DNS ne peuvent pas atteindre les serveurs de backend.

Pour contourner ce problème, définissez les valeurs dnsPolicy et dnsConfig pour les pods hostNetwork :

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"

Remplacez les éléments suivants :

  • NAMESPACE : espace de noms du pod hostNetwork.
  • PROJECT_ID : ID de votre projet Google Cloud
  • KUBE_DNS_UPSTREAM : adresse IP de cluster du service kube-dns en amont. Vous pouvez obtenir cette valeur à l'aide de la commande suivante :

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

Les requêtes DNS du pod peuvent désormais atteindre kube-dns et contourner NodeLocal DNSCache.

Erreurs de délai avant expiration de NodeLocal DNSCache

Sur les clusters sur lesquels NodeLocal DNSCache est activé, les journaux peuvent contenir des entrées semblables à ce qui suit :

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

Le résultat inclut l'adresse IP du service IP du cluster kube-dns-upstream. Dans cet exemple, la réponse à une requête DNS n'a pas été reçue par kube-dns après deux secondes. Cela peut être dû à l'une des raisons suivantes :

  • un problème de connectivité réseau sous-jacent
  • Augmentation considérable des requêtes DNS de la charge de travail ou scaling à la hausse du pool de nœuds

Par conséquent, les pods kube-dns existants ne peuvent pas traiter toutes les requêtes à temps. La solution consiste à augmenter le nombre d'instances répliquées kube-dns en ajustant les paramètres d'autoscaling.

Faire évoluer kube-dns à la hausse

Vous pouvez utiliser une valeur inférieure pour nodesPerReplica, afin de vous assurer de la création d'un plus grand nombre de pods kube-dns au fur et à mesure du scaling à la hausse des nœuds du cluster. Nous vous recommandons vivement de définir une valeur max explicite pour vous assurer que la machine virtuelle (VM) du plan de contrôle GKE n'est pas submergée par un grand nombre de pods kube-dns qui surveillent l'API Kubernetes.

Vous pouvez définir max sur le nombre de nœuds du cluster. Si le cluster comporte plus de 500 nœuds, définissez max sur 500.

Pour les clusters standards, vous pouvez modifier le nombre d'instances dupliquées kube-dns en modifiant le fichier ConfigMap kube-dns-autoscaler. Cette configuration n'est pas compatible avec les clusters Autopilot.

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

Le résultat ressemble à ce qui suit :

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

Le nombre d'instances dupliquées de kube-dns est calculé à l'aide de la formule suivante :

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

Pour effectuer un scaling à la hausse, réduisez la valeur de nodesPerReplica et incluez une valeur max.

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

Cette configuration crée un pod kube-dns pour chacun des huit nœuds du cluster. Un cluster de 24 nœuds aura trois instances dupliquées et un cluster de 40 nœuds en aura cinq. Si le cluster dépasse 120 nœuds, le nombre d'instances dupliquées kube-dns ne dépasse pas 15, la valeur max.

Pour garantir un niveau de disponibilité du DNS de base dans votre cluster, définissez un nombre minimal d'instances dupliquées pour kube-dns.

Une sortie de ConfigMap kube-dns-autoscaler avec le champ min ressemblerait à ce qui suit :

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

Étape suivante