Cómo un límite de conexiones a la base de datos casi reinicia los Mac de mis clientes
Gestionamos una pequeña flota de Mac mini para clientes. Un daemon en un hub consulta cada máquina por SSH, envía telemetría a un plano de control y escala cuando una máquina se queda callada. Primero espera. Después apaga y enciende la máquina con un enchufe inteligente. Después pide ayuda a una persona.
La semana pasada, el plano de control empezó a devolver errores 500. Trece minutos después, el daemon había concluido que los cuatro Mac estaban muertos y había registrado un ciclo de apagado y encendido para cada uno. Dos eran de clientes de pago. Un tercero se había vendido esa misma mañana.
Qué falló de verdad
Un pool de conexiones a la base de datos. El plano de control corre en funciones serverless contra un pooler de Postgres con un límite de quince conexiones para todo el proyecto. Unas pocas funciones en caliente las ocuparon todas, y todas las rutas de la API que usan la base de datos empezaron a fallar. Los detalles están en otro artículo.
Los Mac estaban bien. SSH funcionaba. Todas las sesiones gráficas estaban activas. El cliente que compilaba en uno de ellos no notó nada. Lo único roto era el sistema cuyo trabajo era saber si los Mac estaban rotos.
Cómo una flota sana pareció muerta
El daemon guardaba una marca de tiempo por máquina: la última vez que una consulta tuvo éxito. La lógica de escalado la comparaba con la hora actual. La consulta, con bastante lógica, empezaba pidiendo la lista de máquinas al plano de control, y terminaba antes de tiempo si esa petición fallaba.
Así que durante la caída no se ejecutó ninguna consulta, ninguna marca de tiempo avanzó y todos los huecos crecieron a la vez. La lógica de escalado no sabía que el daemon ni lo había intentado. Vio trece minutos de silencio de cuatro máquinas e hizo aquello para lo que estaba hecha.
ladder: Unit 02 unreachable 12m51s → power cycle ladder: Unit 03 unreachable 12m51s → power cycle ladder: Unit 04 unreachable 12m51s → power cycle ladder: Unit 05 unreachable 12m43s → power cycle
Por qué no se reinició nada
No había ningún enchufe inteligente configurado. El paso de cortar la corriente buscó un enchufe, no encontró ninguno y siguió adelante. Después, las cuatro máquinas mostraban tiempos de actividad de seis días, seis días, un día y una hora más o menos. Nadie las había tocado.
Eso es suerte, no diseño. Los enchufes inteligentes están previstos para el próximo lote de máquinas. Si ya hubieran estado instalados, un problema de conexiones a la base de datos habría cortado la corriente a tres Mac de clientes. Uno de ellos quizá estaba en mitad de una build. Ninguno había hecho nada mal.
La solución
El daemon registra ahora la última vez que consiguió obtener la lista de unidades e intentar de verdad llegar a las máquinas. La lógica de escalado se niega a actuar si eso no ha pasado hace poco, y registra el motivo: el fallo está en el plano de control, no en las unidades.
ladder: skipped, no successful unit poll in 14m02s (control plane, not the units)
Esa línea dice exactamente qué se niega a hacer y por qué. Es lo que la versión antigua debería haber dicho la primera vez.
La regla de fondo es sencilla. Una remediación debe exigir pruebas de que la comprobación se ejecutó. "Intentamos llegar y fallamos" es una prueba. "No sabemos nada de ella" no lo es, porque también es lo que se ve cuando cae quien escucha.
Qué probar en tu propia automatización
Habíamos probado qué pasa cuando muere un Mac. Nunca habíamos probado qué pasa cuando muere lo que vigila a los Mac. No son la misma prueba, y la segunda es la que acaba llevando la mano al interruptor.
Preguntas
- ¿Deberían ser automáticas acciones de recuperación como cortar la corriente?
- Sí, pero solo con pruebas positivas de que el propio objetivo ha fallado. Una acción que se dispara por falta de información se disparará en cualquier caída del sistema que recoge esa información.
- ¿Cómo se prueba esto sin romper producción?
- Tira el observador, no los nodos. Impide que el daemon llegue a su plano de control y mira qué decide la remediación. Si escala, está razonando a partir del silencio.
- ¿Cuál es el umbral correcto para considerar algo inalcanzable?
- Más largo que cualquier corte esperable del plano de control. Y solo debería empezar a contar tras un intento fallido de llegar al nodo, nunca desde la última vez que se vio el nodo por casualidad.
Haz tus propias cuentas con la calculadora o alquila un runner.