Configurer NodeLocal DNSCache

Cette page explique comment configurer NodeLocal DNSCache sur un cluster Google Kubernetes Engine (GKE).

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

NodeLocal DNSCache améliore la latence de la résolution DNS, rend les durées de résolution DNS plus cohérentes et réduit le nombre de requêtes DNS à kube-dns en exécutant un cache DNS sur chaque nœud d'un cluster.

Pour obtenir un aperçu de la façon dont fonctionnent la détection de services et le DNS géré sur GKE, consultez la section Détection de services et DNS.

Architecture

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 pour accéder aux pods kube-dns.
  • Domaines de simulation personnalisés ou serveurs de noms en amont: les requêtes sont transférées directement à partir de 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

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 éléments upstreamServers via TCP. Cela signifie que les serveurs en amont doivent être compatibles avec la résolution DNS via TCP et UDP. Le protocole UDP est disponible pour GKE en versions 1.17.5-gke.6 et 1.18.3-gke.0 et ultérieures, pour les configurations personnalisées fournies à l'aide de ConfigMap de kube-dns. Nous vous recommandons d'utiliser un serveur DNS 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.
  • Si PodSecurityPolicy est activé sur votre cluster, il doit utiliser l'une des versions suivantes pour utiliser NodeLocal DNSCache :
    • 1.15.12-gke.9 et versions ultérieures
    • 1.16.11-gke.5 et versions ultérieures
    • 1.17.7-gke.15 et versions ultérieures
  • 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

Vous pouvez activer NodeLocal DNSCache sur des clusters nouveaux ou existants à l'aide de l'outil de ligne de commande gcloud. Vous pouvez activer NodeLocal DNSCache dans les nouveaux clusters à l'aide de Google Cloud Console.

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 \
    --region=COMPUTE_REGION \
    --cluster-version=CLUSTER_VERSION \
    --addons=NodeLocalDNS

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom de votre nouveau cluster
  • COMPUTE_REGION : région Compute Engine du cluster.
  • CLUSTER_VERSION : version de votre cluster (version 1.15 ou ultérieure)

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 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 Create (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 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

Vous pouvez afficher l'adresse IP de l'IP du cluster à l'aide de la commande suivante :

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

Le résultat ressemble à ce qui suit :

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 les pods node-local-dns à envoyer et recevoir des requêtes DNS.

Utilisez une règle ipBlock dans votre fichier manifeste pour autoriser la communication entre les pods node-local-dns 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_CLUSTER_IP/32
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

Remplacez KUBE_DNS_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
  • un problème connu avec dnsmasq en charge des connexions TCP

Les pods node-local-dns accèdent à kube-dns via TCP pour améliorer la fiabilité. Lors du traitement des connexions à partir de plusieurs adresses IP sources, dnsmasq donne la priorité aux connexions provenant de connexions existantes par rapport aux nouvelles. Par conséquent, sur un cluster avec un nombre élevé de requêtes DNS par seconde (RPS), les pods node-local-dns sur les nœuds nouvellement créés peuvent connaître une latence DNS plus élevée. Cela peut également se produire sur des clusters sur lesquels l'autoscaler de cluster est activé, car l'autoscaler de cluster modifie le nombre de nœuds de manière dynamique.

Ce problème est résolu dans les versions suivantes de GKE :

  • 1.19.7-gke.1500 et versions ultérieures
  • 1.18.16-gke.1200 et versions ultérieures
  • 1.17.17-gke.5400 et versions ultérieures

Une solution de contournement consiste à augmenter le nombre d'instances dupliqué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.

Étape suivante