BLOG | NGINX

Equilibrio de carga del tráfico DNS con NGINX y NGINX Plus

NGINX - Parte de F5 - horizontal, negro, tipo RGB
Miniatura de Liam Crilly
Liam Crilly
Publicado el 14 de abril de 2016

NGINX Plus R9 presenta la capacidad de revertir el proxy y equilibrar la carga del tráfico UDP, una mejora significativa de las capacidades de equilibrio de carga de capa 4 de NGINX Plus.

Esta publicación de blog analiza los desafíos de ejecutar un servidor DNS en una infraestructura de aplicaciones moderna para ilustrar cómo tanto NGINX Open Source como NGINX Plus pueden equilibrar la carga de manera eficaz y eficiente tanto el tráfico UDP como el TCP. (Las comprobaciones de estado de la aplicação [activa] son ​​exclusivas de NGINX Plus, pero por lo demás la información de este blog se aplica igualmente a NGINX Open Source; para abreviar, nos referiremos a NGINX Plus en el resto de la publicación).

[Editor: para obtener una descripción general de todas las nuevas características de NGINX Plus R9, consulte Anuncio de NGINX Plus R9 en nuestro blog].

¿Por qué equilibrar la carga del tráfico UDP?

A diferencia de TCP, UDP por diseño no garantiza la entrega de datos de extremo a extremo. Es similar a enviar un mensaje mediante una paloma mensajera: sabes con certeza que el mensaje fue enviado, pero no puedes estar seguro de que haya llegado. Este enfoque “sin conexión” tiene varias ventajas, la más notable es una latencia menor que TCP, tanto porque los mensajes individuales más pequeños de UDP utilizan menos ancho de banda como porque no hay un proceso de protocolo de enlace para establecer una conexión. UDP deja el problema de detectar tiempos de espera y otros problemas a nivel de red al desarrollador de aplicaciones. ¿Pero qué significa esto para el DNS?

Al igual que varios otros protocolos basados en UDP, DNS utiliza un flujo de datos de solicitud-respuesta. Por ejemplo, un cliente DNS solicita la dirección IP correspondiente a un nombre de host y recibe una respuesta. Si no llega una respuesta dentro de un período de tiempo determinado, el cliente DNS envía la misma solicitud a un servidor DNS de “respaldo”. Sin embargo, tener que esperar el período de tiempo de espera antes de volver a intentar una solicitud puede convertir lo que normalmente es un proceso extremadamente rápido (medido en milisegundos) en uno muy lento (medido en segundos).

El efecto de una falla de DNS se puede reducir mediante el equilibrio de carga de DNS
Los clientes reintentan búsquedas DNS fallidas con un servidor de respaldo después de un tiempo de espera.

El uso de NGINX Plus para hacer proxy y equilibrar la carga del tráfico DNS reduce la cantidad de ocasiones en las que el cliente experimenta un tiempo de espera. Con múltiples servidores DNS detrás del balanceador de carga NGINX Plus, los clientes solo experimentan un tiempo de espera cuando hay una partición de red entre el cliente y NGINX Plus. El cliente no experimenta ningún problema con los servidores DNS cuando NGINX Plus utiliza controles de estado de la aplicação . Al monitorear la disponibilidad y el tiempo de respuesta de cada servidor, NGINX Plus evita enviar solicitudes de clientes a un servidor en mal estado.

DNS no es sólo un protocolo UDP

Aunque la gran mayoría del tráfico DNS se realiza a través de UDP, existen operaciones DNS comunes que utilizan TCP. El DNS utiliza UDP para mensajes pequeños (hasta 512 bytes), pero TCP para operaciones que requieren (o es probable que requieran) mensajes más grandes. Históricamente, TCP se utilizaba con DNS sólo para transferencias de zona desde un servidor de nombres primario autorizado a sus servidores de nombres secundarios. Sin embargo, con el cambio hacia contenedores e infraestructura inmutable, el DNS se utiliza cada vez más como el principal mecanismo de descubrimiento de servicios, mediante el uso de registros SRV .

Los registros SRV de DNS se introdujeron originalmente para los teléfonos de voz sobre IP (VoIP) que utilizan SIP para descubrir sus servidores, pero se pueden utilizar para cualquier tipo de servicio. Sin embargo, los registros SRV incluyen mucha más información que la mayoría de los otros tipos de registros DNS. Como resultado, solo unos 10 registros SRV caben en la respuesta UDP estándar de 512 bytes, a diferencia de unos 30 registros A. Cuando una respuesta DNS excede el límite de 512 bytes, se devuelven los primeros 512 bytes pero la respuesta se marca como “truncada”. En este punto, un cliente DNS puede manejar la respuesta truncada lo mejor que pueda o volver a intentar la misma solicitud mediante TCP.

