DEV Community

Alex Carter
Alex Carter

Posted on

Kubernetes: cuándo dejar de reintentar un email

Un email de CI que no llega parece un problema pequeño, hasta que el pipeline empieza a reintentarlo durante media hora. Entonces aparecen duplicados, alertas repetidas y una bandeja que ya no permite distinguir la ejecución actual de una anterior. En Kubernetes, el job puede estar sano desde el punto de vista del contenedor, mientras que la notificación sigue fallando de forma silenciosa.

La solución no es quitar todos los reintentos. Es decidir de antemano cuántos tienen sentido, qué evidencia se guarda y en qué momento el fallo deja de ser transitorio. Ese contrato hace que el runbook sea más predecible para la persona de guardia, incluso cuando el problema ocurre de madrugada.

El síntoma: un email que reintenta para siempre

Un patrón común es poner el envío dentro del mismo Job que ejecuta las pruebas y dejar que el cliente SMTP o HTTP reintente por su cuenta. Si además el Job tiene una política de reintento de Kubernetes, el número real de intentos se vuelve difícil de calcular.

El resultado suele verse así:

  • el test termina, pero el email devuelve un timeout;
  • el proceso reinicia y envía el mismo mensaje otra vez;
  • el destinatario recibe cuatro avisos para una sola ejecución;
  • el equipo no sabe si investigar el test, el proveedor o la configuración del secreto.

No conviene llamar a todo esto un flake. Un timeout breve puede ser transitorio, pero una respuesta 401, un destinatario inválido o un cuerpo sin el run_id son fallos de contrato. Repetirlos consume tiempo sin añadir información nueva.

Separar fallos transitorios de fallos de contrato

Antes de configurar backoff, clasifico las respuestas en tres grupos.

Transitorio: conexión rechazada momentáneamente, respuesta 429 o un error 5xx del proveedor. Se puede reintentar con espera creciente y un límite pequeño.

Configuración: secreto ausente, credencial caducada o endpoint equivocado. El retry no arregla esto; el paso debe terminar y dejar una alerta accionable.

Contrato del mensaje: falta el identificador de ejecución, el asunto no contiene el servicio o el enlace apunta al entorno incorrecto. Conviene guardar el mensaje para inspección, pero no enviarlo otra vez.

En sistemas con agentes y herramientas, esta separación también importa: un contrato de tools que resisten fallos define qué error puede repetir el consumidor y cuál debe subir de nivel. El envío de notificaciones necesita la misma claridad.

Un presupuesto de reintentos por ejecución

Para un email de CI prefiero un presupuesto explícito: tres intentos como máximo, con esperas de 5, 20 y 60 segundos. No es una cifra universal, pero obliga a hablar de la latencia aceptable y evita el retry: true sin límite.

El contrato puede expresarse con unos campos simples:

notification:
  run_id: "build-8472"
  max_attempts: 3
  backoff_seconds: [5, 20, 60]
  stop_on_status: [400, 401, 403, 422]
  dedupe_key: "build-8472:email:ci-finished"
Enter fullscreen mode Exit fullscreen mode

El dedupe_key es importante. Si el pod muere después de entregar el mensaje pero antes de guardar la respuesta, el siguiente intento debe poder reconocer la misma operación. De lo contrario, cada reinicio puede generar otro correo.

Para las pruebas, uso un buzón aislado por ejecución. Si hace falta preparar un fixture rápido, un recurso como temp mail so puede servir para separar la bandeja de esta corrida de la de otros tests. En un smoke test muy corto también he visto equipos buscar create temp mail; lo importante es que el buzón tenga un ciclo de vida claro y no se reutilice entre ramas.

La misma regla aplica a búsquedas imperfectas que aparecen en tickets: fake e mail com y temp gamil com pueden quedar como texto de referencia en una nota de diagnóstico, pero nunca deben convertirse en una política de validación. Son entradas humanas, no nombres de proveedores confiables.

Qué guardar antes de escalar al on-call

Cuando se agota el presupuesto, el evento debe ser útil sin obligar a abrir cinco sistemas. Guardo como mínimo:

  1. run_id, namespace y nombre del Job.
  2. Número de intento y motivo de la última respuesta.
  3. Host del endpoint, sin exponer secretos ni tokens.
  4. Hash o asunto normalizado del mensaje.
  5. Momento de inicio, última respuesta y próximo paso del runbook.

Si el equipo rota credenciales con frecuencia, merece la pena revisar también cómo validar correos de Alertmanager tras rotar secretos en Kubernetes. El caso es distinto, pero la lección es igual: un envío correcto no demuestra que el flujo de operación sea observable.

La alerta final debería decir “notificación no entregada tras 3 intentos” y no solo “pod failed”. Ese detalle reduce bastante el tiempo de triage. Aveces la causa está en el proveedor y otras veces en una variable mal escrita; la evidencia inicial debe permitir separar ambas cosas.

Checklist para el runbook de Kubernetes

Antes de cerrar el cambio, reviso:

  • ¿Existe un límite único de reintentos entre el cliente y el Job?
  • ¿Se diferencian 429, 5xx y errores de configuración?
  • ¿Cada mensaje tiene run_id y una clave de deduplicación?
  • ¿El buzón de prueba pertenece solo a la ejecución actual?
  • ¿Se conserva el resultado sin guardar credenciales?
  • ¿La alerta final incluye el siguiente paso para on-call?

También compruebo que un fallo del email no convierta automáticamente una prueba de aplicación exitosa en un falso fallo de despliegue. Depende del tipo de pipeline: en producción, una alerta crítica quizá debe bloquear; en una preview, puede bastar con registrar la incidencia y continuar.

Preguntas frecuentes

¿Tres intentos siempre es lo correcto?

No. Es un punto de partida. Un proveedor con límites estrictos puede necesitar menos intentos, mientras que una red interna muy inestable puede necesitar más. La decisión debe salir del SLO de la notificación, no de una cifra copiada.

¿Debo reintentar un 401?

Normalmente no. Primero revisa el secreto, su fecha de rotación y el endpoint. Repetir una credencial inválida solo añade ruido.

¿El email debe bloquear el pipeline?

Solo si la notificación forma parte del requisito de seguridad o auditoría. Para mensajes informativos, prefiero fallar de forma visible, conservar la evidencia y no ocultar el resultado real de las pruebas.

Un presupuesto pequeño, una clave de deduplicación y una alerta con contexto convierten un email frágil en una parte manejable del sistema. El objetivo no es que nunca falle; es que, cuando falle, el equipo sepa cuándo insistir y cuándo dejar de reintentar.

Top comments (0)