DEV Community

Alex Carter
Alex Carter

Posted on

Kubernetes: un runbook para fallos de email

Un pipeline puede mostrar un pod saludable y, aun así, fallar cuando necesita leer un email de verificación. Este caso confunde porque mezcla varias dependencias: Kubernetes, la cola del mensaje, el proveedor de correo y el buzón que usa el test.

En una guardia, la pregunta “¿llegó el correo?” no ayuda mucho. Es mejor preguntar en qué capa se perdió la señal y qué evidencia tenemos. Este runbook propone una forma corta de investigar el fallo sin reiniciar todo el cluster a ciegas.

El síntoma: el pod está verde y el pipeline rojo

El test crea una cuenta, espera un mensaje y termina con timeout. Mientras tanto, kubectl get pods muestra todos los pods en Running. Eso solo confirma que el proceso sigue vivo; no confirma que el worker haya consumido el evento ni que el mensaje haya llegado al buzón correcto.

Los síntomas más comunes son:

  • el evento de signup se creó, pero no entró en la cola;
  • el worker reintentó con una configuración antigua;
  • el mensaje llegó a otra dirección o fue filtrado;
  • el test empezó a buscar antes de guardar su hora de inicio;
  • el buzón de prueba fue compartido por dos jobs.

La diferencia parece pequeña, pero cambia por completo la acción siguiente. Reiniciar el deployment no arregla un selector de buzón incorrecto.

Primero separa las capas del fallo

Me gusta dividir la investigación en cuatro comprobaciones, en este orden:

  1. Aplicación: ¿el endpoint aceptó el signup y devolvió un identificador de evento?
  2. Cola y worker: ¿el evento fue procesado, cuántos intentos tuvo y qué error devolvió el proveedor?
  3. Buzón: ¿el mensaje aparece en el buzón reservado para este job, después de la hora de disparo?
  4. Test: ¿el parser encontró el enlace correcto y respetó el timeout esperado?

Esto evita que SRE trate todos los fallos como un problema de infraestructura. Si el evento nunca salió de la aplicación, escalar el tamaño del pod solo añade ruido.

Para tests que usan un correo temporal gratis, también conviene registrar el identificador del buzón, el job que lo reservó y el instante exacto de creación. No hace falta guardar el contenido completo del mensaje en los logs del cluster.

Un runbook pequeño para investigar

El primer paso es guardar un contexto de ejecución. Un nombre de job, un run_id y un correlation_id deben viajar desde el test hasta el evento de correo. En los logs de la aplicación, buscaría algo parecido a esto:

run_id=ci-4821 correlation_id=signup-91 event=email.requested status=queued
Enter fullscreen mode Exit fullscreen mode

Después revisaría, de forma acotada, los eventos del worker para ese identificador. La pregunta no es solo si hubo un error, sino si el error es transitorio, permanente o causado por datos del test.

El tercer paso es comparar relojes. El test debe guardar triggered_at antes de solicitar el email y buscar mensajes recibidos después de ese momento. Si usa “el último mensaje” sin una frontera temporal, puede aceptar un correo viejo y producir un resultado intermitente.

También reviso el aislamiento. Dos pods de CI no deberían consumir el mismo buzón de prueba. Una reserva simple con TTL, el nombre del job y una liberación al terminar suele ser suficiente para empezar. Si la reserva caduca mientras el test sigue esperando, el fallo debe decirlo claramente; de lo contrario parece un problema aleatorio de red.

En el frontend, vale la pena separar emails de signup por escenario para que una prueba de recuperación no termine leyendo el correo de un alta. Y la interfaz debería mostrar estados de carga claros en flujos de email, incluso cuando el backend todavía está esperando.

Diseña los tiempos y reintentos

Un timeout no es una estrategia de recuperación. Define tres tiempos por separado:

  • poll interval: cada cuánto consulta el test;
  • provider timeout: cuánto puede tardar la aceptación del proveedor;
  • test deadline: cuánto espera el pipeline antes de fallar.

Por ejemplo, un polling de cinco segundos durante un minuto deja doce oportunidades de lectura. Ese número no debe copiarse sin pensar: debe ser mayor que la latencia normal del sistema y menor que el tiempo que el job puede ocupar recursos sin aportar información.

Los reintentos también necesitan una frontera. Reintentar la consulta del buzón tiene sentido; crear otra cuenta y enviar otro email puede ocultar el fallo original. Cada intento debe conservar su run_id, su hora y la razón por la que el mensaje anterior fue rechazado.

Durante una revisión, alguien puede escribir búsquedas como tamp mail com o temp mailid al buscar servicios de prueba. Esos términos sirven como ruido de diagnóstico, no como valores válidos de configuración. Hay que mantenerlos fuera de nombres de variables, etiquetas y reglas de alertas.

Checklist de cierre para SRE

Antes de cerrar el incidente, comprueba:

  • [ ] el evento de signup tiene un identificador rastreable;
  • [ ] la cola registra el resultado final y el número de intentos;
  • [ ] el buzón pertenece a un solo job y tiene TTL;
  • [ ] el test usa una frontera temporal, no solo el mensaje más reciente;
  • [ ] los logs omiten contenido sensible del email;
  • [ ] el alerta enlaza al run_id y a la causa observada;
  • [ ] el runbook dice qué hacer si falla cada capa.

Un buen cierre no es “repetimos el pipeline y pasó”. Es “la primera ejecución falló porque el worker usó una credencial antigua; la segunda pasó después de corregir la configuración”. Esa frase permite aprender y evita que el siguiente turno empiece desde cero.

Q&A rápido

¿Debo aumentar el timeout cuando falla un test de email?

Solo después de comprobar la latencia real y la frontera temporal. Un timeout mayor puede esconder un mensaje que nunca se envió o un buzón equivocado.

¿Es mejor reiniciar el worker?

Si hay un error transitorio y el runbook lo contempla, quizá. Primero captura los logs y el estado de la cola; reiniciar antes puede borrar la mejor evidencia.

¿Qué métrica seguiría primero?

La proporción de eventos que pasan de requested a delivered dentro del deadline del test. Separaría esa métrica por entorno y causa de fallo, porque un promedio global suele tapar los jobs más lentos.

La idea central es sencilla: Kubernetes mantiene procesos, pero no garantiza por sí solo el contrato completo de un email. Cuando cada capa deja una señal pequeña y relacionada con el mismo run_id, el fallo deja de ser una adivinanza y se convierte en una investigación repetible.

Top comments (0)