Contactez-nous

Fonctionnement du DNS interne (CoreDNS en détail)

Explorez le fonctionnement interne de CoreDNS, le serveur DNS standard de Kubernetes, et comprenez comment il assure la découverte de services au sein du cluster.

Le pilier de la découverte de services : le DNS

Dans un environnement dynamique comme Kubernetes, où les Pods sont créés et détruits fréquemment et où leurs adresses IP sont éphémères, un mécanisme fiable de découverte de services est indispensable. Comment un Pod 'frontend' peut-il trouver l'adresse IP actuelle d'un Pod 'backend' sans connaître son IP à l'avance ? La réponse principale réside dans le système DNS interne du cluster.

Kubernetes fournit un service DNS intégré qui attribue des noms de domaine stables aux Services. Les applications peuvent alors utiliser ces noms DNS prévisibles pour communiquer, et le système DNS se charge de résoudre ces noms en adresses IP de Services (ClusterIP) ou directement en adresses IP de Pods (pour les Services Headless).

Depuis Kubernetes 1.11, l'implémentation DNS par défaut et recommandée est CoreDNS. Il a remplacé l'ancienne solution (kube-dns). CoreDNS est un serveur DNS flexible et extensible, écrit en Go, qui s'intègre nativement avec l'API Kubernetes pour fournir la résolution de noms au sein du cluster.

Déploiement et architecture de CoreDNS

CoreDNS est généralement déployé dans le cluster comme un Deployment standard, souvent dans le namespace `kube-system`. Ce Deployment gère un ou plusieurs Pods CoreDNS pour assurer la haute disponibilité. Un Service de type ClusterIP, nommé `kube-dns` (pour des raisons de compatibilité historique) est créé devant ces Pods CoreDNS. C'est l'adresse IP de ce Service qui est fournie aux autres Pods du cluster comme serveur DNS primaire.

