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'est affiché, mais que vous ne connaissez pas la cause, consultez les sections suivantes pour l'identifier. Les sections suivantes sont organisées de manière à commencer par les étapes les plus susceptibles de vous aider. Essayez donc chaque section dans l'ordre.
Vérifier si les pods kube-dns sont en cours d'exécution
Les pods kube-dns sont essentiels pour la résolution de noms dans le cluster. Si ce n'est pas le cas, vous risquez de rencontrer des problèmes de résolution DNS.
Pour vérifier que les pods kube-dns sont en cours d'exécution 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 le résultat indique que l'un de vos pods kube-dns n'a pas l'état Running
, suivez les étapes ci-dessous :
Utilisez les journaux d'audit des activités d'administration pour vérifier si des modifications récentes ont été apportées, comme des mises à niveau de la version du cluster ou du pool de nœuds, ou des modifications du ConfigMap kube-dns. Pour en savoir plus sur les journaux d'audit, consultez Informations sur la journalisation d'audit de GKE. Si vous constatez des modifications, rétablissez-les et affichez à nouveau l'état des pods.
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 un message d'erreur semblable à celui-ci s'affiche dans vos messages de journaux Cloud Logging, cela signifie que ces pods rencontrent une erreur OOM :
Warning: OOMKilling Memory cgroup out of memory
Ce message indique que Kubernetes a arrêté un processus en raison d'une consommation excessive de ressources. Kubernetes planifie les pods en fonction des demandes de ressources, mais leur permet de consommer jusqu'à leurs limites de ressources. Si les limites sont supérieures aux demandes ou s'il n'y en a pas, l'utilisation des ressources du pod peut dépasser les ressources du système.
Pour résoudre cette erreur, vous pouvez supprimer les charges de travail problématiques ou définir des limites de mémoire ou de processeur. Pour savoir comment définir des limites, consultez Gestion des ressources pour les pods et les conteneurs dans la documentation de Kubernetes. Pour en savoir plus sur les événements OOM, consultez Résoudre les problèmes liés aux événements OOM.
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 tous vos pods kube-dns ont l'état Running
, mais que vous rencontrez toujours des problèmes 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 qui rencontrent des problèmes DNS et assurez-vous que les entrées qu'il contient sont correctes :
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'accepte pas la commande
kubectl exec
, cette commande peut é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.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 être169.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 :
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
Notez la valeur de la colonne "Adresse IP de cluster". Dans cet exemple, il s'agit de
192.0.2.10
.Comparez l'adresse IP du service kube-dns avec l'adresse IP 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 à l'origine 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 d'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.
- Les pods qui utilisent un réseau hôte doivent utiliser les valeurs du fichier
Vérifiez les entrées
search
etndots
dans/etc/resolv.conf
. Assurez-vous qu'il n'y a pas de fautes d'orthographe ni de configurations obsolètes, et que la requête en échec pointe vers un service existant dans le bon espace de noms.
Effectuer une résolution DNS
Après avoir vérifié que /etc/resolv.conf
est correctement configuré et que l'enregistrement DNS est correct, utilisez l'outil en ligne de commande dig pour effectuer des recherches DNS à partir du pod qui signale des erreurs DNS :
Interrogez directement un pod en ouvrant un shell à 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 appartient le pod.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
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 quelque chose comme
10.96.0.1
). Si vous voyezSERVFAIL
ou aucune réponse, cela indique généralement que le pod kube-dns n'est pas en mesure de résoudre les noms de service internes.Vérifiez si le service kube-dns peut résoudre un nom de domaine externe :
dig example.com
Si vous rencontrez des difficultés avec un pod kube-dns spécifique 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 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
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 fonctionnent désormais. Si elles échouent toujours, passez à la 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 traitées correctement par les pods kube-dns :
À l'aide de SSH, connectez-vous au nœud exécutant le pod kube-dns. Exemple :
Dans la console Google Cloud , accédez à la page Instances de VM.
Localisez le nœud auquel vous souhaitez vous connecter. Si vous ne connaissez pas le nom du nœud sur 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 est indiqué dans la colonne Nœud.
Dans la colonne Connecter, cliquez sur SSH.
Dans le terminal, démarrez toolbox, un outil de débogage préinstallé :
toolbox
À l'invite racine, installez le package
tcpdump
:apt update -y && apt install -y tcpdump
À l'aide de
tcpdump
, capturez les 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.Examinez la capture de paquets. Vérifiez s'il existe des paquets dont les adresses IP de destination correspondent à l'adresse IP du service kube-dns. Cela permet de s'assurer que les requêtes DNS atteignent la bonne destination pour la résolution. Si le trafic DNS n'arrive pas sur les bons pods, cela peut indiquer la présence d'une règle de réseau qui bloque les requêtes.
Rechercher une règle de réseau
Des règles de 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 de réseau, examinez-la et assurez-vous qu'elle autorise la communication DNS nécessaire. Par exemple, si vous disposez d'une règle de réseau qui bloque tout le trafic de sortie, elle bloquera également les requêtes DNS.
Si le résultat est No resources found in kube-system namespace
, cela signifie que vous n'avez aucune règle de réseau et que vous pouvez exclure cette cause pour 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 du débogage des requêtes DNS. Pour activer les requêtes, créez un pod basé sur un pod kube-dns existant. Toute modification apportée au déploiement kube-dns est automatiquement annulée.
L'activation de la journalisation temporaire des requêtes DNS est une procédure gourmande en ressources. Nous vous recommandons donc de supprimer le pod que vous créez dès que vous avez collecté un échantillon de journaux approprié.
Pour activer la journalisation temporaire des requêtes DNS, procédez comme suit :
Récupérez un pod kube-dns et stockez-le dans une variable nommée
POD
:POD=$(kubectl -n kube-system get pods --selector=k8s-app=kube-dns -o jsonpath="{.items[0].metadata.name}")
Créez un pod nommé
kube-dns-debug
. Ce pod est une copie du pod stocké dans la variablePOD
, mais avec la journalisation dnsmasq activée. Cette commande ne modifie pas le pod kube-dns d'origine :kubectl apply -f <(kubectl get pod -n kube-system ${POD} -o json | jq -e ' ( (.spec.containers[] | select(.name == "dnsmasq") | .args) += ["--log-queries"] ) | (.metadata.name = "kube-dns-debug") | (del(.metadata.labels."pod-template-hash")) ')
Inspectez les journaux :
kubectl logs -f --tail 100 -c dnsmasq -n kube-system kube-dns-debug
Vous pouvez également consulter les requêtes dans Cloud Logging.
Une fois que vous avez terminé de consulter les journaux de requêtes DNS, supprimez le pod
kube-dns-debug
:kubectl -n kube-system delete pod kube-dns-debug
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 liées au pod kube-dns, procédez comme suit :
Dans la console Google Cloud , accédez à la page Explorateur de journaux.
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.
Cliquez sur Exécuter la requête.
Examinez le résultat. L'exemple de résultat suivant montre une erreur possible :
{ "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 dû à plusieurs problèmes. Par exemple, le serveur en amont peut être mal configuré dans le fichier ConfigMap de kube-dns, ou le trafic réseau peut être élevé.
Si Cloud Logging n'est pas activé, consultez 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 à kube-dns ConfigMap
Si vous rencontrez soudainement des échecs de résolution DNS dans votre cluster, l'une des causes possibles est une modification incorrecte de la configuration apportée à kube-dns ConfigMap. En particulier, les modifications apportées aux définitions des domaines de simulation et des serveurs en amont peuvent entraîner des problèmes.
Pour vérifier si les paramètres du domaine de stub ont été mis à jour, procédez comme suit :
Dans la console Google Cloud , accédez à la page Explorateur de journaux.
Dans le volet "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"
Cliquez sur Exécuter la requête.
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 si le serveur en amont a été modifié, procédez comme suit :
Dans la console Google Cloud , accédez à la page Explorateur de journaux.
Dans le volet "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"
Cliquez sur Exécuter la requête.
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 de stub et aux serveurs en amont, mais que vous n'avez trouvé aucun résultat, recherchez toutes les modifications avec le 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 ci-dessous.
Problème : Expiration de délais DNS intermittente
Si vous constatez des délais d'expiration intermittents de la 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 en cours d'exécution sur le cluster et comparez-le au nombre total de nœuds GKE. S'il n'y a pas assez de ressources, envisagez de faire évoluer les pods kube-dns.
Pour améliorer la durée moyenne de résolution DNS, activez NodeLocal DNSCache.
La résolution DNS pour les 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 figurer 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 en
1
afin de rechercher uniquement 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 par intermittence à partir de certains nœuds
Si vous constatez que les requêtes DNS échouent par intermittence à partir de certains nœuds, vous pouvez observer les symptômes suivants :
- Lorsque vous exécutez des commandes dig sur l'adresse IP du service kube-dns ou sur l'adresse IP du pod, les requêtes DNS échouent par intermittence avec des délais d'attente.
- 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 :
- Effectuez un test de connectivité. Définissez le pod ou le nœud problématique comme source, et l'adresse IP du pod kube-dns comme destination. Cela vous permet de vérifier si vous avez mis en place les règles de pare-feu requises pour autoriser ce trafic.
Si le test n'est pas concluant 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 :
Dans la console Google Cloud , accédez à la page Explorateur de journaux.
Dans le volet "Requête", saisissez la requête suivante :
logName="projects/project-name/logs/cloudaudit.googleapis.com/activity" resource.type="gce_firewall_rule"
Cliquez sur Exécuter la requête. Utilisez le résultat 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.
Veillez à ne pas modifier les règles de pare-feu automatiques.
Si aucune modification n'a été apportée aux règles de pare-feu, 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 fonctionnels. 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 être à l'origine de problèmes. Pour en savoir plus sur cette incompatibilité, consultez La version du nœud n'est pas compatible avec la version du plan de contrôle.
Pour déterminer si les requêtes sont envoyées à l'adresse IP du service kube-dns appropriée, capturez le trafic réseau sur le nœud problématique et filtrez-le sur 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 avec succès.
Étapes suivantes
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.
Si vous ne trouvez pas de solution à votre problème dans la documentation, consultez Obtenir de l'aide pour obtenir une assistance supplémentaire, y compris des conseils sur les sujets suivants :
- Ouvrez une demande d'assistance en contactant le service client Google Cloud.
- Obtenir de l'aide de la communauté en posant des questions sur Stack Overflow et en utilisant le tag
google-kubernetes-engine
pour rechercher des problèmes similaires. Vous pouvez également rejoindre le canal Slack#kubernetes-engine
pour obtenir de l'aide auprès de la communauté. - Signaler des bugs ou demander des fonctionnalités à l'aide de l'outil public de suivi des problèmes.