Comment résoudre les échecs DNS avec Amazon EKS ?

Dernière mise à jour : 09/11/2021

Les applications ou les pods qui utilisent CoreDNS dans mon cluster Amazon Elastic Kubernetes Service (Amazon EKS) échouent aux résolutions de noms DNS internes ou externes.

Brève description

Les pods qui s'exécutent à l'intérieur du cluster Amazon EKS utilisent l'adresse IP du cluster du service CoreDNS comme serveur de noms par défaut pour interroger les enregistrements DNS internes et externes. S'il y a des problèmes avec les pods CoreDNS, la configuration du service ou la connectivité, les applications peuvent échouer aux résolutions DNS.

Les pods CoreDNS sont extraits par un objet de service appelé kube-dns. Pour résoudre les problèmes liés à vos pods CoreDNS, vérifiez que tous les composants du service kube dns fonctionnent. Ces composants incluent, sans s'y limiter, les options de point de terminaison de service et les règles iptables.

Résolution

La résolution suivante s'applique au ClusterIP CoreDNS 10.100.0.10.

1.    Obtenez le ClusterIP de votre service CoreDNS :

kubectl get service kube-dns -n kube-system

2.    Vérifiez que les points de terminaison DNS sont exposés et dirigés vers des pods CoreDNS :

kubectl -n kube-system get endpoints kube-dns

Sortie :

NAME       ENDPOINTS                                                        AGE
kube-dns   192.168.2.218:53,192.168.3.117:53,192.168.2.218:53 + 1 more...   90d

Remarque : si la liste des points de terminaison est vide, vérifiez alors le statut des pods CoreDNS.

3.    Vérifiez qu'un groupe de sécurité ou une liste de contrôle d'accès réseau (ACL réseau) ne bloque pas les pods lorsqu'ils communiquent avec CoreDNS.

Pour plus d'informations, consultez la section Pourquoi mes pods ne se connectent-ils pas à d'autres pods dans Amazon EKS ?

Vérifiez que le pod kube-proxy fonctionne

Vérifiez que le pod kube-proxy a accès aux serveurs d'API de votre cluster en recherchant dans vos journaux les erreurs d'expiration dans le plan de contrôle. Vérifiez également les erreurs 403 non autorisées.

Obtenez les journaux kube-proxy :

kubectl logs -n kube-system --selector 'k8s-app=kube-proxy'

Remarque : kube-proxy obtient les points de terminaison du plan de contrôle et crée les règles iptables sur chaque nœud.

Se connecter au pod d'application pour résoudre le problème DNS

1.    Afin d'exécuter des commandes à l'intérieur de vos pods d'application, exécutez la commande suivante pour accéder à un shell à l'intérieur du pod en cours d'exécution :

$ kubectl exec -it your-pod-name -- sh

Si votre pod d'application n’a pas de binaire shell disponible, vous recevrez une erreur similaire à ce qui suit :

OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown
command terminated with exit code 126

Pour déboguer, mettez à jour l'image utilisée dans votre fichier manifeste afin d'utiliser une autre image, comme l'image busybox (à partir du site web Docker).

2.    Pour vérifier que l'adresse IP du cluster du service kube-dns se trouve dans le /etc/resolv.conf de votre pod, exécutez la commande suivante dans le shell à l'intérieur du pod :

cat /etc/resolv.conf

L'exemple resolv.conf suivant montre un pod qui est configuré pour être dirigé vers 10.100.0.10 pour les requêtes DNS. L'adresse IP doit correspondre à l'adresse ClusterIP de votre service kube dns :

nameserver 10.100.0.10
search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal
options ndots:5

Remarque : vous pouvez gérer la configuration DNS de votre pod avec le champ dnsPolicy de la spécification de pod. Si ce champ n'est pas renseigné, lastratégie DNS ClusterFirst est utilisée par défaut.

3.    Pour vérifier que votre pod peut résoudre un domaine interne à l'aide du ClusterIP par défaut exécutez la commande suivante dans le shell à l'intérieur du pod :

nslookup kubernetes 10.100.0.10

Sortie :

Server:     10.100.0.10
Address:    10.100.0.10#53
Name:       kubernetes.default.svc.cluster.local
Address:    10.100.0.1

4.    Pour vérifier que votre pod peut résoudre un domaine externe à l'aide du ClusterIP par défaut, exécutez la commande suivante dans le shell à l'intérieur du pod :

