Résoudre les problèmes liés à kube-dns dans GKE


Cette page explique comment résoudre les problèmes liés à kube-dns dans Google Kubernetes Engine (GKE).

Identifier la source des problèmes DNS dans kube-dns

Les erreurs telles que dial tcp: i/o timeout, no such host ou Could not resolve host signalent souvent des problèmes liés à la capacité de kube-dns à résoudre les requêtes.

Si l'un de ces messages d'erreur s'affiche, mais que vous ne savez pas pourquoi, consultez les sections suivantes pour trouver la cause. Les sections suivantes sont organisées de manière à commencer par les étapes les plus susceptibles de vous aider. Essayez donc de suivre chaque section dans l'ordre.

Vérifier si les pods kube-dns sont en cours d'exécution

Les pods kube-dns sont essentiels à la résolution de noms au sein du cluster. Si elles ne sont pas exécutées, vous risquez de rencontrer des problèmes de résolution DNS.

Pour vérifier que les pods kube-dns s'exécutent sans redémarrage récent, consultez l'état de ces pods:

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

Le résultat ressemble à ce qui suit :

NAME                   READY          STATUS          RESTARTS       AGE
kube-dns-POD_ID_1      5/5            Running         0              16d
kube-dns-POD_ID_2      0/5            Terminating     0              16d

Dans cette sortie, POD_ID_1 et POD_ID_2 représentent des identifiants uniques qui sont automatiquement ajoutés aux pods kube-dns.

Si votre sortie indique qu'aucun de vos pods kube-dns n'a l'état Running, procédez comme suit:

  1. Utilisez les journaux d'audit des activités d'administration pour déterminer si des modifications récentes ont été apportées, telles que des mises à niveau de version du cluster ou du pool de nœuds, ou des modifications apportées au ConfigMap kube-dns. Pour en savoir plus sur les journaux d'audit, consultez la page Informations sur la journalisation d'audit de GKE. Si vous constatez des modifications, rétablissez-les et vérifiez à nouveau l'état des pods.

  2. Si vous ne trouvez aucune modification récente pertinente, vérifiez si vous rencontrez une erreur OOM sur le nœud sur lequel le pod kube-dns s'exécute. Si une erreur semblable à celle-ci s'affiche dans les messages de journal Cloud Logging, ces pods rencontrent une erreur OOM:

    Warning: OOMKilling Memory cgroup out of memory
    

    Pour résoudre cette erreur, consultez la section Message d'erreur: "Warning: OOMKilling Memory cgroup out of memory".

  3. Si aucun message d'erreur OOM ne s'affiche, redémarrez le déploiement kube-dns:

    kubectl rollout restart deployment/kube-dns --namespace=kube-system
    

    Après avoir redémarré le déploiement, vérifiez si vos pods kube-dns sont en cours d'exécution.

Si ces étapes ne fonctionnent pas, ou si l'état de tous vos pods kube-dns est Running, mais que vous rencontrez toujours des problèmes de DNS, vérifiez que le fichier /etc/resolv.conf est correctement configuré.

Vérifier que /etc/resolv.conf est correctement configuré

