Saltar a contenido

upstream-jdomain: Módulo de resolución de nombres de dominio asíncrono para NGINX upstream

Instalación

Puedes instalar este módulo en cualquier distribución basada en RHEL, incluyendo, pero no limitado a:

  • RedHat Enterprise Linux 7, 8, 9 y 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 y Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-upstream-jdomain
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-upstream-jdomain

Habilita el módulo añadiendo lo siguiente en la parte superior de /etc/nginx/nginx.conf:

load_module modules/ngx_http_upstream_jdomain_module.so;

Este documento describe nginx-module-upstream-jdomain v1.5.2 lanzado el 09 de diciembre de 2024.


Un módulo de resolución de nombres de dominio asíncrono para nginx upstream.

Este módulo te permite usar un nombre de dominio en un bloque upstream y esperar que el nombre de dominio se resuelva dinámicamente para que tu upstream pueda ser resistente a las actualizaciones de entradas DNS.

El módulo no realiza la resolución DNS automáticamente en algún intervalo. En su lugar, la resolución DNS debe ser provocada por una solicitud para el upstream dado. Si nginx sirve una conexión destinada a un upstream jdomain, y ha transcurrido el interval configurado, entonces el módulo realizará una búsqueda DNS.

El módulo es compatible con otras directivas de ámbito upstream. Esto significa que puedes poblar un bloque upstream con múltiples directivas jdomain, múltiples directivas server, keepalive, directivas de balanceo de carga, etc. Ten en cuenta que a menos que se especifique otro método de balanceo de carga en el bloque upstream, este módulo utiliza el algoritmo de balanceo de carga round robin por defecto integrado en el núcleo de nginx.

Nota Importante: Si se especifica un algoritmo de balanceo de carga alternativo, debe venir antes de la directiva jdomain en el bloque upstream! Si esto no se sigue, nginx se caerá durante el tiempo de ejecución! Esto se debe a que muchos otros módulos de balanceo de carga extienden explícitamente el round robin incorporado, y por lo tanto terminan sobrescribiendo los controladores de inicialización de jdomain, ya que jdomain es técnicamente un módulo de balanceo de carga también. Aunque esto puede no ser el caso con todos los módulos de balanceo de carga, es mejor mantenerse en el lado seguro y colocar jdomain después.

Nota Importante: Debido a la naturaleza no bloqueante de este módulo y al hecho de que su resolución DNS se activa por solicitudes entrantes, la solicitud que provoca una búsqueda se reenviará efectivamente al upstream que fue resuelto y almacenado en caché antes de que ocurra la búsqueda DNS. Dependiendo del escenario, esto podría resultar en un fallo ocasional al cambiar los estados de los upstreams. Esto es importante tenerlo en cuenta para asegurar transiciones suaves de tus upstreams.

Este repositorio es un fork de un repositorio originalmente creado por wdaike. Como ese proyecto ya no se mantiene, este repositorio tiene como objetivo ser su sucesor y ahora cuenta con varias características adicionales.

Uso

resolver 8.8.8.8; # Tu servidor DNS local

## Upstream básico usando el nombre de dominio con el puerto 80 por defecto.
upstream backend_01 {
    jdomain example.com;
}

## Upstream básico especificando un puerto diferente.
upstream backend_02 {
    jdomain example.com port=8080;
}

## Upstream con un servidor de respaldo para usar en caso de que no se encuentre el host o errores de formato en la resolución DNS.
upstream backend_03 {
    server 127.0.0.2 backup;
    jdomain example.com;
}

## Upstream que usará el respaldo para cualquier y todos los errores de resolución DNS.
upstream backend_04 {
    server 127.0.0.2 backup;
    jdomain example.com strict;
}

server {
    listen 127.0.0.2:80;
    return 502 'Un error.';
}

Sinopsis

