Un rollback de Kubernetes suele devolver la aplicación a un estado conocido. Sin embargo, no siempre devuelve el contexto de las pruebas de email. Ahí aparece un incidente típico: el despliegue está sano, el mensaje llegó, pero el job de CI lee un correo creado por otra versión.
He visto este problema cuando un consumidor conserva la misma dirección mientras cambian los pods, los intentos y la release. El fallo parece aleatorio porque el correo correcto existe, pero llega después de que el test haya aceptado otro mensaje. Una cuenta de correo desechable necesita el mismo cuidado que cualquier recurso distribuido.
El incidente: el email pertenece a otro despliegue
Imagina una pipeline que crea un usuario y espera un enlace de verificación. La versión checkout-42 crea un buzón de prueba y empieza a esperar. El job se interrumpe durante una actualización. Kubernetes hace rollback a checkout-41, y un reintento vuelve a usar la dirección anterior.
Ahora hay dos problemas posibles:
- El mensaje de
checkout-42llega después del rollback. - El consumidor de
checkout-41busca el primer mensaje disponible, no el mensaje de su propia ejecución.
En los logs solo aparece “email no encontrado” o, peor, una prueba verde con un enlace equivocado. Mirar únicamente el estado de los pods no alcanza.
La primera pregunta durante el diagnóstico debe ser: “¿qué ejecución creó este mensaje?”. Investigar por orden de llegada vuelve el rollback mas ruidoso de lo necesario.
Por qué el rollback confunde la evidencia
Un pod es efímero, pero la evidencia de una prueba no debería depender de que ese pod siga vivo. Si el consumidor guarda el cursor del buzón solo en memoria, el nuevo pod puede volver a leer mensajes antiguos. Si el nombre de la dirección se basa solo en el entorno, dos intentos concurrentes parecen ser uno.
Una etiqueta como app=checkout identifica muchos pods a lo largo del tiempo; no identifica una ejecución. Para correlacionar un mensaje hacen falta al menos el run_id, el intento y un token generado para ese caso.
Conviene separar tres hechos en los registros:
- Provisión: qué fixture se creó y cuándo caduca.
- Entrega: qué identificador de mensaje recibió el proveedor.
- Consumo: qué versión, pod y ejecución aceptaron el mensaje.
No guardaría el cuerpo completo del correo por defecto. Una dirección redactada, el identificador y un hash del token bastan para reconstruir la secuencia sin copiar datos privados. La retención tambien debe tener dueño.
Un contrato de diagnóstico por ejecución
Antes de lanzar el test, genera un contrato pequeño y pásalo al job como configuración efímera:
{
"run_id": "ci-1842-attempt-2",
"release": "checkout-42",
"mailbox_id": "fixture-7f31",
"correlation_token": "signup-91ab",
"expires_at": "2026-10-08T01:00:00Z"
}
El lector debe rechazar un mensaje si no coincide el run_id, la release esperada o el token. No basta con comprobar el asunto: un asunto repetido es una coincidencia débil. Después de un rollback, el consumidor nuevo puede seguir usando la fixture si su contrato continúa vigente; si no, debe pedir una nueva y dejar la anterior en estado cleanup_pending.
Una transición explícita ayuda a razonar el incidente: planned, created, message_received, consumed, expired y cleanup_pending. El controlador debe ser idempotente para que el reintento no cree una segunda acción desconocida. El error mas común es marcar la fixture como limpia cuando solo terminó el pod.
Para entender el lado de la aplicación, puede servir revisar emails de reactivación con contexto. El principio es el mismo: el mensaje necesita contexto suficiente para que una persona pueda distinguirlo de otro flujo.
Qué debe sobrevivir al pod
El estado mínimo debe vivir fuera del contenedor: el contrato de ejecución, la relación entre run_id y mailbox_id, el último cursor consumido y los eventos de limpieza. Puede ser una tabla pequeña, un artefacto de CI con retención corta o un servicio interno. Lo importante es que el rollback de la aplicación no borre la historia del test.
Los logs del pod pueden incluir el run_id y una versión corta del token, pero no la dirección completa ni el contenido del correo. Para un fallo, conserva un recibo redactado con:
- timestamp de creación y recepción;
- versión de la aplicación y nombre del namespace;
- identificador del mensaje;
- motivo exacto del rechazo;
- resultado de la limpieza.
Si la prueba necesita una herramienta externa para generar un correo desechable temporal, la dependencia debe tener límites claros: expiración, acceso por ejecución y ninguna reutilización entre ramas. Documenta qué ocurre cuando el proveedor está lento. “Esperar más” no es una estrategia de recuperación.
El texto temp org mail puede aparecer en datos antiguos o en búsquedas internas, pero no debería convertirse en una etiqueta operativa. Mantener esa distinción evita que un término heredado termine enlazado a una decisión de seguridad.
Las pruebas limpias de email desde una API muestran otra perspectiva útil: aislar la creación de fixtures del resto de la aserción. En Kubernetes, esa separación hace mas facil decidir si falló el despliegue, la entrega o la limpieza.
Checklist para el siguiente rollback
- ¿Cada intento tiene un
run_idy un token distintos? - ¿El lector rechaza mensajes de otra release aunque el asunto coincida?
- ¿La relación entre ejecución, fixture y mensaje sobrevive al pod?
- ¿El rollback conserva o invalida explícitamente el contrato anterior?
- ¿Los logs distinguen provisión, entrega, consumo y limpieza?
- ¿Existe una ruta para
cleanup_pendingcuando el runner desaparece? - ¿La retención de recibos está definida y es suficientemente corta?
- ¿La prueba simula mensajes tardíos y dos reintentos concurrentes?
Preguntas rápidas
¿Debo crear un buzón nuevo después de cada rollback?
No siempre. Si el contrato sigue siendo válido y el consumidor conoce su cursor, puedes conservar la fixture. Si cambió el intento o el token, crear una nueva suele ser mas facil de diagnosticar.
¿Kubernetes puede resolver este problema por sí solo?
No. Kubernetes gestiona pods, servicios y despliegues; no sabe qué mensaje pertenece a una ejecución de negocio. La correlación debe estar en el contrato de la aplicación y en el almacenamiento de evidencia.
¿Qué significa una prueba realmente depurable?
Que un compañero puede contestar tres preguntas sin reproducir el fallo: qué versión creó el mensaje, por qué el consumidor lo aceptó o rechazó, y quién limpiará la fixture. Si solo tenemos “email no encontrado”, todavía falta observabilidad.
Un rollback devuelve código, no necesariamente contexto. Cuando cada email de prueba lleva identidad de ejecución, expiración y recibo verificable, el incidente deja de ser una carrera misteriosa entre pods y se convierte en una secuencia que un equipo SRE puede revisar.
Top comments (0)