Baba-yaga con Ubuntu 24.04

per Victor Carceler darrera modificació 2024-06-01T11:06:55+02:00

https://upload.wikimedia.org/wikipedia/commons/2/29/The_russian_fairy_book_-_plate_facing_p034.jpgCualquiera que transitando por un remoto bosque se encuentre con una casita de madera que descansa sobre unas patas de ave sabrá que se encuentra en el mundo de los cuentos y que tiene delante la morada de Baba-yaga, alguien que habita entre dos mundos y que provocará un giro en el devenir de los acontecimientos.

Baba-yaga es mágica y peligrosa pero no es completamente perversa. Después de leer los cuentos tradicionales recopilados por Afanásiev o Baba Yagá puso un huevo de Dubravka Ugrešić se le puede tener cariño.

En la infraestructura del instituto Baba-yaga es el nombre de la máquina que administra el parque informático utilizando Ansible.

La anterior instancia ha estado funcionando de manera incansable pero el inexorable paso del tiempo se ha hecho notar y, aprovechando la publicación de Ubuntu 24.04 LTS, se ha decidido reimplementar esta máquina para que siga haciendo su magia durante los próximos años.

Aprovecho para contar aquí algunos de los servicios que proporciona Baba-yaga :-)

Troika: Vasilisa, Sirin y Baba-yaga

El principal encargo de Baba-yaga en nuestro centro consiste en utilizar Ansible para administrar el parque informático compuesto por más de un millar de ordenadores. Todos esos ordenadores son equipos para el usuario final (ordenadores de aula y portátiles) que el usuario enciende y apaga cuando considera oportuno.

Esto hace que no sea viable lanzar los playbooks de Ansible a cierta hora porque tal vez los equipos no estén encendidos. Se debe lanzar Ansible con cierta frecuencia y cuando los ordenadores estén encendidos (aunque no todos se encienden a la vez).

Para conseguir nuestro objetivo de lanzar periódicamente playbooks que mantengan los equipos, cuando estos estén encendidos, sin realizar excesivas ejecuciones de los playbooks y agrupando a los equipos de un mismo tipo en un solo playbook colaboran tres elementos: Vasilisa, Sirin y Baba-yaga.

Vasilisa

La cadena comienza con la ejecución de Vasilisa un script que se ejecuta en el arranque de cada equipo.

Vasilisa realiza varias para mantener en buen estado los equipos. Por ejemplo, en el momento de escribir estas líneas realiza las siguientes tareas:

  • Si el equipo tiene menos de 50GiB libres en disco borra el directorio de descargas y la papelera.
  • Si hay algún contenedor LXD encendido lo detiene.
  • En Ubuntu lanza unattended-upgrade.
  • En Fedora aplica actualizaciones con dnf update -y.
  • Actualiza las aplicaciones flatpak.
  • Utiliza glpi-agent para actualizar el inventario de la máquina en GLPI.
  • Prepara algunas métricas para Prometheus con información de los equipos.
  • Realiza una petición a Sirin.

La petición a Sirin sirve para notificar que el equipo está encendido y anuncia playbook que define su estado.

Por ejemplo, los ordenadores del aula Ada realizan una petición a la URL: http://192.168.17.18:8080/register/dpt-inf-u2404.yml.

Sirin

Sirin es un pequeño servicio web que registra las solicitudes de los ordenadores que se encienden y las clasifica como solicitudes pendientes (Baba-yaga deberá lanzar el playbook para ese equipo) o ya atendidas.

Como se ha visto en el apartado anterior, cuando Sirin recibe una petición como http://192.168.17.18:8080/register/dpt-inf-u2404.ymlse podrá registrar:

  1. La IP del equipo que ha hecho la petición. La IP 192.168.17.18 y el puerto 8080 es uno de los puntos en los que Sirin atiende a los clientes.
  2. El playbook solicitado por el equipo, en este caso dpt-inf-u2404.yml.

Si Sirin no tenía ninguna petición para el cliente entonces registrará la petición como pendiente. También registrará la petición como pendiente si la última petición registrada (aunque ya fuera atendida) es de hace más de 23h (este timeout es un parámetro configurable). Pero si la última petición de ese equipo es reciente (todavía no ha transcurrido timeout desde que se registró) entonces se ignora.

De esta manera Sirin guardará en su memoria la lista de equipos que se han encendido y que Ansible debe repasar porque como mínimo hace cierta cantidad de tiempo (timeout) desde que se ejecutó su playbook por última vez.

Pero Sirin no sólo puede registrar equipos con el playbook que necesitan (/register/{playbook}). También puede contestar con el número de ordenadores que están pendientes de que se ejecute cierto playbook (/getnumberofrequests/{playbook}) y con la lista de las direcciones de esos ordenadores (/gethosts/{secret}/{playbook}). Esta última petición, que necesita tener el parámetro {secret} correcto, marca las peticiones como atendidas.

En la anterior instancia de Baba-yaga Sirin estaba implentando en Python utilizando Django. El servicio ha estado funcionando bien pero para instalarlo en Ubuntu 24.04 sería necesario actualizar la aplicación Django para ponerla al día. Como esta tarea no me ha parecido lo más estimulante del mundo he decidido reimplementar Sirin en un lenguaje que proporcione un binario para evitar este problema en el futuro.

Y así es como llegamos a la actual versión de Sirin implementada en Go: https://github.com/vcarceler/sirin-go.

Baba-yaga