Sintaxis: jdomain <nombre-de-dominio> [port=80] [max_ips=4] [interval=1] [strict]
Contexto: upstream
Atributos:
    port:       Puerto de escucha del backend.                                      (Por defecto: 80)
    max_ips:    Tamaño del búfer de IP. Número máximo de IPs resueltas para almacenar en caché.       (Por defecto: 4)
    interval:   Cuántos segundos para resolver el nombre de dominio.                       (Por defecto: 1)
    ipver:      Solo se utilizarán direcciones de la familia IPv4 o IPv6 si se define  (Por defecto: 0)
    strict:     Requiere que la resolución DNS tenga éxito y devuelva direcciones,
                de lo contrario marca el servidor subyacente y los pares como inactivos y
                obliga a usar otros servidores en el bloque upstream si hay alguno presente. Una resolución fallida puede ser un tiempo de espera, fallo del servidor DNS, rechazos de conexión, respuesta sin
                direcciones, etc.

Consulta https://www.nginx.com/resources/wiki/modules/domain_resolve/ para más detalles.

Desarrollo

Requisitos previos

Para facilitar el desarrollo local y permitirte construir y probar el módulo, necesitarás algunas herramientas.

  • Docker: para proporcionar un entorno que reproduzca fácilmente las condiciones ideales para construir y probar.
  • act: para simular la ejecución de flujos de trabajo de acciones de github localmente y evitar que tengas que enviar commits solo para ver fallar el CI.
  • rust: dependencia de cargo-make.
  • cargo-make: para ejecutar tareas comunes de desarrollo como construir, probar y formatear código.

Ejecutador de Tareas

cargo-make es un ejecutor de tareas avanzado que te permitirá realizar fácilmente operaciones comunes de desarrollo como formatear el código, construir el módulo, ejecutar la suite de pruebas y realizar análisis de código. Puedes ver las definiciones de tareas en el archivo Makefile.toml. Instalar cargo-make resultará en un ejecutable independiente llamado makers así como una extensión de cargo que se puede ejecutar a través de cargo make. Dado que este proyecto no es un crate de rust, se recomienda simplemente usar makers.

También ten en cuenta que, por simplicidad, el ejecutor de tareas utiliza docker para ejecutar todas las tareas. Esto significa que el binario de construcción no está dirigido a tu plataforma host.

Tarea por Defecto

Para agregar valor, la tarea por defecto (es decir, simplemente ejecutar makers solo) comenzará una sesión interactiva de bash dentro del contenedor docker utilizado para este proyecto.

Esto debería ayudar con la depuración y el flujo de trabajo general.

Formateo

El código mal formateado hará que el trabajo de linting de acciones de github falle. Para evitar esto, puedes ejecutar la tarea de formateo antes de enviar nuevos cambios, así:

makers format

Este formateo se realiza mediante una herramienta llamada clang-format. Puedes encontrar las opciones de configuración para esto definidas en el archivo ./.clang-format.

Análisis de Código Estático

Puedes ejecutar un análisis estático del código a través de la tarea de análisis:

makers analyse

Este análisis se realiza mediante una herramienta llamada clang-tidy. Puedes encontrar las opciones de configuración para esto definidas en el archivo ./.clang-tidy.

Pruebas

Puedes ejecutar la suite de pruebas utilizando la tarea de prueba, así:

makers test

Depuración

Podemos usar valgrind y gdb en nginx desde dentro del contenedor.

Primero abre una shell interactiva en el contenedor con:

$ makers

Usaremos esa sesión para ejecutar valgrind:

$ valgrind --vgdb=full --vgdb-error=0 /github/workspace/bin/static/nginx -p/github/workspace/t/servroot -cconf/nginx.conf
==15== Memcheck, un detector de errores de memoria
==15== Copyright (C) 2002-2017, y GPL de GNU, por Julian Seward et al.
==15== Usando Valgrind-3.13.0 y LibVEX; vuelve a ejecutar con -h para información de copyright
==15== Comando: /github/workspace/bin/static/nginx -p/github/workspace/t/servroot -cconf/nginx.conf
==15==
==15== (acción al inicio) vgdb me ...
==15==
==15== PARA DEPURAR ESTE PROCESO USANDO GDB: inicia GDB así
==15==   /path/to/gdb /github/workspace/bin/static/nginx
==15== y luego dale a GDB el siguiente comando
==15==   target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=15
==15== --pid es opcional si solo un proceso de valgrind está en ejecución
==15==