nslookup amazon.com 10.100.0.10

Sortie :

Server:     10.100.0.10
Address:    10.100.0.10#53
Non-authoritative answer:
Name:   amazon.com
Address: 176.32.98.166
Name:    amazon.com
Address: 205.251.242.103
Name:    amazon.com
Address: 176.32.103.205

5.    Pour vérifier que votre pod peut résoudre directement à l'aide de l'adresse IP du pod CoreDNS, exécutez la commande suivante dans le shell à l'intérieur du pod :

nslookup kubernetes COREDNS_POD_IP

nslookup amazon.com COREDNS_POD_IP

Remarque : remplacez COREDNS_POD_IP par l'une des adresses IP de point de terminaison des points de terminaison kubectl get que vous avez utilisés précédemment.

Obtenir des journaux plus détaillés à partir de pods CoreDNS pour le débogage

1.    Activez le journal de débogage des pods CoreDNS et ajoutez le plugin log à CoreDNS ConfigMap :

kubectl -n kube-system edit configmap coredns

2.    Dans l'écran de l'éditeur qui s'affiche dans la sortie, ajoutez la chaîne de journal. Par exemple :

kind: ConfigMap
apiVersion: v1
data:
  Corefile: |
    .:53 {
        log    # Enabling CoreDNS Logging
        errors
        health
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          upstream
          fallthrough in-addr.arpa ip6.arpa
        }
        ...
...

Remarque : le rechargement de la configuration CoreDNS dure plusieurs minutes. Vous pouvez redémarrer les pods un par un pour appliquer les modifications immédiatement.

3.    Vérifiez si les journaux CoreDNS échouent ou obtiennent des résultats du pod d'application :

kubectl logs --follow -n kube-system --selector 'k8s-app=kube-dns'

Mettre à jour la valeur ndots

DNS utilise nameserver pour les résolutions de noms qui est généralement le ClusterIP d'un service kube-dns. DNS utilise search (recherche) pour transformer un nom de requête en nom de domaine pleinement qualifié. La valeur ndots correspond au nombre de points qui doivent apparaître dans un nom pour résoudre une requête avant qu'une requête absolue initiale ne soit effectuée.

Par exemple, vous pouvez définir l'option ndots sur la valeur par défaut 5 dans un nom de domaine qui n'est pas pleinement qualifié. Ensuite, tous les domaines externes qui ne relèvent pas du domaine interne cluster.local sont ajoutés aux domaines de recherche avant d'envoyer des requêtes.

Consultez l'exemple suivant avec le paramètre /etc/resolv.conf du pod d'application :

nameserver 10.100.0.10
search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal
options ndots:5

CoreDNS recherche cinq points dans le domaine interrogé. Si le pod effectue un appel de résolution DNS pour amazon.com, vos journaux se présenteront alors comme suit :

[INFO] 192.168.3.71:33238 - 36534 "A IN amazon.com.default.svc.cluster.local. udp 54 false 512" NXDOMAIN qr,aa,rd 147 0.000473434s
[INFO] 192.168.3.71:57098 - 43241 "A IN amazon.com.svc.cluster.local. udp 46 false 512" NXDOMAIN qr,aa,rd 139 0.000066171s
[INFO] 192.168.3.71:51937 - 15588 "A IN amazon.com.cluster.local. udp 42 false 512" NXDOMAIN qr,aa,rd 135 0.000137489s
[INFO] 192.168.3.71:52618 - 14916 "A IN amazon.com.ec2.internal. udp 41 false 512" NXDOMAIN qr,rd,ra 41 0.001248388s
[INFO] 192.168.3.71:51298 - 65181 "A IN amazon.com. udp 28 false 512" NOERROR qr,rd,ra 106 0.001711104s

Remarque : NXDOMAIN signifie que l'enregistrement de domaine est introuvable et NOERROR signifie que l'enregistrement de domaine a été trouvé.

Chaque domaine de recherche est précédé d'amazon.com avant d'effectuer l'appel final sur le domaine absolu à la fin. Un point (.) est ajouté à la fin du nom de domaine final, ce qui en fait un nom de domaine pleinement qualifié. Cela signifie que pour chaque requête de nom de domaine externe, il peut y avoir quatre à cinq appels supplémentaires, ce qui peut surcharger le pod CoreDNS.

