Haute-disponibilité et Load-Balancing par Cascade de NS

©Disney/Pixar

 Un retour aux premiers amours de ce blog, avec, pour changer, une suite de billets système et réseau.

Cette série est issue d’une petite discussion que j’ai eu avec mon ami Horacio, du blog LostinBrittany, durant un projet technique professionnel commun.
Plutôt que de garder pour moi mes réflexions, autant vous les faire partager 🙂

Cette discussion concerne surtout le prochain billet de ce blog, mais avant de l’aborder, il fallait poser les bases d’une certaine architecture et c’est ce que nous allons tout d’abord voir aujourd’hui.

Je vais vous parler d’une technique qui paraît bien triviale mais étonnamment efficace et largement employée dans les architectures disposant de 2 branches d’accès Internet.

Après tout, dans votre soucis constant de disposer d’une architecture hautement disponible et partant du sacro-saint adage « on ne met pas les oeufs dans le même panier », vous avez décidé de confier l’accès internet de votre infrastructure à deux opérateurs différents (par exemple, si  > 2, cela marche aussi…)

Bien évidemment, cela peut aussi être l’hébergement de vos serveurs dédiés chez deux entités différentes, ou encore, plus simplement, des serveurs dédiés dans 2 datacenters différents, ou tout bêtement, de 2 serveurs dédiés devant lesquelles vous n’avez pas de load-balancer…

Quoi qu’il en soit, la multiplication des points d’entrées « Internet » de votre service sur plusieurs chemins différents, vous donne, déjà, une meilleure sérénité de sa disponibilité envers le « monde ».

L’inconvénient de ce choix est qu’il est difficile de positionner un Load-Balancer devant vos serveurs pour répartir la charge ou tout simplement de renvoyer tout le trafic sur le serveur « vivant » quand l’autre est tombé.

On ramenant le concept à deux serveurs web (que je vais utiliser pour un exemple plus « accessible » ), nous allons voir comment utiliser le service DNS pour aller sur l’un ou l’autre des serveurs et pouvoir basculer le trafic sur l’un des deux en cas de panne d’un accès (ou du décès de l’un des serveurs Web).

Dans un vision très habituelle des choses, que l’on rencontre fréquemment sur les architectures exposées par les sysadmins, la technique souvent utilisée est le « Round Robin DNS« .

Je vous rassure tout de suite, rien à voir avec des problèmes d’obésité d’un quelconque défenseur de la fôret de Sherwood, mais d’une bidouille d’un enregistrement dns.

En effet, pour un enregistrement de type A (un enregistrement DNS spécifiant un nom = une adresse IP  pour faire simple), on peut donner 2 entrées pour le même nom.

Exemple :

blog.guiguiabloc.fr  IN A 10.10.10.10
blog.guiguiabloc.fr  IN A 10.20.20.20

Les plus pointus allant même jusqu’à modifier l’entrée TTL pour peaufiner.

Résultat, alternativement, les requêtes sont envoyées sur 10.10.10.10 ou sur 10.20.20.20.

Le gros inconvénient de cette technique est que les requêtes iront toujours sur l’un ou l’autre, même si l’un des deux est mort… Un accès sur 2 n’aura donc pas de réponse… Gênant.
C’est donc une technique « a pas cher » de load-balancing, mais nullement une solution de haute-disponibilité (ou de Fail-Over).

Alors comment utiliser les DNS pour faire et du load-balancing et du fail-over ?
La réponse s’appelle du « Cascading NS » (ou cascade de serveurs NS).

Si une entrée DNS de type A fait la correspondance entre un nom d’hôte et une adresse IP, un enregistrement de type NS vous donne le serveur DNS ayant autorité sur le domaine (et qui donc sera à même de vous donner l’adresse IP (ou type A) du nom d’hôte que vous recherchez ou de vous indiquez à qui le demander).

Un dessin valant un long discours, regardons un peu le fonctionnement du cascading NS :

Que se passe t-il quand le client demande « blog.guiguiabloc.fr » ?

– Les autorités TLD répondent que le domaine « guiguiabloc.fr » est géré par les NS de tel registrar (OVH, GANDI, etc…) (je simplifie hein :p)

– Les serveurs DNS du Registrar répondent qu’il faut interroger deux autres NS, NS1.mondns.fr et NS2.mondns.fr qui sont autorité de zone pour le domaine « guiguiabloc.fr » (on arrive la sur VOS serveurs DNS) (1)