Examinez le fichier /etc/resolv.conf des pods présentant des problèmes DNS et assurez-vous que les entrées qu'il contient sont correctes:

  1. Affichez le fichier /etc/resolv.conf du pod:

    kubectl exec -it POD_NAME -- cat /etc/resolv.conf
    

    Remplacez POD_NAME par le nom du pod qui rencontre des problèmes DNS. Si plusieurs pods rencontrent des problèmes, répétez les étapes de cette section pour chacun d'eux.

    Si le binaire Pod n'est pas compatible avec la commande kubectl exec, celle-ci risque d'échouer. Dans ce cas, créez un pod simple à utiliser comme environnement de test. Cette procédure vous permet d'exécuter un pod de test dans le même espace de noms que votre pod problématique.

  2. Vérifiez que l'adresse IP du serveur de noms dans le fichier /etc/resolv.conf est correcte:

    • Les pods qui utilisent un réseau hôte doivent utiliser les valeurs du fichier /etc/resolv.conf du nœud. L'adresse IP du serveur de noms doit être 169.254.169.254.
    • Pour les pods qui n'utilisent pas de réseau hôte, l'adresse IP du service kube-dns doit être identique à celle du serveur de noms. Pour comparer les adresses IP, procédez comme suit:

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

        kubectl get svc kube-dns -n kube-system
        

        Le résultat ressemble à ce qui suit :

        NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
        kube-dns   ClusterIP   192.0.2.10   <none>        53/UDP,53/TCP   64d
        
      2. Notez la valeur de la colonne "Adresse IP du cluster". Dans cet exemple, il s'agit de 192.0.2.10.

      3. Comparez l'adresse IP du service kube-dns à celle du fichier /etc/resolv.conf:

        # cat /etc/resolv.conf
        
        search default.svc.cluster.local svc.cluster.local cluster.local c.PROJECT_NAME google.internal
        nameserver 192.0.2.10
        options ndots:5
        

        Dans cet exemple, les deux valeurs correspondent. Par conséquent, une adresse IP de serveur de noms incorrecte n'est pas la cause de votre problème.

        Toutefois, si les adresses IP ne correspondent pas, cela signifie qu'un champ dnsConfig est configuré dans le fichier manifeste du pod de l'application.

        Si la valeur du champ dnsConfig.nameservers est correcte, examinez votre serveur DNS et assurez-vous qu'il fonctionne correctement.

        Si vous ne souhaitez pas utiliser le serveur de noms personnalisé, supprimez le champ et effectuez un redémarrage progressif du pod:

        kubectl rollout restart deployment POD_NAME
        

        Remplacez POD_NAME par le nom de votre pod.

  3. Vérifiez les entrées search et ndots dans /etc/resolv.conf. Assurez-vous qu'il n'y a pas de fautes d'orthographe, de configurations obsolètes et que la requête qui échoue pointe vers un service existant dans l'espace de noms approprié.

Effectuer une résolution DNS

Une fois que vous avez vérifié que /etc/resolv.conf est correctement configuré et que l'enregistrement DNS est correct, utilisez l'outil de ligne de commande dig pour effectuer des recherches DNS à partir du pod qui signale des erreurs DNS:

  1. Interrogez directement un pod en ouvrant une interface système à l'intérieur:

    kubectl exec -it POD_NAME -n NAMESPACE_NAME -- SHELL_NAME
    

    Remplacez les éléments suivants :

    • POD_NAME: nom du pod qui signale des erreurs DNS.
    • NAMESPACE_NAME: espace de noms auquel le pod appartient.
    • SHELL_NAME: nom du shell que vous souhaitez ouvrir. Par exemple, sh ou /bin/bash.

    Cette commande peut échouer si votre pod n'autorise pas la commande kubectl exec ou s'il ne dispose pas du binaire dig. Si cela se produit, créez un pod de test avec une image sur laquelle dig est installé:

    kubectl run "test-$RANDOM" ti --restart=Never --image=thockin/dnsutils - bash
    
  2. Vérifiez si le pod peut résoudre correctement le service DNS interne du cluster:

    dig kubernetes
    

    Étant donné que le fichier /etc/resolv.conf pointe vers l'adresse IP du service kube-dns, lorsque vous exécutez cette commande, le serveur DNS est le service kube-dns.

    Vous devriez voir une réponse DNS réussie avec l'adresse IP du service d'API Kubernetes (souvent 10.96.0.1). Si SERVFAIL s'affiche ou si aucune réponse n'est renvoyée, cela indique généralement que le pod kube-dns ne parvient pas à résoudre les noms de service internes.

  3. Vérifiez si le service kube-dns peut résoudre un nom de domaine externe:

    dig example.com
    
  4. Si vous rencontrez des difficultés avec un pod kube-dns particulier qui répond aux requêtes DNS, vérifiez si ce pod peut résoudre un nom de domaine externe:

     dig example.com @KUBE_DNS_POD_IP
    

    Remplacez KUBE_DNS_POD_IP par l'adresse IP du pod kube-dns. Si vous ne connaissez pas la valeur de cette adresse IP, exécutez la commande suivante:

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

    L'adresse IP se trouve dans la colonne IP.

    Si la résolution de la commande aboutit, status: NOERROR et les détails de l'enregistrement A s'affichent, comme illustré dans l'exemple suivant:

     ; <<>> DiG 9.16.27 <<>> example.com
     ;; global options: +cmd
     ;; Got answer:
     ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31256
     ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
    
     ;; OPT PSEUDOSECTION:
     ; EDNS: version: 0, flags:; udp: 512
     ;; QUESTION SECTION:
     ;example.com.                   IN      A
    
     ;; ANSWER SECTION:
     example.com.            30      IN      A       93.184.215.14
    
     ;; Query time: 6 msec
     ;; SERVER: 10.76.0.10#53(10.76.0.10)
     ;; WHEN: Tue Oct 15 16:45:26 UTC 2024
     ;; MSG SIZE  rcvd: 56
    
  5. Quittez le shell:

    exit
    