Esto significa que al equilibrar la carga de servidores DNS en una infraestructura de red moderna, NGINX Plus puede esperar recibir una combinación de tráfico UDP y TCP.

DNS en un entorno de microservicios

La siguiente ilustración muestra una vista simplificada de un entorno de microservicios con dos balanceadores de carga. El balanceador de carga del frontend redirige las solicitudes de los clientes públicos de la aplicação, seleccionando la mejor instancia de microservicio y realizando muchas otras funciones que no analizaremos aquí. Nos concentraremos en el balanceador de carga DNS, que se encuentra entre el entorno de microservicios y los servidores DNS que brindan información de descubrimiento de servicios a los microservicios.

La capacidad de equilibrio de carga UDP en NGINX y NGINX Plus los hace ideales para el equilibrio de carga de DNS en un entorno de microservicios y con alta disponibilidad y escala.
NGINX Plus equilibra la carga de los servidores DNS en un entorno de microservicios.

Configuración del equilibrio de carga DNS básico

NGINX Plus implementa el equilibrio de carga de capa 4 en el módulo Stream , por lo que el equilibrio de carga UDP y TCP se configura en el bloque de flujo como se muestra en el siguiente fragmento.

Advertencia: No puede simplemente agregar este fragmento de configuración como un nuevo archivo en el directorio /etc/nginx/conf.d . Se produce un error de validación (“la directiva stream no está permitida aquí”), porque el archivo de configuración nginx.conf predeterminado de NGINX Plus incluye el contenido de los archivos en el directorio conf.d en el bloque http . La solución más sencilla es incluir el bloque de transmisión completo directamente en nginx.conf .

stream { upstream servidores_dns {
servidor 192.168.136.130:53;
servidor 192.168.136.131:53;
}

servidor {
escucha 53 udp;
escucha 53; #tcp
contraseña_proxy servidores_dns;
registro_errores /var/log/nginx/dns.log info;
}
}

Primero definimos el grupo ascendente de servidores DNS. Las directivas del servidor especifican el número de puerto en el que nuestros servidores ascendentes están escuchando, 53 (el puerto conocido para DNS).

El bloque server{} define cómo NGINX Plus maneja el tráfico DNS entrante. Las dos directivas de escucha le indican a NGINX Plus que escuche en el puerto 53 el tráfico UDP y TCP. TCP es el protocolo de capa 4 predeterminado para el módulo Stream, por lo que no lo especificamos explícitamente como parámetro como lo hacemos para UDP.

La directiva proxy_pass le dice a NGINX Plus qué hacer con el tráfico que está escuchando. Aquí redirigimos dicho tráfico al grupo ascendente dns_servers . NGINX Plus utiliza automáticamente UDP al reenviar solicitudes UDP del cliente a servidores ascendentes (y TCP para solicitudes TCP del cliente), por lo que no necesitamos especificar explícitamente el protocolo de Capa 4 en el grupo ascendente.

No hay ninguna directiva access_log en el módulo Stream, porque NGINX Plus no inspecciona la carga útil de los segmentos TCP o los datagramas UDP (como lo hace con los paquetes HTTP). Sin embargo, podemos utilizar el parámetro info en la directiva error_log para registrar el procesamiento de la conexión y los eventos del proxy.

[Editor: El registro de acceso se habilitó en el módulo Stream después de la publicación de este blog, en NGINX Open Source 1.11.4 y NGINX Plus R11 .]

Ajuste para alta disponibilidad

Para mejorar la disponibilidad de nuestros servidores DNS, podemos agregar un par de directivas más y configurar controles de estado activos (de la aplicação).

Configuración del número de respuestas de proxy y la duración del tiempo de espera

La primera directiva adicional es proxy_responses , que indica cuántas respuestas espera NGINX Plus para cada solicitud UDP con proxy. En nuestro caso, después de recibir una sola respuesta, NGINX Plus deja inmediatamente de esperar más respuestas, lo que libera la memoria y el socket utilizados para esa sesión.