– Les serveurs DNS, ns1.mondns.fr et ns2.mondns.fr répondent qu’ils gèrent bien le domaine « guiguiabloc.fr » mais le sous-domaine « blog.guiguiabloc.fr » est géré par deux autres DNS, web-1.mondns.fr et web-2.mondns.fr (qui sont vos serveurs Web sur lesquelles tournent un serveur DNS ne s’occupant que de cette zone) (2)

– Le client interroge alors l’un des NS (web-1.mondns.fr ou web-2.mondns.fr) pour connaitre l’entrée A de blog.guiguiabloc.fr (3)

– Si c’est web-1.mondns.fr qui est interrogé, il répondra 10.10.10.10, si c’est web-2.mondns.fr, il répondra 10.20.20.20, avec une durée de vie d’1 minute de la correspondance (60 secondes plus tard, si le client doit demander de nouveau blog.guiguiabloc.fr, il devra demander de nouveau l’adresse IP (lors d’une nouvelle session par exemple).

Voila ce que donnera une demande de résolution :

guigui@Clara:~$ dig blog.guiguiabloc.fr
 
; <<>> DiG 9.7.3 <<>> blog.guiguiabloc.fr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41551
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
 
;; QUESTION SECTION:
;blog.guiguiabloc.fr.              IN      A
 
;; ANSWER SECTION:
blog.guiguiabloc.fr.       49      IN      A       10.10.10.10
 
;; AUTHORITY SECTION:
blog.guiguiabloc.fr.       49      IN      NS      web-1.mondns.fr.
 
;; ADDITIONAL SECTION:
web-1.mondns.fr.         3922    IN      A       10.10.10.10

Et 60 secondes plus tard :

...
;; ANSWER SECTION:
blog.guiguiabloc.fr.       60      IN      A       10.20.20.20
 
;; AUTHORITY SECTION:
blog.guiguiabloc.fr.       60      IN      NS      web-2.mondns.fr.
 
;; ADDITIONAL SECTION:
web-2.mondns.fr.         5006    IN      A       10.20.20.20

Vous avez compris que le site web blog.guiguiabloc.fr tourne sur les deux serveurs web avec chacun une IP différente.

A l’inverse du Round-Robin DNS, le client interroge les NS aléatoirement et prend la réponse du plus rapide (et donc également du plus proche géographiquement).
Rassurez vous, toute cette séquence ne prend que quelques millisecondes.

Mais que se passe-t-il quand web-1.mondns.fr tombe (et donc ne peut plus répondre).

 Le début est identique mais quand le client demande « blog.guiguiabloc.fr »  aux serveurs NS de la sous-zone, seul le « NS » 2 répondra.

Vous avez la un fail-over immédiat (tout au moins a 60 secondes après le crash) puisque NS1 ne répondra jamais.
La technique est aussi très efficace quand vous souhaitez retirer un des serveurs web de votre pool, il vous suffit d’arreter le serveur DNS dessus. Il ne répondra plus aux requètes NS et donc ne prendra pas de trafic 😀

La configuration des DNS est des plus basiques pour cela, il faut bien évidemment que les serveurs DNS de web-1.mondns.fr et web-2.mondns.fr soit chacun master (maître) (puisqu’ils donnent une entrée de type A différente).

Pré-requis, vous avez bien entendu défini une entrée de type A pour web-1 et web-2 dans la zone « mondns.fr ».

Sur vos serveurs DNS principaux (ns1.mondns.fr et ns2.mondns.fr), pour la zone « guiguiabloc.fr » (bien sûr remplacez tout cela par vos domaines/IP 😉 )

$TTL 600
@                IN SOA  ns1.mondns.fr. noc.mondns.fr. (
2013020400 ; serial
3600       ; refresh
3600       ; retry
3600000    ; expire
3600       ; minimum
)
 
IN NS ns1.mondns.fr.
IN NS ns2.mondns.fr.
blog                  IN NS web-1.mondns.fr.
                        IN NS web-2.mondns.fr.

Sur web-1, pour la zone « blog.guiguiabloc.fr » :

$ORIGIN .
$TTL 60
blog.guiguiabloc.fr                IN SOA  ns1.mondns.fr. noc.mondns.fr. (
2013020400 ; serial
3600       ; refresh
3600       ; retry
3600000    ; expire
3600       ; minimum
)
 
IN NS          web-1.mondns.fr.
IN A       10.10.10.10

Sur web-2, pour la zone « blog.guiguiabloc.fr »

$ORIGIN .
$TTL 60
blog.guiguiabloc.fr                IN SOA  ns1.mondns.fr. noc.mondns.fr. (
2013020400 ; serial
3600       ; refresh
3600       ; retry
3600000    ; expire
3600       ; minimum
)
 
IN NS          web-2.mondns.fr.
IN A       10.20.20.20

Bien entendu, je vous laisse adapter à votre configuration, c’est juste un exemple 🙂

Alors, elle n’est pas sympa cette technique ? 🙂

« oui,oui. Très sympa oh Grand Guiguiabloc, mais y’a quand même un problème ! »
« Ah ? Je t’écoute jeune Padawan »
« si le service web de web-1 plante par exemple, mais pas le serveur, mon DNS il répond toujours !!! et les visiteurs ils arrivent toujours sur mon serveur !! Ca craint ! »
« Je m’attendais à cette remarque, jeune youglin, et comme je suis dans une année de grande bonté, je vais te donner une solution pour cela »

« oh merci Grand Guiguiabloc !!! » (flap-flap-flap)

La solution pour couper votre DNS local sur votre serveur web (ou votre reverse-proxy hein) en cas de crash du service http s’appelle :
MONIT.

MONIT est un utilitaire qui surveille vos process (mais également vos répertoires, fichiers, programmes etc..) et execute des actions en cas de soucis.

L’action la plus courante est d’avertir l’admin (forcément :p) mais également par exemple, de tenter de relancer le programme.

Exemple pour surveiller le process Nginx

check process nginx with pidfile /var/run/nginx.pid
  start program = "/etc/init.d/nginx start"
  stop program  = "/etc/init.d/nginx stop"
  group www-data

Vous trouverez des exemples sur la page wiki du projet :

http://mmonit.com/wiki/Monit/ConfigurationExamples

En cas de non réponse du process, vous pouvez appeler un script par « exec » ‘de type « /etc/init.d/bind9 stop » 😉

Plus simple encore, un simple script bash appeler en crontab :

#!/bin/bash
#pre-requis blog.guiguiabloc.fr a une entrée dans
#le fichier /etc/hosts avec son ip locale
#pour éviter d'interroger les DNS
TESTING=`curl -sL -w "%{http_code} %{url_effective}\\n" "blog.guiguiabloc.fr" -o /dev/null`
if test "$TESTING" != "200 http://blog.guiguiabloc.fr"
then
echo "CA CHIE"
else
echo "ok"
fi

Et donc arreter le service DNS si « CA CA CHIE » 😀

En espérant que cela vous donne des idées

Amusez-vous bien 😀

 

 

Ce billet a été posté dans architecture, linux et taggé , . Bookmark ce permalink.

22 commentaires sur “Haute-disponibilité et Load-Balancing par Cascade de NS

  1. Tu oublies de parler de l’inconvénient principal de ce mécanisme, à savoir que tu dois du coup disposer d’un sous domaine et ce n’est pas compatible avec http://domain.tld 😉

  2. Merci pour le post ! Toujours aussi sympa à lire.

    Bien vu Steven ! une solution guiguiabloc ?

  3. Smart ‘n’ simple 🙂 – je vais tester ça dans une configuration satanique (euh, sur environnement MS je veux dire ^^) mais de toute façon j’ai mes HAProxy qui tournent et donc qui peuvent faire le frontal en GLB 🙂

  4. Pour en revenir au soucis du domaine sans sous domaine, généralement le service utilisé derrière est un serveur Web. Donc si on redirige le domaine vers le sous domaine www. avec un champ CNAME (comme c’est normalement toujours le cas…) puis qu’on met en place ton astuce de cascade de NS, alors ça fonctionne non ?

  5. Toujours le cas où ? 😉
    Dans ton explication, tu transforme donc les 2 serveurs Web en NS du domaine (t’enlève un étage).

  6. C’est ceci dit une assez ancienne façon de faire (qui tourne tjrs pour qq gros sites français, hein guigui ;), et on en prend soin) mais je ne partirai plus sur cette archi en 2013…

    Je combinerais plutôt anycast + hook sur dns recursif qui permet de résoudre uniquement un service répondant à un health check.

  7. Alors,

    concernant mettre un CNAME sur un domaine pour faire pointer sur un sous-domaine, ce n’est juste pas possible, il faut forcement un record A.

    C’est dans la RFC, un CNAME doit etre unique (contrairement a un A ou un NS par exemple)

    et donc mettre un

    @ IN NS dns1
    @ IN NS dns2
    @ IN CNAME plop

    le bind il va crier bien fort 🙂 donc pas de solution avec un CNAME

    concernant la solution 2013 sur l anycast, faut déjà l infra qui va bien, les routeur qui vont bien, le bgp qui va bien.. c’est moins facile à faire en labs.

    En plus en général l’anycast est surtout utilisé pour faire de la réponse à du service géolocalisé multi zone

  8. Bel article.

    Seul probleme a mon gout, c’est le non respect du ttl dns par des gros
    FAI francais (ttl inférieur à 30mn corrigé a 30mn)
    testez par exemple sur free avec le domaine dyn.com

    Ainsi un ttl de 5mn donne 30mn à 1h de migration effective.
    (et encore je parle de la majorité du trafic)

    Donc se baser la dessus pour couper un serveur pour maintenance, c’est
    faisable en attendant.

    Pour gérer la panne, plus génant.

    Si vous avez une solution pour bypasser suis preneur 🙂

  9. C’est le problème de Free pour pas le citer. Même chez OpenDNS le ttl est pas touché.
    Y’a malheureusement rien a faire si on utilise les DNS. Ces « gens » se donnent le droit de modifier des TTL de domaine dont il ne sont pas autorité, c’est pitoyable.
    Tout ca pour quoi ? Economiser du trafic DNS ? (c’est vrai que c’est énorme le trafic DNS…).
    Si chacun y joue de sa bidouille, un jour ou l’autre, plus rien ne marchera ou se comportera complètement différemment d’un FAI à l’autre. Si les RFC existent c’est pour quelque chose aussi.

  10. Très intéressant cet article

    Cependant je ne suis pas tout à fait d’accord sur un point 😉
    Tu dis « Le gros inconvénient de cette technique est que les requêtes iront toujours sur l’un ou l’autre, même si l’un des deux est mort… Un accès sur 2 n’aura donc pas de réponse… Gênant. »
    Mais il me semble que les navigateurs récent intègre le fait que s’il y a plusieurs IP retournés par le nslookup et que si une ne réponde pas, il bascule sur la deuxième IP proposer puis ainsi de suite. Ainsi on arrive toujours un serveur UP.
    Je viens de tester vite fait, et ça marche pour moi. Je me souviens pas avoir fait une quelconque bidouille dans mon navigateur n’y sur mon dns… . J’ai juste un petit délai de 1sec environ mais rien de bien méchant.

  11. Pas de soucis sur le fonctionnement de la solution mais dans des infras conséquentes actuelles, où la performance est de mise, il me semble, de mémoire, que le TTL d’un FQDN ne doit pas descendre en dessous de 3 minutes.
    Afin d’éviter des mises à jour dns trop fréquentes qui peuvent impacter la performance du site, surtout si on utilise plusieurs FQDN pour // les requêtes.

    Pour résoudre les problèmes de haute-dispo, j’aime opter pour un FailOver avec des ip flottantes sur chacun des noeuds (surtout dans des infras à 2 noeuds).
    Certes tu bouffes plus d’IP mais dans la majorité des cas les web/reverse sont dans un adressage privé …

  12. Pourquoi depuis le registrar ne pas configurer directement que pour le sous domaine : blog.guiguiabloc.fr le NS1 = web1.mondns.fr et NS2 = web2.mondns.fr ?

  13. Si vous avez décider de confier le service DNS à votre registrar, et que vous y gérer l’entrée A du sous-domaine, pourquoi pas.
    La plupart du temps, quand on monte de type d’infra, on a l’habitude de gérer aussi ses serveurs DNS de zone 🙂

  14. Nickel cet article, une belle explication avec des infographies claires et lisibles, Monit est vraiment un petit outil très utile qui devrait être présent partout … Pourrais tu me contacter par email, j’aurais une question à te poser sur ton article. Merci d’avance 😉 !