Si l'une de ces commandes échoue, effectuez un redémarrage progressif du déploiement kube-dns:

kubectl rollout restart deployment/kube-dns --namespace=kube-system

Une fois le redémarrage terminé, réessayez les commandes dig et vérifiez si elles aboutissent. Si elles échouent toujours, effectuez une capture de paquets.

Effectuer une capture de paquets

Effectuez une capture de paquets pour vérifier si les requêtes DNS sont reçues et si les pods kube-dns y répondent de manière appropriée:

  1. Connectez-vous au nœud qui exécute le pod kube-dns à l'aide de SSH. Exemple :

    1. Dans la console Google Cloud , accédez à la page Instances de VM.

      Accéder à la page "Instances de VM"

    2. Recherchez le nœud auquel vous souhaitez vous connecter. Si vous ne connaissez pas le nom du nœud de votre pod kube-dns, exécutez la commande suivante:

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

      Le nom du nœud s'affiche dans la colonne Nœud.

    3. Dans la colonne Connecter, cliquez sur SSH.

  2. Dans le terminal, démarrez toolbox, un outil de débogage préinstallé:

    toolbox
    
  3. À l'invite racine, installez le package tcpdump:

    apt update -y && apt install -y tcpdump
    
  4. À l'aide de tcpdump, effectuez une capture de paquets de votre trafic DNS:

    tcpdump -i eth0 port 53" -w FILE_LOCATION
    

    Remplacez FILE_LOCATION par le chemin d'accès à l'emplacement où vous souhaitez enregistrer la capture.

  5. Examinez la capture de paquets. Vérifiez si des paquets dont les adresses IP de destination correspondent à l'adresse IP du service kube-dns existent. Cela garantit que les requêtes DNS atteignent la bonne destination pour la résolution. L'absence de trafic DNS sur les bons pods peut indiquer la présence d'une règle réseau bloquant les requêtes.

Rechercher une règle de réseau

Des règles réseau restrictives peuvent parfois perturber le trafic DNS. Pour vérifier si une règle de réseau existe dans l'espace de noms kube-system, exécutez la commande suivante:

kubectl get networkpolicy -n kube-system

Si vous trouvez une règle réseau, examinez-la et assurez-vous qu'elle autorise la communication DNS nécessaire. Par exemple, si vous disposez d'une règle réseau qui bloque tout le trafic sortant, elle bloque également les requêtes DNS.

Si la sortie est No resources found in kube-system namespace, vous n'avez aucune règle réseau et vous pouvez exclure cette cause de votre problème. L'examen des journaux peut vous aider à identifier d'autres points de défaillance.

Activer la journalisation temporaire des requêtes DNS

Pour vous aider à identifier les problèmes tels que les réponses DNS incorrectes, activez temporairement la journalisation de débogage des requêtes DNS.

Il s'agit d'une procédure gourmande en ressources. Nous vous recommandons donc de désactiver cette journalisation une fois que vous avez collecté un échantillon de journaux approprié.

Examiner le pod kube-dns

Découvrez comment les pods kube-dns reçoivent et résolvent les requêtes DNS avec Cloud Logging.

Pour afficher les entrées de journal associées au pod kube-dns, procédez comme suit:

  1. Dans la console Google Cloud , accédez à la page Explorateur de journaux.

    Accéder à l'explorateur de journaux

  2. Dans le volet de requête, saisissez le filtre suivant pour afficher les événements liés au conteneur kube-dns:

    resource.type="k8s_container"
    resource.labels.namespace_name="kube-system"
    resource.labels.Pod_name:"kube-dns"
    resource.labels.cluster_name="CLUSTER_NAME"
    resource.labels.location="CLUSTER_LOCATION"
    

    Remplacez les éléments suivants :

    • CLUSTER_NAME: nom du cluster auquel appartient le pod kube-dns.
    • CLUSTER_LOCATION : emplacement de votre cluster.
  3. Cliquez sur Exécuter la requête.

  4. Examinez le résultat. L'exemple de sortie suivant montre une erreur possible que vous pouvez rencontrer:

    {
       "timestamp": "2024-10-10T15:32:16.789Z",
       "severity": "ERROR",
       "resource": {
          "type": "k8s_container",
          "labels": {
          "namespace_name": "kube-system",
          "Pod_name": "kube-dns",
          "cluster_name": "CLUSTER_NAME",
          "location": "CLUSTER_LOCATION"
          }
       },
       "message": "Failed to resolve 'example.com': Timeout."
    },
    

    Dans cet exemple, kube-dns n'a pas pu résoudre example.com dans un délai raisonnable. Ce type d'erreur peut être causé par plusieurs problèmes. Par exemple, le serveur en amont peut être mal configuré dans le fichier ConfigMap kube-dns, ou le trafic réseau peut être élevé.

