¡Hola!
Me llamo Sergey, soy ingeniero de infraestructura en el equipo de API de tinkoff.ru.
En este artículo, hablaré sobre los problemas que ha enfrentado nuestro equipo al preparar equilibradores basados en para varios proyectos. También discutiré una herramienta que nos permitió superar la mayor parte de ellos.
Nginx es un servidor proxy multifuncional y en constante desarrollo. Se caracteriza por tener una gran cantidad de módulos, . Cada proyecto impone ciertos requisitos sobre la funcionalidad del equilibrador y la versión de Nginx (por ejemplo, la disponibilidad de http/2 y el proxy de grpc), así como sobre la composición de sus módulos.
Queremos ver una versión actualizada con el conjunto de módulos necesarios, funcionando en una distribución específica de Linux. En nuestro caso, son sistemas basados en deb y rpm. La opción de contenedores no se considera en este artículo.
Deseamos poder modificar rápidamente la funcionalidad de nuestros equilibradores. Y aquí surge la pregunta: ¿cómo lograrlo utilizando la menor cantidad de recursos posible? Sería incluso mejor establecer un proceso que nos permita definir un número fijo de parámetros de entrada y, como resultado, obtener un artefacto en forma de paquete deb/rpm para el sistema operativo requerido.
En resumen, se pueden formular una serie de problemas:
- No siempre hay paquetes con la versión más reciente de Nginx.
- No hay paquetes con los módulos necesarios.
- Compilar y construir un paquete manualmente lleva mucho tiempo y es simplemente tedioso.
- No hay documentación sobre cómo se ha compilado cada instancia de Nginx.
Para resolver estos problemas, se sugiere algún tipo de herramienta que reciba una especificación en un formato legible para humanos y genere un paquete de Nginx con la funcionalidad deseada.
Al no encontrar una opción adecuada en GitHub, decidimos crear nuestra propia herramienta — .
Especificaciones
En nuestra herramienta, queríamos crear una descripción de la especificación en forma de código, que luego pudiera ser alojada en un repositorio de Git. Para esto, elegimos un formato habitual para este tipo de cosas: yaml. Ejemplo de especificación:
nginx_version: 1.14.1
output_package: deb
modules:
- module:
name: nginx-auth-ldap
git_url: https://github.com/kvspb/nginx-auth-ldap.git
git_branch: master
dependencies:
- libldap2-dev
- module:
name: ngx_http_substitutions_filter_module
git_url: https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git
- module:
name: headers-more-nginx-module
web_url: https://github.com/openresty/headers-more-nginx-module/archive/v0.261.zip
- module:
name: nginx-module-vts
git_url: https://github.com/vozlt/nginx-module-vts.git
git_tag: v0.1.18
- module:
name: ngx_devel_kit
git_url: https://github.com/simplresty/ngx_devel_kit.git
git_tag: v0.3.0
- module:
name: ngx_cache_purge
git_url: https://github.com/FRiCKLE/ngx_cache_purge.git
- module:
name: ngx_http_dyups_module
git_url: https://github.com/yzprofile/ngx_http_dyups_module.git
- module:
name: nginx-brotli
git_url: https://github.com/eustas/ngx_brotli.git
git_tag: v0.1.2
- module:
name: nginx_upstream_check_module
git_url: https://github.com/yaoweibin/nginx_upstream_check_module.git
- module:
name: njs
git_url: https://github.com/nginx/njs.git
git_tag: 0.2.5
config_folder_path: nginx
Aquí indicamos que queremos ver un paquete deb con la versión de Nginx 1.14.2 y el conjunto de módulos necesarios. La sección de módulos es opcional. Para cada uno de ellos se puede especificar:
- Nombre.
- Dirección desde donde se puede obtener:
- Repositorio Git. También se puede especificar una rama o etiqueta.
- Enlace web al archivo comprimido.
- Enlace local al archivo comprimido.
Algunos módulos requieren la instalación de dependencias adicionales, por ejemplo, para nginx-auth-ldap se necesita tener instalado libldap2-dev. Las dependencias necesarias también se pueden especificar en la descripción del módulo.
Entorno
En nuestra herramienta se puede obtener rápidamente un entorno con utilidades instaladas para la compilación, creación del paquete y otro software auxiliar. Aquí es ideal un contenedor Docker con todo lo necesario (en el repositorio ya hay un par de ejemplos de archivos Docker para ubuntu y centos).
Después de que se elabora la especificación y se prepara el entorno, iniciamos nuestro compilador, instalando previamente sus dependencias:
pip3 install -r requirements.txt
./main.py build -f [config_file].yaml -r [revision_number]
El número de revisión aquí es opcional y se utiliza para la versionado de las compilaciones. Se graba en la metainformación del paquete, lo que facilita su actualización en los servidores.
Se puede observar lo que sucede a través de los registros. Aquí hay un ejemplo de los momentos clave:
builder - INFO - Analizando archivo yaml: example.config.yaml
builder - INFO - Descargando scripts para construir paquete deb
builder - INFO - Descargando src de nginx...
builder - INFO - --> http://nginx.org/download/nginx-1.14.1.tar.gz
builder - INFO - Descargando módulos de terceros...
builder - INFO - El módulo nginx-auth-ldap se descargará por rama
builder - INFO - -- Hecho: nginx-auth-ldap
builder - INFO - -- Hecho: ngx_http_substitutions_filter_module
builder - INFO - El módulo headers-more-nginx-module se descargará
builder - INFO - El módulo nginx-module-vts se descargará por etiqueta
builder - INFO - -- Hecho: nginx-module-vts
builder - INFO - El módulo ngx_devel_kit se descargará por etiqueta
builder - INFO - -- Hecho: ngx_devel_kit
builder - INFO - -- Hecho: ngx_cache_purge
builder - INFO - -- Hecho: ngx_http_dyups_module
builder - INFO - Descargando dependencias
builder - INFO - Construyendo paquete .deb
builder - INFO - Ejecutando 'dh_make'...
builder - INFO - Ejecutando 'dpkg-buildpackage'...
dpkg-deb: construyendo el paquete 'nginx' en '../nginx_1.14.1-1_amd64.deb'.
Así, con solo un par de comandos, creamos el entorno y la construcción necesaria de Nginx, y el paquete aparece en el directorio desde donde se ejecuta el script.
Integración
También podemos integrar nuestra herramienta en procesos de CI/CD. Cualquier sistema de CI existente hoy en día puede ayudar con esto, por ejemplo o .
Como resultado, cada vez que se cambia la especificación en el repositorio de Git, se inicia automáticamente la construcción del artefacto. El número de revisión se vincula al contador de ejecuciones del build.
Gastando un poco más de tiempo, se puede configurar el envío del artefacto a un repositorio de paquetes local, Nexus, Artifactory, etc.
Además, el archivo de configuración yaml se puede conectar en Ansible u otro sistema de configuración automática, y tomar de allí el número de versión y tipo de paquete que queremos desplegar.
¿Qué sigue?
El proyecto aún no está terminado. Esto es en lo que estamos trabajando actualmente:
- Ampliamos la capacidad de configuración, pero al mismo tiempo la mantenemos lo más simple posible. No queremos definir mil parámetros si solo necesitamos dos, y el resto es adecuado por defecto. Esto incluye las flags de compilación (ahora se pueden cambiar en el archivo de configuración interno src/config.py), las rutas de instalación y el usuario para ejecutar.
- Añadiendo opciones para el envío automático del paquete a diferentes almacenes de artefactos.
- Ejecutando un comando personalizado al cargar el módulo (por ejemplo, para usar es necesario aplicar primero un parche de una versión específica)
- Añadiendo la realización de pruebas:
- El paquete se instala correctamente.
- Nginx tiene la versión correcta y se compila con las flags y módulos requeridos.
- Se crean las rutas necesarias, cuentas y demás.
Pero ya puede utilizar esta herramienta y también proponer mejoras — ¡Bienvenido!
Fuente: habr.com