A continuación, encuentra el identificador del contenedor para que podamos abrir otra sesión dentro de él:

$ docker ps
CONTAINER ID        IMAGE                                     COMMAND             CREATED             STATUS              PORTS                    NAMES
55fab1e069ba        act-github-actions-nginx-module-toolbox   "bash"              hace 4 segundos     En ejecución hace 3 segundos        0.0.0.0:1984->1984/tcp   serene_newton

Usa el nombre o ID para ejecutar una sesión bash dentro del contenedor:

$ docker exec -it serene_newton bash

Usaremos esta sesión para iniciar gdb y dirigirnos al servidor gdb de valgrind que iniciamos en la otra sesión:

$ gdb /github/workspace/bin/static/nginx
GNU gdb (GDB) Red Hat Enterprise Linux 8.0.1-30.amzn2.0.3
Copyright (C) 2017 Free Software Foundation, Inc.
Licencia GPLv3+: GNU GPL versión 3 o posterior <http://gnu.org/licenses/gpl.html>
Este es software libre: eres libre de cambiar y redistribuirlo.
NO HAY GARANTÍA, en la medida permitida por la ley. Escribe "show copying"
y "show warranty" para más detalles.
Este GDB fue configurado como "x86_64-redhat-linux-gnu".
Escribe "show configuration" para detalles de configuración.
Para instrucciones de reporte de errores, por favor consulta:
<http://www.gnu.org/software/gdb/bugs/>.
Encuentra el manual de GDB y otros recursos de documentación en línea en:
<http://www.gnu.org/software/gdb/documentation/>.
Para ayuda, escribe "help".
Escribe "apropos word" para buscar comandos relacionados con "word"...
Leyendo símbolos de /github/workspace/bin/static/nginx...hecho.
(gdb)

Desde el prompt de gdb, dirígete al proceso de valgrind y comienza a depurar:

(gdb) target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=15
Depuración remota usando | /usr/lib64/valgrind/../../bin/vgdb --pid=15
transmitiendo datos entre gdb y el proceso 15
advertencia: el objetivo remoto no admite la transferencia de archivos, intentando acceder a archivos desde el sistema de archivos local.
Leyendo símbolos de /lib64/ld-linux-x86-64.so.2...(no se encontraron símbolos de depuración)...hecho.
0x0000000004000ef0 in _start () from /lib64/ld-linux-x86-64.so.2
Faltan debuginfos separados, usa: debuginfo-install glibc-2.26-35.amzn2.x86_64
(gdb)

Ejecutando GitHub Actions

Con act, puedes simular el flujo de trabajo que se ejecutará en los servidores de GitHub una vez que envíes cambios.

Hay más de un trabajo en el flujo de trabajo principal, así que necesitas especificar el trabajo de prueba cuando ejecutes act. Por ejemplo, puedes usar este comando para ejecutar la validación del formato del código:

act -vj lint

Ten en cuenta que el trabajo lint no formatea tu código, solo verifica que el formateo sea el esperado.

También ten en cuenta que -v se usa para habilitar el modo detallado y dar más visibilidad sobre todo lo que act está haciendo.

Los trabajos que puedes (y debes) ejecutar localmente son lint, build, analyse y test. El trabajo test depende de la salida del trabajo build. Para mantener la salida del trabajo de construcción, puedes agregar la bandera -b a act, o simplemente puedes usar el ejecutor de tareas para construir.

Problemas Conocidos

¿En este momento? ¡Ninguno! 🎉

Si descubres un error o tienes una pregunta que plantear, por favor abre un issue.

Autor Original

wdaike wdaike@163.com (https://github.com/wdaike), Baidu Inc.

GitHub

Puedes encontrar consejos de configuración adicionales y documentación para este módulo en el repositorio de GitHub para nginx-module-upstream-jdomain.