NGINX Plus R9 introduit la possibilité d'inverser le proxy et d'équilibrer la charge du trafic UDP, une amélioration significative des capacités d'équilibrage de charge de couche 4 de NGINX Plus.
Cet article de blog examine les défis liés à l'exécution d'un serveur DNS dans une infrastructure d'application moderne pour illustrer comment NGINX Open Source et NGINX Plus peuvent équilibrer efficacement la charge du trafic UDP et TCP. (Les contrôles de santé [actifs] des applications sont exclusifs à NGINX Plus, mais sinon les informations contenues dans ce blog s’appliquent également à NGINX Open Source ; par souci de concision, nous ferons référence à NGINX Plus pour le reste de l’article).
[Éditeur – Pour un aperçu de toutes les nouvelles fonctionnalités de NGINX Plus R9, voir Annonce de NGINX Plus R9 sur notre blog.]
Contrairement au protocole TCP, le protocole UDP, de par sa conception, ne garantit pas la livraison de bout en bout des données. C’est comme envoyer un message par un pigeon voyageur : vous savez avec certitude que le message a été envoyé, mais vous ne pouvez pas être sûr qu’il est arrivé. Cette approche « sans connexion » présente plusieurs avantages, notamment une latence inférieure à celle du TCP, à la fois parce que les messages individuels plus petits du protocole UDP utilisent moins de bande passante et parce qu’il n’y a pas de processus de négociation pour établir une connexion. UDP laisse le problème de la détection des délais d’attente et d’autres problèmes au niveau du réseau au développeur de l’application. Mais qu’est-ce que cela signifie pour le DNS ?
Comme plusieurs autres protocoles basés sur UDP, DNS utilise un flux de données de type requête-réponse. Par exemple, un client DNS demande l’adresse IP correspondant à un nom d’hôte et reçoit une réponse. Si une réponse n’arrive pas dans un délai donné, le client DNS envoie la même requête à un serveur DNS « de secours ». Cependant, devoir attendre la période de temporisation avant de réessayer une demande peut transformer ce qui est généralement un processus extrêmement rapide (mesuré en millisecondes) en un processus très lent (mesuré en secondes).
L'utilisation de NGINX Plus pour proxy et équilibrer la charge du trafic DNS réduit le nombre d'occasions où le client rencontre un délai d'attente. Avec plusieurs serveurs DNS derrière l'équilibreur de charge NGINX Plus, les clients ne subissent un délai d'attente que lorsqu'il existe une partition réseau entre le client et NGINX Plus. Les problèmes liés aux serveurs DNS eux-mêmes ne sont pas rencontrés par le client lorsque NGINX Plus utilise des contrôles de santé des applications . En surveillant la disponibilité et le temps de réponse de chaque serveur, NGINX Plus évite d'envoyer des requêtes client à un serveur défectueux.
Bien que la grande majorité du trafic DNS passe par UDP, il existe des opérations DNS courantes qui utilisent TCP. Le DNS utilise UDP pour les petits messages (jusqu'à 512 octets), mais TCP pour les opérations qui nécessitent (ou sont susceptibles de nécessiter) des messages plus volumineux. Historiquement, TCP était utilisé avec DNS uniquement pour les transferts de zone d'un serveur de noms principal faisant autorité vers ses serveurs de noms secondaires. Cependant, avec l’évolution vers les conteneurs et les infrastructures immuables, le DNS est de plus en plus utilisé comme mécanisme principal de découverte de services, grâce à l’utilisation d’enregistrements SRV
.
Les enregistrements DNS SRV
ont été initialement introduits pour les combinés VoIP (Voice over IP) utilisant SIP pour découvrir leurs serveurs, mais peuvent être utilisés pour tout type de service. Cependant, les enregistrements SRV
incluent beaucoup plus d’informations que la plupart des autres types d’enregistrements DNS. Par conséquent, seulement environ 10 enregistrements SRV
peuvent être intégrés dans la réponse UDP standard de 512 octets, contre environ 30 enregistrements A.
Lorsqu'une réponse DNS dépasse la limite de 512 octets, les 512 premiers octets sont renvoyés mais la réponse est signalée comme « tronquée ». À ce stade, un client DNS peut soit gérer la réponse tronquée du mieux qu'il peut, soit réessayer la même demande en utilisant TCP.
Cela signifie que lors de l'équilibrage de la charge des serveurs DNS dans une infrastructure réseau moderne, NGINX Plus peut s'attendre à recevoir un mélange de trafic UDP et TCP.
L’illustration suivante montre une vue simplifiée d’un environnement de microservices avec deux équilibreurs de charge. L'équilibreur de charge frontal traite les requêtes des clients publics de l'application, en sélectionnant la meilleure instance de microservice et en exécutant de nombreuses autres fonctions dont nous ne parlerons pas ici. Nous nous concentrerons sur l’équilibreur de charge DNS, qui se situe entre l’environnement des microservices et les serveurs DNS qui fournissent des informations de découverte de services aux microservices.
NGINX Plus implémente l'équilibrage de charge de couche 4 dans le module Stream , donc l'équilibrage de charge UDP et TCP est configuré dans le bloc de flux
comme indiqué dans l'extrait suivant.
Avertissement: Vous ne pouvez pas simplement ajouter cet extrait de configuration en tant que nouveau fichier dans le répertoire /etc/nginx/conf.d . Une erreur de validation se produit (« la directive de flux n'est pas autorisée ici »), car le fichier de configuration par défaut de NGINX Plus nginx.conf inclut le contenu des fichiers du répertoire conf.d dans le bloc http
. La solution la plus simple est d'inclure le bloc de flux
complet directement dans nginx.conf .
flux { serveurs_dns_en_amont {
serveur 192.168.136.130:53;
serveur 192.168.136.131:53;
}
serveur {
écouter 53 udp;
écouter 53; #tcp
proxy_pass serveurs_dns;
journal_d'erreurs /var/log/nginx/dns.log info;
}
}
Nous définissons d’abord le groupe de serveurs DNS en amont. Les directives du serveur
spécifient le numéro de port sur lequel nos serveurs en amont écoutent, 53 (le port bien connu pour DNS).
Le bloc server{}
définit la manière dont NGINX Plus gère le trafic DNS entrant. Les deux directives d'écoute
indiquent à NGINX Plus d'écouter sur le port 53 le trafic UDP et TCP. TCP est le protocole de couche 4 par défaut pour le module Stream, nous ne le spécifions donc pas explicitement comme paramètre comme nous le faisons pour UDP.
La directive proxy_pass
indique à NGINX Plus ce qu'il doit faire avec le trafic qu'il écoute. Ici, nous transmettons ce trafic au groupe en amont dns_servers . NGINX Plus utilise automatiquement UDP lors de la transmission des requêtes UDP des clients aux serveurs en amont (et TCP pour les requêtes TCP des clients), nous n'avons donc pas besoin de spécifier explicitement le protocole de couche 4 dans le groupe en amont.
Il n'y a pas de directive access_log
dans le module Stream, car NGINX Plus n'inspecte pas la charge utile des segments TCP ou des datagrammes UDP (comme il le fait pour les paquets HTTP). Cependant, nous pouvons utiliser le paramètre info
de la directive error_log
pour enregistrer le traitement de la connexion et les événements proxy.
[Éditeur – La journalisation des accès a été activée dans le module Stream après la publication de ce blog, dans NGINX Open Source 1.11.4 et NGINX Plus R11 .]
Pour améliorer la disponibilité de nos serveurs DNS, nous pouvons ajouter quelques directives supplémentaires et configurer des contrôles de santé actifs (d'application).
La première directive supplémentaire est proxy_responses
, qui indique le nombre de réponses que NGINX Plus attend pour chaque requête UDP proxy. Dans notre cas, après avoir reçu une seule réponse, NGINX Plus arrête immédiatement d'attendre d'autres réponses, ce qui libère la mémoire et le socket utilisés pour cette session.
La deuxième directive supplémentaire, proxy_timeout
, détermine combien de temps NGINX Plus attend une réponse du serveur (ici, nous réduisons la valeur par défaut de 10 minutes à 1 seconde). Si NGINX Plus ne reçoit aucune réponse dans ce délai, il essaie le serveur suivant dans le groupe en amont et marque le serveur en amont qui ne répond pas comme indisponible pendant une période définie (10 secondes par défaut) afin qu'aucun autre client ne subisse un retard induit par un dépassement de délai pendant cette période.
serveur { écouter 53 udp ; écouter 53 ; #tcp proxy_pass dns_servers ; journal_d'erreurs /var/log/nginx/dns.log info ; proxy_responses 1 ; proxy_timeout 1s ; }
Nous pouvons également modifier la durée pendant laquelle un serveur est marqué comme indisponible, en incluant l'option fail_timeout
à la directive server
dans le groupe en amont. Avec le paramètre suivant, NGINX Plus marque les serveurs en amont défaillants comme indisponibles pendant 60 secondes :
serveurs DNS en amont { serveur 192.168.136.130:53 fail_timeout=60s ; serveur 192.168.136.131:53 fail_timeout=60s ; }
Cela nous permet de contrôler le délai qu'un client subit en cas de défaillance de l'un de nos serveurs DNS. Cependant, si une requête TCP est tentée vers un serveur DNS défaillant, la vérification des erreurs inhérente à TCP permet à NGINX Plus de le marquer automatiquement comme indisponible afin que les requêtes TCP ou UDP ultérieures vers ce serveur soient évitées.
La fonctionnalité de contrôle de santé actif de NGINX Plus est un outil supplémentaire et extrêmement précieux pour la haute disponibilité de tout service à charge équilibrée, y compris DNS. Plutôt que d'attendre qu'une requête TCP réelle d'un client DNS échoue avant de marquer le serveur DNS comme étant en panne, nous demandons à NGINX Plus de tenter périodiquement une connexion TCP sur le port 53 pour déterminer si le serveur DNS est à la fois opérationnel et fonctionne correctement, en incluant la directive health_check
avec son paramètre port=53
dans le bloc server{}
. (NGINX Plus envoie par défaut des contrôles de santé au port spécifié par la directive listen
, 53 dans notre cas. Nous utilisons donc ici le paramètre pour configurer explicitement la valeur par défaut, mais nous pourrions spécifier un port différent si nous modifions également nos serveurs DNS pour répondre au trafic sur celui-ci.)
Avec UDP, nous pouvons aller plus loin et configurer un contrôle de santé actif qui effectue une véritable recherche DNS pour un enregistrement connu. Par exemple, nous pouvons placer l’enregistrement CNAME
suivant dans le fichier de zone pour le même sous-domaine que celui utilisé pour la découverte de services dans l’environnement de microservices.
contrôle de santé DANS CNAME healthy.svcs.example.com.
Étant donné la nature légère de l’UDP, nous pouvons surveiller le trafic réseau et extraire facilement la chaîne d’octets qui représente une recherche DNS. Nous créons ensuite un bloc de configuration de correspondance
avec cette chaîne comme paramètre de la directive d'envoi
. La directive expect
spécifie la réponse que le serveur doit renvoyer pour être considéré comme sain.
match dns_lookup {
envoyer x00x01x00x00x00x01x00x00x00x00x00x00x06x68x65x61 ...;
attendre ~* "healthy.svcs.example.com.";
}
L’avantage de ce contrôle de santé approfondi au niveau de l’application est que même si votre serveur de noms est opérationnel, l’exécution d’une véritable recherche DNS pour votre domaine de production révèle des problèmes de configuration et de corruption des données qui pourraient autrement causer des problèmes en aval.
L' équipe d'assistance NGINX Plus peut vous aider à préparer les contrôles de santé UDP pour les recherches DNS et d'autres protocoles.
L'extrait suivant met en évidence les directives supplémentaires requises pour les contrôles de santé actifs.
stream { en amont dns_servers { zone dns_mem 64k ; serveur 192.168.136.130:53 fail_timeout=60s; serveur 192.168.136.131:53 fail_timeout=60s; } match dns_lookup { envoyer x00x01x00x00x00x01x00x00x00x00x00x00x00x06x68x65x61 ...; attendre ~* "healthy.svcs.example.com."; } serveur { écouter 53 udp; écouter 53; #tcp health_check match=dns_lookup intervalle=20 échecs=2 passes=2 udp; health_check intervalle=20 échecs=1 passes=2 port=53; #tcp proxy_pass dns_servers; journal_d'erreurs /var/log/nginx/dns.log débogage ; réponses_proxy 1 ; délai_proxy 1 s ; } }
La directive zone
définit une zone de mémoire partagée appelée dns_mem , qui rend les résultats des contrôles de santé (et d'autres informations d'état) disponibles pour tous les processus de travail NGINX Plus.
La directive match
est discutée juste au-dessus.
La directive health_check
comporte un certain nombre de paramètres que vous pouvez ajuster pour votre environnement. Nous définissons ici des contrôles de santé distincts pour UDP et TCP respectivement. En raison de la différence entre UDP et TCP, nous exigeons deux échecs successifs de vérification de l’état UDP avant de marquer le serveur DNS comme défectueux, mais un seul échec TCP. Pour les deux protocoles, nous avons besoin de deux réponses réussies avant de marquer un serveur comme étant à nouveau sain, afin d'éviter d'envoyer des requêtes à un serveur instable et « instable ».
L’un des avantages de la définition d’un seul groupe en amont de serveurs DNS pour le trafic UDP et TCP est qu’un échec de vérification de l’état de l’un ou l’autre protocole marque le serveur comme non sain et le supprime du pool à charge équilibrée.
Bien que le déploiement de seulement deux serveurs back-end puisse constituer une solution de haute disponibilité efficace, les capacités d’équilibrage de charge de NGINX Plus vous permettent de faire évoluer les serveurs back-end horizontalement à l’insu du client.
Il est peu probable que l’exemple d’environnement de microservices décrit ci-dessus nécessite une mise à l’échelle des serveurs DNS principaux. Cependant, un FAI fournissant des services DNS à tous ses abonnés subit une charge constante et un potentiel de pics énormes, créant le besoin d'un grand nombre de serveurs DNS et d'un proxy frontal pour équilibrer la charge du trafic entre eux.
Tous les algorithmes d'équilibrage de charge NGINX et NGINX Plus sont disponibles pour TCP et UDP ainsi que HTTP :
(Vous pouvez également configurer des poids sur tous les algorithmes pour augmenter encore plus leur efficacité. Pour une discussion, voir la section sur les poids dans Choisir une technique d'équilibrage de charge NGINX Plus sur notre blog.)
Alors que les requêtes HTTP peuvent varier énormément en termes de charge et de demandes de traitement imposées aux serveurs principaux, les requêtes DNS génèrent généralement toutes la même charge. Pour cette raison, il est peu probable que les algorithmes Least Connections et Least Time donnent un avantage sur Round Robin. En particulier, Least Connections inclut dans son nombre de connexions toutes les requêtes UDP pour lesquelles NGINX Plus attend toujours une réponse du serveur en amont. Tant que les valeurs de proxy_responses
et proxy_timeout
ne sont pas respectées, NGINX Plus continue de compter les connexions pour les serveurs en amont qui ont peut-être déjà terminé leur travail.
Lorsque vous avez un grand nombre de clients et un protocole qui effectue beaucoup de « dialogue » (plusieurs messages échangés entre le client et le serveur, comme dans le flux de défi-réponse RADIUS), l'utilisation d'un hachage IP source permet à ce dialogue d'avoir lieu avec un seul serveur principal. En d’autres termes, il établit la persistance de session , ce qui signifie que NGINX Plus dirige toutes les demandes d’un client donné vers le même serveur. L'exemple suivant configure l'algorithme d'équilibrage de charge Hash pour une paire de serveurs d'authentification RADIUS, avec l'adresse IP source (client) (capturée par la variable $remote_addr
) comme clé.
radius_servers en amont { hachage $remote_addr; # hachage IP source
serveur 192.168.136.201:1812;
serveur 192.168.136.202:1812;
}
Pour plus d'informations sur l'équilibrage de charge UDP et TCP, consultez les ressources suivantes :
en amont
Pour en savoir plus sur les autres fonctionnalités intéressantes de NGINX Plus R9, consultez l'annonce de NGINX Plus R9 sur notre blog et regardez notre webinaire à la demande, Quoi de neuf dans NGINX Plus R9 .
Pour essayer NGINX Plus, démarrez votre essai gratuit de 30 jours dès aujourd'hui ou contactez-nous pour discuter de vos cas d'utilisation.
« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."