Aller au contenu

Architecture de référence DNS

Vue d'ensemble

L'architecture DNS interne repose sur deux niveaux : des serveurs autoritatifs qui detiennent les enregistrements des zones internes, et des resolvers recursifs qui interrogent ces autoritatifs (et les DNS publics pour les zones externes).

graph TD
    Clients["Clients internes<br/>(serveurs, pods, VMs, postes, VPN)"]
    Clients -->|DNS 53/UDP+TCP| Resolvers
    subgraph Resolvers["Resolvers recursifs (CoreDNS forward + cache)"]
        R1["resolver-1<br/>10.30.2.10"]
        R2["resolver-2<br/>10.30.2.11"]
        R3["resolver-3<br/>10.30.2.12"]
    end
    Resolvers --> Zones["Zones internes<br/>(autoritatif)"]
    Resolvers --> Public["DNS publics<br/>(forward)"]
    Resolvers --> K8s["Kubernetes API<br/>(service discovery)"]

Composants de l'architecture

Serveurs autoritatifs

Les serveurs autoritatifs detiennent les enregistrements des zones internes. Avec CoreDNS, le plugin file ou auto sert les fichiers de zone :

Zone Perimetre Exemples d'enregistrements
internal.company.io Zone racine interne NS, SOA
production.internal.company.io Services de production app-api, db-master, cache-redis
enterprise.internal.company.io Services d'entreprise iam, mail, wiki, vdi
build.internal.company.io Chaîne logicielle gitea, harbor, argocd, sonar
mgmt.internal.company.io Management / ops vault, bastion, monitoring

Resolvers recursifs

Les resolvers reçoivent les requêtes des clients et :

  1. Zones internes : interrogent les serveurs autoritatifs
  2. Zones Kubernetes : interrogent le CoreDNS du cluster (cluster.local)
  3. Zones externes : forwardent vers les DNS publics (ou le DNS du FAI)

Cache DNS

Chaque resolver maintient un cache local pour reduire la latence et la charge :

Parametre Valeur recommandee Justification
Cache positif max 3600 s Respecter les TTL des zones
Cache negatif (NXDOMAIN) 300 s Eviter de marteler pour des noms inexistants
Taille du cache 10 000 entrees Adapter selon le nombre de services
Prefetch Active Rafraichir avant expiration pour les noms populaires

Integration Kubernetes

Dans un cluster Kubernetes, CoreDNS est déployé comme cluster DNS (namespace kube-system). Il résout automatiquement les noms de services :

graph LR
    subgraph K8s["Cluster Kubernetes"]
        PodA["Pod A"] --> CoreDNS["CoreDNS (cluster)"]
        PodB["Pod B"] --> CoreDNS
    end
    CoreDNS -->|cluster.local<br/>svc.cluster.local| Svc["Services K8s"]
    CoreDNS -->|*.internal.company.io| DNSint["DNS interne"]
    CoreDNS -->|* reste| DNSpub["DNS publics"]

Résolution dans Kubernetes

Nom demande Resolu par Résultat
app-api CoreDNS cluster (search domain) app-api.production.svc.cluster.local
app-api.production CoreDNS cluster app-api.production.svc.cluster.local
app-api.production.svc.cluster.local CoreDNS cluster IP du service Kubernetes
iam.enterprise.internal.company.io Forward vers DNS interne IP du serveur IAM
github.com Forward vers DNS publics IP publique

Configuration DNS des pods

Kubernetes configure automatiquement le /etc/resolv.conf des pods :

nameserver 10.96.0.10          # IP du service CoreDNS
search production.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

ndots et performance

La valeur ndots:5 par defaut signifie que tout nom avec moins de 5 points sera d'abord cherche dans les search domains. Pour iam.enterprise.internal.company.io (4 points), Kubernetes tentera d'abord iam.enterprise.internal.company.io.production.svc.cluster.local avant le nom reel. Pour les noms externes fréquents, utiliser un FQDN avec point final (github.com.) ou reduire ndots.

Zones internes et forward

Chaque perimetre fonctionnel a sa propre sous-zone DNS. Les resolvers savent vers quel autoritatif forwarder chaque zone :

graph LR
    subgraph Resolver["Resolver CoreDNS"]
        direction LR
    end
    Resolver -->|*.production.internal.company.io| AuthProd["auth-prod-1<br/>auth-prod-2"]
    Resolver -->|*.enterprise.internal.company.io| AuthEnt["auth-ent-1<br/>auth-ent-2"]
    Resolver -->|*.build.internal.company.io| AuthBuild["auth-build-1<br/>auth-build-2"]
    Resolver -->|cluster.local| K8sDNS["CoreDNS Kubernetes"]
    Resolver -->|* tout le reste| Public["1.1.1.1, 8.8.8.8"]

Failover et haute disponibilité

Regles de base

Regle Minimum Recommande
Resolvers recursifs 2 3 (un par zone de disponibilité)
Serveurs autoritatifs par zone 2 2-3
Synchronisation des zones Transfert de zone (AXFR/IXFR) ou backend partage (etcd) Backend partage

Stratégies de failover

Option 1 — IP virtuelle (VIP) : un keepalived ou équivalent bascule l'IP virtuelle du DNS vers un resolver sain.

graph LR
    Clients --> VIP["VIP 10.30.2.1"]
    VIP --> R1["resolver-1 (actif)"]
    VIP --> R2["resolver-2 (standby)"]

Option 2 — Multiples resolvers dans resolv.conf : les clients listent plusieurs serveurs DNS.

# /etc/resolv.conf
nameserver 10.30.2.10
nameserver 10.30.2.11
nameserver 10.30.2.12
options timeout:2 attempts:3 rotate

Option 3 — Load balancer : un load balancer (HAProxy, MetalLB) distribue les requêtes DNS.

Recommandation

L'option 3 (load balancer) est la plus robuste : elle distribue la charge et détecte les resolvers en panne via health checks actifs. Kubernetes utilise déjà cette approche avec un Service de type ClusterIP devant les pods CoreDNS.

Dimensionnement

Parametre Petite infra (\<100 services) Moyenne (100-1000) Grande (1000+)
Resolvers 2 3 3-5
CPU par resolver 0.25 vCPU 0.5 vCPU 1 vCPU
RAM par resolver 64 Mo 128 Mo 256 Mo
Cache entries 5 000 10 000 50 000
Requêtes/s (estimées) ~100 ~1 000 ~10 000

CoreDNS est tres economique en ressources. Un resolver CoreDNS avec cache gère facilement 10 000 requêtes/s avec 128 Mo de RAM.