La configuration de CoreDNS est principalement gérée via un fichier appelé Corefile, qui est typiquement stocké dans une ConfigMap (par exemple, `coredns` dans `kube-system`). Le Corefile définit les zones DNS que CoreDNS doit servir et les plugins à utiliser pour chaque zone. CoreDNS adopte une architecture basée sur des plugins, où chaque plugin effectue une tâche spécifique (interroger l'API K8s, mettre en cache, transférer les requêtes, loguer, etc.).

Le Kubelet sur chaque noeud configure automatiquement le fichier /etc/resolv.conf de chaque nouveau Pod pour :

  • Utiliser l'adresse ClusterIP du Service `kube-dns` comme `nameserver`.
  • Inclure des chemins de recherche (`search`) appropriés, comme `.svc.cluster.local`, `svc.cluster.local`, et `cluster.local` (où `cluster.local` est le domaine de cluster par défaut, configurable). Ces chemins permettent aux applications d'utiliser des noms courts (ex: `my-service` au lieu de `my-service.my-namespace.svc.cluster.local`).

Le Corefile et les plugins clés

Un Corefile typique pour Kubernetes contient un bloc serveur pour le domaine du cluster (ex: `cluster.local`):

.:53 {
    errors
    health { # Rend CoreDNS observable par Kubelet/Probes
       lameduck 5s
    }
    ready # Signal de disponibilité pour le Service
    kubernetes cluster.local in-addr.arpa ip6.arpa { # Plugin principal pour K8s
       pods insecure # ou 'verified' ou 'disabled'
       upstream
       fallthrough in-addr.arpa ip6.arpa
    }
    prometheus :9153 # Expose les métriques pour Prometheus
    forward . /etc/resolv.conf { # Transfère les requêtes non-K8s
       max_concurrent 1000
    }
    cache 30 # Cache les réponses
    loop # Détecte les boucles de résolution simples
    reload 5s # Recharge la configuration si le Corefile change
    loadbalance # Equilibre la charge entre les serveurs upstream
}

Les plugins essentiels ici sont :

  • kubernetes : Le coeur de l'intégration. Il surveille l'API Server Kubernetes pour les Services et les Pods et génère les enregistrements DNS correspondants à la volée pour les requêtes concernant le domaine `cluster.local`.
  • forward : Transfère les requêtes DNS qui ne concernent pas le domaine du cluster (ex: `google.com`) aux serveurs DNS en amont (upstream), généralement ceux configurés sur le noeud hôte (lus depuis `/etc/resolv.conf` du noeud).
  • cache : Met en cache les réponses DNS pour améliorer les performances et réduire la charge sur les serveurs upstream.
  • errors, log, health, ready, prometheus : Fournissent des fonctionnalités de gestion des erreurs, de journalisation, de vérification de l'état et d'exposition de métriques.

Génération des enregistrements DNS par le plugin `kubernetes`

Le plugin `kubernetes` est responsable de la création des enregistrements DNS pour les ressources Kubernetes :

  • Services (non Headless) : Pour un Service nommé `my-svc` dans le namespace `my-ns` avec un ClusterIP `10.0.0.10`, il crée un enregistrement A :
    my-svc.my-ns.svc.cluster.local. IN A 10.0.0.10
  • Services Headless : Pour un Service Headless `my-headless-svc` dans `my-ns` soutenu par des Pods avec IPs `1.1.1.1` et `2.2.2.2`, il crée plusieurs enregistrements A :
    my-headless-svc.my-ns.svc.cluster.local. IN A 1.1.1.1
    my-headless-svc.my-ns.svc.cluster.local. IN A 2.2.2.2
    Cela permet aux clients de découvrir directement les IPs des Pods.
  • Pods : Si l'option `pods insecure` (ou `verified`) est activée, il peut créer des enregistrements A pour les Pods, souvent sous la forme (IP avec tirets) :
    1-1-1-1.my-ns.pod.cluster.local. IN A 1.1.1.1
  • SRV Records : Pour les ports nommés dans un Service (ex: port `http` sur `my-svc`), il crée des enregistrements SRV :
    _http._tcp.my-svc.my-ns.svc.cluster.local. SRV ... (pointant vers le nom A du Service et le numéro de port). Pour les Services Headless, il crée des enregistrements SRV pointant vers les noms A des Pods individuels et le port cible.
  • PTR Records (Reverse DNS) : Si configuré (via `fallthrough in-addr.arpa ip6.arpa`), il peut répondre aux requêtes DNS inverses pour les IPs des Services et des Pods.

Le processus de résolution d'un nom

Lorsqu'un Pod (client) tente de résoudre un nom de service, par exemple `backend-svc` depuis le namespace `frontend-ns`:

  1. La librairie de résolution du Pod lit /etc/resolv.conf.
  2. Elle essaie d'abord de résoudre `backend-svc.frontend-ns.svc.cluster.local` (en utilisant le premier chemin de recherche).
  3. La requête DNS est envoyée à l'IP du Service `kube-dns` (ClusterIP).
  4. Le Load Balancer du Service `kube-dns` (géré par Kube-proxy) route la requête vers l'un des Pods CoreDNS disponibles.
  5. Le Pod CoreDNS reçoit la requête sur le port 53.
  6. Le plugin `kubernetes` intercepte la requête car elle correspond au domaine `cluster.local`.
  7. Il interroge ses données internes (synchronisées depuis l'API Server) pour trouver le Service `backend-svc` dans le namespace `frontend-ns`.
  8. S'il le trouve, il renvoie l'enregistrement A correspondant (l'IP ClusterIP du Service `backend-svc`).
  9. S'il ne trouve pas `backend-svc` dans `frontend-ns`, la résolution essaie le chemin suivant `backend-svc.svc.cluster.local`, puis `backend-svc.cluster.local`. Si aucune correspondance interne n'est trouvée pour le domaine du cluster.
  10. Si la requête concerne un domaine externe (ex: `www.google.com`), le plugin `kubernetes` ne la traite pas. La requête passe au plugin suivant dans la chaîne, typiquement `forward`.
  11. Le plugin `forward` envoie la requête aux serveurs DNS upstream définis (ceux du noeud).
  12. La réponse (interne ou externe) est renvoyée au Pod client, potentiellement après avoir été mise en cache par le plugin `cache`.

CoreDNS, grâce à son intégration étroite avec l'API Kubernetes et sa configuration flexible via le Corefile, fournit ainsi un service DNS robuste et performant, essentiel à la découverte dynamique des services au sein du cluster.