Si Cloud Logging n'est pas activé, affichez plutôt les journaux Kubernetes:

Pod=$(kubectl get Pods -n kube-system -l k8s-app=kube-dns -o name | head -n1)
kubectl logs -n kube-system $Pod -c dnsmasq
kubectl logs -n kube-system $Pod -c kubedns
kubectl logs -n kube-system $Pod -c sidecar

Examiner les modifications récentes apportées au fichier ConfigMap kube-dns

Si vous rencontrez soudainement des échecs de résolution DNS dans votre cluster, cela peut être dû à une modification de configuration incorrecte apportée au ConfigMap kube-dns. En particulier, les modifications de configuration des domaines de simulation et des définitions des serveurs en amont peuvent entraîner des problèmes.

Pour rechercher les mises à jour des paramètres du domaine fictif, procédez comme suit:

  1. Dans la console Google Cloud , accédez à la page Explorateur de journaux.

    Accéder à l'explorateur de journaux

  2. Dans le volet de requête, saisissez la requête suivante:

    resource.labels.cluster_name="clouddns"
    resource.type="k8s_container"
    resource.labels.namespace_name="kube-system"
    labels.k8s-pod/k8s-app="kube-dns" jsonPayload.message=~"Updated stubDomains to"
    
  3. Cliquez sur Exécuter la requête.

  4. Examinez le résultat. Si des mises à jour ont été effectuées, le résultat ressemble à ce qui suit:

    Updated stubDomains to map[example.com: [8.8.8.8 8.8.4.4 1.1.3.3 1.0.8.111]]
    

    Si une mise à jour s'affiche, développez le résultat pour en savoir plus sur les modifications. Vérifiez que les domaines de simulation et leurs serveurs DNS en amont correspondants sont correctement définis. Des entrées incorrectes peuvent entraîner des échecs de résolution pour ces domaines.

Pour vérifier les modifications apportées au serveur en amont, procédez comme suit:

  1. Dans la console Google Cloud , accédez à la page Explorateur de journaux.

    Accéder à l'explorateur de journaux

  2. Dans le volet de requête, saisissez la requête suivante:

    resource.labels.cluster_name="clouddns"
    resource.type="k8s_container" resource.labels.namespace_name="kube-system"
    labels.k8s-pod/k8s-app="kube-dns" jsonPayload.message=~"Updated upstreamNameservers to"
    
  3. Cliquez sur Exécuter la requête.

  4. Examinez le résultat. Si des modifications ont été apportées, le résultat ressemble à ce qui suit:

    Updated upstreamNameservers to [8.8.8.8]
    

    Développez le résultat pour en savoir plus sur les modifications. Vérifiez que la liste des serveurs DNS en amont est exacte et que ces serveurs sont accessibles depuis votre cluster. Si ces serveurs sont indisponibles ou mal configurés, la résolution DNS générale peut échouer.

Si vous avez vérifié les modifications apportées aux domaines fictifs et aux serveurs en amont, mais que vous n'avez trouvé aucun résultat, recherchez toutes les modifications à l'aide du filtre suivant:

resource.type="k8s_cluster"
protoPayload.resourceName:"namespaces/kube-system/configmaps/kube-dns"
protoPayload.methodName=~"io.k8s.core.v1.configmaps."

Examinez les modifications listées pour voir si elles sont à l'origine de l'erreur.

Contacter Cloud Customer Care

Si vous avez suivi les sections précédentes, mais que vous ne parvenez toujours pas à diagnostiquer la cause de votre problème, contactez l'assistance Cloud Customer Care.

Résoudre les problèmes les plus courants

Si vous avez rencontré une erreur ou un problème spécifique, suivez les conseils des sections suivantes.

Problème: délais d'inactivité DNS intermittents

