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 :
- Zones internes : interrogent les serveurs autoritatifs
- Zones Kubernetes : interrogent le CoreDNS du cluster (
cluster.local) - 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.