baker

Misma semilla.
Mismo bug.

Baker ejecuta tu sistema distribuido completo dentro de un solo kernel Rinux, le corta la red, le congela nodos, le desfasa los relojes y le corta la energía a los discos. Cuando algo se rompe, te entrega la semilla que reproduce la ejecución exacta, todas las veces.

El bug que en producción aparece una vez cada diez mil ejecuciones y termina como "no reproducible" se vuelve un número que puedes pegar en un ticket.

En construcción sobre Rinux. Primeros sistemas bajo prueba: Titan y OxideStore. Qué existe hoy.

titan-1
-
titan-2
-
titan-3
-

        
traza --

Simulación de juguete en tu navegador: tres nodos que se reparten un canal con un arriendo de 15 s, como lo hace Titan. Ejecuta la misma semilla dos veces y la traza da el mismo hash. Busca una semilla que falle y aparece el bug clásico: un nodo congelado que despierta creyéndose dueño.

Los peores bugs no se repiten.

Dependen del orden exacto de los eventos: un ACK que llega tarde, un nodo que se cae justo mientras escribe, dos procesos que creen tener el mismo arriendo. Los tests normales corren siempre por el camino feliz. Producción no.

Baker cambia la pregunta "¿falla?" por "¿con qué semilla falla y con qué probabilidad?".

400 ejecuciones del mismo testuna sola falla
Sin determinismo, la ejecución roja se pierde: la vuelves a correr y pasa. Con Baker, la semilla 0x2f9a la reproduce instrucción por instrucción.

Todo el sistema cabe en un nodo Rinux.

Cada nodo de tu sistema corre como un dominio del mismo kernel Rinux, con imágenes OCI sin modificar. El kernel ya es dueño de lo que en Linux es azar: el reloj, la aleatoriedad, el planificador, la red entre dominios y el disco. En modo determinista, todo eso sale de una semilla.

nodo rinux-baker 1 vCPU modo deterministaejemplo: Titan ESB en tres nodos
bakercontrolador: genera la carga, decide las fallas, verifica
semilla 0x2f9aplan de fallascarga HL7 sintéticaverificador de propiedadestraza con hash encadenado
Kernel Rinux (Rust)personalidad Linux, dominios aislados
reloj lógicoentropía sembradaplanificador determinista red interna: partición, pérdida, latenciarfs: cortes de energíaRDTSC atrapadopausa de dominio
dominiosuna carga por dominio, imágenes OCI sin cambios
titan-1Elixir / BEAM Mnesia
titan-2Elixir / BEAM Mnesia
titan-3Elixir / BEAM Mnesia
postgresestado de los canales
his-simemisor HL7 sintético
pacs-simreceptor MLLP, responde AA, AE o nada
Mnesia y los arriendos viajan por la red interna del kernel: Baker decide qué paquete llega, cuándo y si llega.
La pieza de abajo ya existe: en mentat-1 (GCE) tres nodos de OxideStore corren hoy como dominios de un solo Rinux, con Raft entre ellos por la IP del nodo. Baker agrega la capa determinista y el controlador.

Una corrida es una semilla: de ella salen la carga, el momento de cada falla y todo valor "aleatorio" que vea el sistema. Baker corre miles de semillas en paralelo y, al final de cada una, el verificador compara lo enviado con lo recibido. Lo que se pierde, se duplica o queda colgado aparece con su número.

Rebobinar, bifurcar, contar.

Encontrar la semilla es la mitad. Baker vuelve a un punto anterior a la falla y desde ahí abre cien ramas con entropía nueva. Así se sabe si el bug es raro o casi seguro, y si el arreglo realmente lo cierra.

Los puntos de control los toma la máquina virtual de abajo (KVM o Firecracker): como el determinismo vive en Rinux, restaurar y resembrar basta.

semilla 0x2f9arebobinar a t = 41 s y bifurcar
t=0 t=41 s t=63 s falla rebobinar rama 1 ok rama 2 falla rama 3 ok rama 4 falla 37 de 100 ramas fallan desde t = 41 s
Cifras ilustrativas. Con el arreglo aplicado, se reproducen las mismas cien ramas: si alguna sigue fallando, el arreglo no cierra el bug.

Por qué Rinux y no un hipervisor.

La forma conocida de hacer esto es un hipervisor determinista: atrapar cada instrucción no determinista del Linux invitado e inyectar cada interrupción en el punto exacto. Funciona, pero exige hardware Intel dedicado y años de trabajo en el hipervisor. Rinux toma otro camino: el kernel que corre tu sistema es el mismo que decide el tiempo, el orden y la red.

Hipervisor determinista

tu sistemacontenedores Linux
Linux invitadodecide el orden, pero no controla su reloj ni sus interrupciones
hipervisor con determinismoatrapa RDTSC, RDRAND y CPUID; cuenta saltos para inyectar interrupciones
Intel bare metalVT-x, EPT, PMU; sin nube común, sin ARM

Baker sobre Rinux