Afin de résoudre ce problème, modifiez ndots en 1 (pour ne rechercher qu'un seul point). Ou ajoutez un point (. ) à la fin du domaine interrogé ou utilisé. Par exemple :

nslookup example.com.

Prenez en considération les limites (AmazonProvidedDNS) du résolveur VPC

Le résolveur Amazon Virtual Private Cloud (Amazon VPC) peut accepter uniquement une limite stricte maximale de 1024 paquets par seconde et par interface réseau. Si plusieurs pods CoreDNS se trouvent sur le même nœud, les probabilités d'atteindre cette limite sont plus élevées pour les requêtes de domaines externes.

Pour utiliser les règles PodAntiAffinity (du site web Kubernetes) afin de programmer des pods CoreDNS sur des instances distinctes, ajoutez les options suivantes au déploiement CoreDNS :

podAntiAffinity:
  preferredDuringSchedulingIgnoredDuringExecution:
  - podAffinityTerm:
      labelSelector:
        matchExpressions:
        - key: k8s-app
          operator: In
          values:
          - kube-dns
      topologyKey: kubernetes.io/hostname
    weight: 100

Utiliser tcpdump pour capturer des paquets CoreDNS des composants masters Amazon EKS

Utilisez l'outil tcpdump afin d'effectuer une capture de paquets pour diagnostiquer les problèmes de résolution DNS. Cet outil permet de vérifier si le trafic réseau pour les requêtes DNS atteint vos pods CoreDNS et s'il existe des problèmes de connectivité réseau sous-jacents. Pour utiliser tcpdump, procédez comme suit.

1.    Localisez un composant master sur lequel un pod CoreDNS est en cours d'exécution :

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

2.    Utilisez SSH pour vous connecter au composant master où un pod CoreDNS est en cours d'exécution et installez l'outil tcpdump :

sudo yum install tcpdump –y

3.    Localisez l'ID de processus de pod CoreDNS sur le composant master :

ps ax | grep coredns

4.    À partir du composant master, effectuez une capture de paquets sur le réseau de pods CoreDNS pour surveiller le trafic réseau sur le port UDP 53 :

sudo nsenter -n -t PID tcpdump udp port 53

5.    À partir d'un terminal distinct, obtenez le service CoreDNS et les IP des pods :

kubectl describe svc kube-dns -n kube-system

Remarque : notez l'adresse IP du service située dans le champ « IP » et les adresses IP des pods situées dans le champ « Endpoints » (Points de terminaison).

6.    Lancez un pod à partir duquel vous testerez le service DNS. L'exemple suivant utilise une image de conteneur Ubuntu :

kubectl run ubuntu --image=ubuntu sleep 1d

kubectl exec -it ubuntu sh

7.    Utilisez l'outil nslookup pour effectuer une requête DNS sur un domaine, tel que amazon.com :

nslookup amazon.com

Exécutez la même requête explicitement sur l'adresse IP du service CoreDNS de l'étape 5 :

nslookup amazon.com COREDNS_SERVICE_IP

Exécutez la requête sur chacune des adresses IP des pods CoreDNS de l'étape 5 :

nslookup amazon.com COREDNS_POD_IP

Remarque : si plusieurs pods CoreDNS sont en cours d'exécution, effectuez plusieurs requêtes afin qu'au moins une requête soit envoyée au pod à partir duquel vous capturez le trafic.

8.    Examinez les résultats de la capture de paquets.

Si vous rencontrez des délais d'expiration de requête DNS vers le pod CoreDNS que vous surveillez et que la requête ne s'affiche pas dans la capture de paquets, il est possible que vous rencontriez un problème de connectivité réseau. Assurez-vous de vérifier l'accessibilité du réseau entre les composants masters.

Si vous observez un délai d'expiration de requête DNS par rapport à une adresse IP de pod à partir duquel vous ne capturez pas, suivez les étapes 2 à 4 pour effectuer une autre capture de paquets sur le composant master associé.

Afin d'enregistrer les résultats d'une capture de paquets pour référence ultérieure, ajoutez l'indicateur -w FILE_NAME à la commande tcpdump. L'exemple suivant écrit les résultats dans un fichier nommé capture.pcap :

tcpdump -w capture.pcap udp port 53

CoreDNS GA for Kubernetes cluster DNS (Disponibilité générale (GA) de CoreDNS pour DNS de cluster Kubernetes)

Cet article vous a-t-il été utile ?


Besoin d'aide pour une question technique ou de facturation ?