Si vous constatez des délais avant expiration intermittents de résolution DNS qui se produisent en cas d'augmentation du trafic DNS ou au début des heures d'ouverture, essayez les solutions suivantes pour optimiser les performances de votre DNS:

  • Vérifiez le nombre de pods kube-dns exécutés sur le cluster et comparez-le au nombre total de nœuds GKE. Si les ressources ne sont pas suffisantes, envisagez de redimensionner les pods kube-dns.

  • Pour améliorer la durée moyenne de résolution DNS, activez NodeLocal DNS Cache.

  • La résolution DNS des noms externes peut surcharger le pod kube-dns. Pour réduire le nombre de requêtes, ajustez le paramètre ndots dans le fichier /etc/resolv.conf. ndots représente le nombre de points qui doivent apparaître dans un nom de domaine pour résoudre une requête avant la requête absolue initiale.

    L'exemple suivant est le fichier /etc/resolv.conf d'un pod d'application:

    search default.svc.cluster.local svc.cluster.local cluster.local c.PROJECT_ID.internal google.internal
    nameserver 10.52.16.10
    options ndots:5
    

    Dans cet exemple, kube-dns recherche cinq points dans le domaine interrogé. Si le pod effectue un appel de résolution DNS pour example.com, vos journaux ressemblent à l'exemple suivant:

    "A IN example.com.default.svc.cluster.local." NXDOMAIN
    "A IN example.com.svc.cluster.local." NXDOMAIN
    "A IN example.com.cluster.local." NXDOMAIN
    "A IN example.com.google.internal." NXDOMAIN
    "A IN example.com.c.PROJECT_ID.internal." NXDOMAIN
    "A IN example.com." NOERROR
    

    Pour résoudre ce problème, modifiez la valeur de ndots sur 1 pour rechercher un seul point ou ajoutez un point (.) à la fin du domaine que vous interrogez ou utilisez. Exemple :

    dig example.com.
    

Problème: les requêtes DNS échouent de manière intermittente à partir de certains nœuds

Si vous constatez que les requêtes DNS échouent de manière intermittente à partir de certains nœuds, vous pouvez observer les symptômes suivants:

  • Lorsque vous exécutez des commandes dig à l'adresse IP du service kube-dns ou à l'adresse IP du pod, les requêtes DNS échouent de manière intermittente avec des délais avant expiration.
  • L'exécution de commandes dig à partir d'un pod sur le même nœud que le pod kube-dns échoue.

Pour résoudre ce problème, procédez comme suit :

  1. Effectuez un test de connectivité. Définissez le pod ou le nœud problématique comme source et la destination comme adresse IP du pod kube-dns. Cela vous permet de vérifier si vous avez mis en place les règles de pare-feu requises pour autoriser ce trafic.
  2. Si le test échoue et que le trafic est bloqué par une règle de pare-feu, utilisez Cloud Logging pour lister les modifications manuelles apportées aux règles de pare-feu. Recherchez les modifications qui bloquent un type de trafic spécifique:

    1. Dans la console Google Cloud , accédez à la page Explorateur de journaux.

      Accéder à l'explorateur de journaux

    2. Dans le volet de requête, saisissez la requête suivante:

      logName="projects/project-name/logs/cloudaudit.googleapis.com/activity"
      resource.type="gce_firewall_rule"
      
    3. Cliquez sur Exécuter la requête. Utilisez la sortie de la requête pour déterminer si des modifications ont été apportées. Si vous constatez des erreurs, corrigez-les et réappliquez la règle de pare-feu.

      Assurez-vous de ne pas modifier les règles de pare-feu automatiques.

  3. Si les règles de pare-feu n'ont pas été modifiées, vérifiez la version du pool de nœuds et assurez-vous qu'elle est compatible avec le plan de contrôle et les autres pools de nœuds opérationnels. Si l'un des pools de nœuds du cluster a plus de deux versions mineures antérieures au plan de contrôle, cela peut engendrer des problèmes. Pour en savoir plus sur cette incompatibilité, consultez la section La version du nœud n'est pas compatible avec la version du plan de contrôle.

  4. Pour déterminer si les requêtes sont envoyées à la bonne adresse IP de service kube-dns, capturez le trafic réseau sur le nœud problématique et filtrez-le pour le port 53 (trafic DNS). Capturez le trafic sur les pods kube-dns eux-mêmes pour voir si les requêtes atteignent les pods prévus et si elles sont résolues.

Étape suivante

  • 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.