Finalmente Baba-yaga consultará cada 5 minutos a Sirin el número de ordenadores pendientes de repasar cada uno de los playbooks.

Si el número de ordenadores no es 0 entonces solicitará (/gethosts/{secret}/{playbook}) las direcciones de esos equipos y lanzará ansible-playbook con el parámetro --limit para limitar la ejecución del playbook a los equipos que ha retornado Sirin.

Los playbooks de Ansible utilizados en el centro son públicos y se encuentran en https://github.com/vcarceler/playbooks-elpuig.

Hay un playbook diferente para cada conjunto de ordenadores y se utilizan roles para permitir la reutilización de las tareas. Los únicos datos que no están subidos al repositorio de GitHub son la declaración de los usuarios (con sus claves) y las claves para la vpn implementada con wireguard que permite gestionar los portátiles aunque estén fuera del centro.

Otras tareas de Baba-yaga

La función principal de Baba-yaga es lanzar los playbooks de Ansible de manera periódica pero también realiza otras funciones auxiliares que son muy importantes.

ARA Records Ansible

Como se ha explicado la mayoría de los playbooks que lanza Baba-yaga se lanzan de manera automática. ARA Records Ansible permite registrar la ejecución de cada playbook (tareas, tiempos, errores, estados, ...) en una base de datos y consultar toda la información a través de la web.

Desde el centro se puede consultar la interfaz de ARA Records Ansible accediendo a http://192.168.0.18:10000 (o http://10.0.0.2:10000 desde nuestra vpn).

Captura de ARA en baba-yaga-2404

Prometheus snmp_exporter

El protocolo SNMP permite monitorizar equipos como switches, puntos de acceso, impresoras, etc. En el caso de los equipos de red resulta conveniente recoger métricas que se guardarán en Prometheus y que nos permitirán visualizar la información en Grafana.

Pues snmp_exporter es el servicio de red que puede obtener información mediante SNMP de diferentes equipos y publicar esa información en forma de métricas para Prometheus.

Captura de dashboard de Grafana mostrando métricas de los switches (SNMP).

Inventario de los equipos de red con SNMP

La herramienta netinventory de glpi-agent puede utilizar el protocolo SNMP para expresar en XML el inventario de un equipo.

Por ejemplo el comando:

glpi-agent.netinventory --host 192.168.0.50 --community public

Utiliza SNMP para obtener los datos del switch que tiene por IP 192.168.0.50.

Estos datos pueden enviarse a GLPi con el comando glpi-agent.injector pero también se pueden procesar para obtener información útil.

Por ejemplo, este es el fichero de datos completo del switch 192.168.0.50 que expresa propiedades generales del equipo y detalles de cada puerto:

  • MAC de dispositivos conectados.
  • Información del equipo remoto obtenida con LLDP.
  • Contadores de tráfico.
  • VLANs.
  • Velocidad.

Baba-yaga actualiza de manera periódica el inventario de GLPi y publica estos datos (en una dirección interna http://10.0.0.2/) para que se pueda consultar en tiempo real qué dispositivos están conectados a cada puerto.

Un pequeño script en python procesa estos ficheros para extraer la MAC de cada dispositivo que conoce el switch (porque está en ese puerto o porque el puerto enlaza con otro switch). Toda esta información se registra en journal y se exporta a loki.

may 14 18:31:22 baba-yaga-2404 cat[5287]: switchaddress=192.168.0.53 ifname="Slot0/23" ifnumber=23 mac="52:54:00:5b:aa:db"
may 14 18:31:22 baba-yaga-2404 cat[5287]: switchaddress=192.168.0.53 ifname="Slot0/23" ifnumber=23 mac="52:54:00:14:c2:05"
may 14 18:31:22 baba-yaga-2404 cat[5287]: switchaddress=192.168.0.53 ifname="Slot0/23" ifnumber=23 mac="52:54:00:ee:09:4b"
may 14 18:31:22 baba-yaga-2404 cat[5287]: switchaddress=192.168.0.53 ifname="Slot0/23" ifnumber=23 mac="52:54:00:69:50:9f"
may 14 18:31:22 baba-yaga-2404 cat[5287]: switchaddress=192.168.0.53 ifname="Slot0/23" ifnumber=23 mac="52:54:00:92:81:43"

De esta manera es posible consultar en loki qué dispositivo ha estado conectado a cada puerto en cada momento.

Log remoto

En los equipos de red es posible configurar un log remoto (puerto udp 514).

Para que Baba-yaga pueda recibir el log de los equipos de red se ha decidido instalar syslog-ng y utilizar la siguiente configuración /etc/syslog-ng/conf.d/50-udp.conf

# Recibimos logs UDP en el puerto 514
#
source s_udp {
udp(port(514));
};

destination d_file {
file("/var/log/udp_logs.log");
};

log {
source(s_udp);
destination(d_file);
};

En el fichero /var/log/udp_logs.log quedarán registrados los mensajes que envíen los equipos de red.

May 28 15:02:11 192.168.15.50 25 link up, 1Gbps FULL duplex
May 28 16:06:05 192.168.0.58 %LINK-W-Down: 2:15
May 28 16:06:08 192.168.0.58 %LINK-I-Up: 2:15
May 28 16:06:38 192.168.0.58 %STP-W-PORTSTATUS: 2:15: STP status Forwarding
May 28 14:13:16 192.168.20.50 14 link down

Finalmente promtail enviará estos datos a loki.