tu sistemalos mismos contenedores, como dominios
Rinux con determinismosu planificador, su reloj, su aleatoriedad, su red y su disco: todo sale de la semilla
KVM, Firecracker, GCE, Apple Siliconsolo para puntos de control; x86_64 y aarch64
Baker empezó como un parche al hipervisor bhyve de FreeBSD. Sigue siendo el camino para probar Linux real; Rinux es el camino rápido para todo lo que ya corre sobre Rinux.
Fuentes de no determinismo y quién las controla
FuenteEn un hipervisorEn Rinux
Orden entre procesosinyectar interrupciones contando saltosel planificador es del kernel
TiempoTSC virtual, timers virtualesreloj lógico en syscalls y vDSO; RDTSC atrapado
Aleatoriedadatrapar RDRAND y RDSEEDgetrandom, /dev/urandom y ASLR sembrados
Red entre nodosdispositivos virtuales deterministaspila del kernel: partición, pérdida y latencia por regla
Discodispositivo virtual deterministarfs, con pruebas de corte en cada escritura

El precio: se prueba sobre Rinux, no sobre el kernel Linux. Para el stack propio, que va a producción sobre Rinux, es una ventaja. Para un sistema que depende de detalles del TCP o el ext4 de Linux, Baker sobre bhyve sigue siendo la opción.

Una orden de examen no se puede duplicar.

Un motor de integración saca mensajes HL7 de una tabla, los envía por MLLP a un PACS o a un laboratorio y marca el estado según el ACK. Cada flecha de este flujo es un lugar donde un corte en el momento justo pierde o duplica una orden.

flujo de salida HL7cuatro puntos de falla que Baker inyecta
tabla de salidaestado 0, 2, 1 o 9 motor de integraciónTitan o Mirth PACS / labreceptor MLLP lee ORM / ADT ACK AA marca 1 o 9 1 2 3 4 1 ACK perdido: la fila queda en 2 y nadie avisa. 2 ACK correcto, la base falla al marcar. 3 Reinicio entre marcar 2 y enviar. 4 Destino lento: reintento y orden duplicada.
Propiedades que verifica Baker al terminar cada semilla: toda fila llega a un estado final o queda en 2 con alerta; un estado 1 implica que el destino tiene el mensaje; ningún control ID (MSH-10) llega dos veces. Solo mensajes sintéticos: nunca datos de pacientes.
Titan contra Mirth
El mismo arnés HL7 contra los dos motores, con las mismas semillas. Una comparación bajo fallas, no bajo carga feliz.
Arriendos de Titan
Titan promete un canal en un solo nodo y nada duplicado. Baker congela al dueño más de 15 s y mira si dos nodos procesan a la vez. Es lo que muestra el simulador de arriba.
Gateways de datos
Un procedimiento que hace commit justo después del timeout y un reintento que lo ejecuta dos veces. Un caché que mezcla tenants.

Para qué sistemas sirve.

Baker vale la pena cuando hay varios procesos o nodos, se guarda estado y un error cuesta caro.

Tipo de sistemaLo que Baker busca
Bases de datos y almacenamientoescrituras confirmadas que desaparecen tras un corte, réplicas que divergen
Consenso (Raft, Paxos)dos líderes a la vez, un cambio de membresía con un nodo caído
Colas, buses, HL7mensajes perdidos o entregados dos veces
Pagos y ledgerscarreras que descuadran un saldo
Orquestadores y workflowsjobs que corren dos veces o nunca cuando cambia el coordinador
Sincronización sin conexiónconflictos que se resuelven distinto según el orden de llegada

No es para una web CRUD sobre una base de datos, un frontend o un script. Ahí los bugs son de lógica y los encuentran los tests de siempre.

Qué existe y qué no.

Baker se construye a la vista. Esta tabla dice qué corre hoy y qué está en diseño.

PiezaEstadoDetalle
Varios nodos como dominios de un Rinuxcorre hoyOxideStore en tres dominios con Raft entre ellos, en GCE (mentat-1)
Fallas de disco en Rinuxcorre hoyrfs con pruebas de corte de energía en cada escritura de una secuencia de commits
Arnés: carga, fallas, verificadoren construcciónprimero contra Titan y Mirth sobre Linux, sin determinismo
Modo determinista de Rinuxdiseño1 vCPU, reloj lógico, entropía sembrada, red interna con fallas
Rebobinar y bifurcardiseñopuntos de control de la VM de abajo, resembrado por rama
Baker sobre bhyve (Linux real)F0código de línea base listo, pendiente de host Intel bare metal

El resto del stack.

Rinux

Kernel en Rust que ejecuta userspace Linux sin modificar dentro de dominios. La base de Baker.

Mentat

Plataforma privada de cargas. Sus nodos corren sobre Rinux.

Hull

Formato e imágenes firmadas de cada carga.

Titan

ESB en Elixir con HL7. Primer sistema bajo prueba.

OxideStore

Almacenamiento compatible con S3 sobre Raft. Segundo sistema bajo prueba.