La segunda directiva adicional, proxy_timeout , determina cuánto tiempo NGINX Plus espera una respuesta del servidor (aquí estamos reduciendo el valor predeterminado de 10 minutos a 1 segundo). Si NGINX Plus no recibe respuesta dentro de este período, prueba con el siguiente servidor en el grupo ascendente y marca el servidor ascendente que no responde como no disponible durante un período definido (10 segundos de manera predeterminada) para que ningún otro cliente sufra una demora inducida por el tiempo de espera durante ese tiempo.

servidor { escuchar 53 udp; escuchar 53; #tcp proxy_pass dns_servers; registro_de_errores /var/log/nginx/dns.log info; respuestas_proxy 1 ; tiempo_de_espera_proxy 1s ; }

También podemos cambiar la cantidad de tiempo que un servidor está marcado como no disponible, incluyendo la opción fail_timeout en la directiva del servidor en el grupo ascendente. Con la siguiente configuración, NGINX Plus marca los servidores ascendentes fallidos como no disponibles durante 60 segundos:

servidores dns_de_subida { servidor 192.168.136.130:53 tiempo_de_espera_fallo=60s ; servidor 192.168.136.131:53 tiempo_de_espera_fallo=60s ; }

Esto nos permite controlar cuánto retraso experimenta un cliente si uno de nuestros servidores DNS falla. Sin embargo, si se intenta una solicitud TCP a un servidor DNS fallido, la verificación de errores inherente en TCP permite que NGINX Plus lo marque automáticamente como no disponible para evitar solicitudes posteriores de TCP o UDP a ese servidor.

Configuración de comprobaciones de salud activas

La función de verificación de estado activo en NGINX Plus es una herramienta adicional y extremadamente valiosa para la alta disponibilidad de cualquier servicio con equilibrio de carga, incluido DNS. En lugar de esperar a que falle una solicitud TCP real de un cliente DNS antes de marcar el servidor DNS como inactivo, hacemos que NGINX Plus intente periódicamente una conexión TCP en el puerto 53 para establecer si el servidor DNS está activo y funcionando correctamente, incluyendo la directiva health_check con su parámetro port=53 en el bloque server{} . (NGINX Plus envía de forma predeterminada comprobaciones de estado al puerto especificado por la directiva de escucha , 53 en nuestro caso. Entonces, aquí usamos el parámetro para configurar el valor predeterminado explícitamente, pero podríamos especificar un puerto diferente si también modificamos nuestros servidores DNS para responder al tráfico en él).

Con UDP, podemos ir un paso más allá y configurar una comprobación de estado activa que realiza una búsqueda DNS real de un registro conocido. Por ejemplo, podríamos colocar el siguiente registro CNAME en el archivo de zona para el mismo subdominio que se utiliza para el descubrimiento de servicios dentro del entorno de microservicios.

control de salud EN CNAME healthy.svcs.example.com.

Dada la naturaleza liviana de UDP, podemos observar el tráfico de la red y extraer fácilmente la cadena de bytes que representa una búsqueda de DNS. Luego creamos un bloque de configuración de coincidencia con esa cadena como parámetro para la directiva de envío . La directiva expect especifica la respuesta que debe devolver el servidor para considerarse saludable.

coincidencia dns_lookup {
enviar x00x01x00x00x00x01x00x00x00x00x00x00x06x68x65x61 ...;
esperar ~* "healthy.svcs.example.com.";
}

El beneficio de esta verificación de estado profunda a nivel de aplicação es que, incluso si su servidor de nombres está en funcionamiento, realizar una búsqueda DNS real para su dominio de producción descubre problemas de configuración y corrupción de datos que de otro modo podrían causar problemas más adelante.

El equipo de soporte de NGINX Plus puede ayudar a preparar comprobaciones de estado de UDP para búsquedas de DNS y otros protocolos.

El siguiente fragmento destaca las directivas adicionales necesarias para los controles de salud activos.

stream { upstream dns_servers { zona dns_mem 64k ; servidor 192.168.136.130:53 fail_timeout=60s; servidor 192.168.136.131:53 fail_timeout=60s; } match dns_lookup { enviar x00x01x00x00x00x01x00x00x00x00x00x00x06x68x65x61 ...; esperar ~* "healthy.svcs.example.com."; } servidor { escuchar 53 udp; escuchar 53; #tcp health_check match=dns_lookup intervalo=20 falla=2 pasa=2 udp; health_check intervalo=20 falla=1 pasa=2 puerto=53; #tcp proxy_pass dns_servers; registro_de_errores /var/log/nginx/dns.log depuración; respuestas_de_proxy 1; tiempo_de_espera_de_proxy 1 s; } }

La directiva de zona define una zona de memoria compartida llamada dns_mem , que hace que los resultados de las comprobaciones de estado (y otra información de estado) estén disponibles para todos los procesos de trabajo de NGINX Plus.

La directiva de coincidencia se analiza más arriba.

La directiva health_check tiene una serie de parámetros que puedes ajustar para tu entorno. Aquí definimos comprobaciones de estado independientes para UDP y TCP respectivamente. Debido a la diferencia entre UDP y TCP, requerimos dos fallas sucesivas de verificación de estado de UDP antes de marcar el servidor DNS como no saludable, pero solo una falla de TCP. Para ambos protocolos, necesitamos dos respuestas exitosas antes de marcar nuevamente un servidor como saludable, para evitar enviar solicitudes a un servidor inestable y “con fluctuaciones”.

Una ventaja de definir un único grupo ascendente de servidores DNS para el tráfico UDP y TCP es que una verificación de estado fallida para cualquiera de los protocolos marca al servidor como no saludable y lo elimina del grupo de equilibrio de carga.

Ajuste de escala

Si bien implementar solo dos servidores back-end puede ser una solución eficaz de alta disponibilidad, las capacidades de equilibrio de carga de NGINX Plus le permiten escalar servidores back-end horizontalmente sin el conocimiento del cliente.

Es poco probable que el entorno de microservicios de muestra descrito anteriormente requiera escalamiento de los servidores DNS backend. Sin embargo, un ISP que proporciona servicios de DNS a todos sus suscriptores experimenta una carga constante y el potencial de picos enormes, lo que crea la necesidad de una gran cantidad de servidores DNS y un proxy frontend para equilibrar la carga del tráfico entre ellos.

Todos los algoritmos de equilibrio de carga NGINX y NGINX Plus están disponibles para TCP y UDP, así como para HTTP:

  • Round Robin (predeterminado)
  • Hash genérico y su variante consistente (algoritmo ketama)
  • Hash de IP
  • Conexiones mínimas
  • Menos tiempo (solo NGINX Plus)

(También puede configurar pesos en todos los algoritmos para aumentar aún más su eficiencia. (Para obtener más información, consulte la sección sobre pesos en Cómo elegir una técnica de equilibrio de carga NGINX Plus en nuestro blog).

Mientras que las solicitudes HTTP pueden variar enormemente en términos de la carga y las demandas de procesamiento impuestas a los servidores back-end, las solicitudes DNS normalmente generan todas la misma carga. Por este motivo, es poco probable que los algoritmos de Menores Conexiones y Menor Tiempo proporcionen una ventaja sobre el método Round Robin. En particular, Least Connections incluye en su recuento de conexiones cualquier solicitud UDP para la cual NGINX Plus todavía está esperando una respuesta del servidor ascendente. Mientras no se cumplan los valores de proxy_responses y proxy_timeout , NGINX Plus seguirá contando las conexiones de los servidores ascendentes que ya hayan completado su trabajo.

Cuando tiene una gran cantidad de clientes y un protocolo que realiza mucho "diálogo" (múltiples mensajes intercambiados entre el cliente y el servidor, como en el flujo de desafío-respuesta RADIUS), entonces el uso de un hash de IP de origen permite que ese diálogo se realice con un solo servidor back-end. En otras palabras, establece la persistencia de la sesión , lo que significa que NGINX Plus dirige todas las solicitudes de un cliente determinado al mismo servidor. El siguiente ejemplo configura el algoritmo de equilibrio de carga Hash para un par de servidores de autenticación RADIUS, con la dirección IP de origen (cliente) (capturada por la variable $remote_addr ) como clave.

servidores de radio ascendentes { hash $dirección_remota; # Hash de la IP de origen
servidor 192.168.136.201:1812;
servidor 192.168.136.202:1812;
}

Más información

Para obtener más información sobre el equilibrio de carga UDP y TCP, consulte los siguientes recursos:

Para conocer otras excelentes características de NGINX Plus R9, consulte Anuncio de NGINX Plus R9 en nuestro blog y mire nuestro seminario web a pedido, Novedades de NGINX Plus R9 .

Para probar NGINX Plus, comience hoy su prueba gratuita de 30 días o contáctenos para analizar sus casos de uso.


"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.