
Sesenta contenedores en un servidor
Un servidor bare-metal ejecuta decenas a cientos de contenedores Hoody. KSM y dedup BTRFS hacen que el costo marginal sea casi cero.
Tu CI matricial se reparte entre treinta runners de test. Cada uno necesita la misma imagen de 800 MB. Transmite el tarball a una sola ruta de pipe con ?n=30. Los treinta workers hacen curl a la misma URL. Los bytes salen una vez, el servidor no guarda nada y no se rotan credenciales de registry.
# transmite la imagen una veztar c ./image.tar | curl -T - https://pipe.hoody.com/build-12af?n=30UN EMISOR A LA IZQUIERDA. TREINTA RECEPTORES GET A LA DERECHA. EL PIPE ESPERA HASTA QUE TODOS ESTÉN ESCUCHANDO, ENTONCES LOS BYTES PASAN UNA VEZ.
El pipe es un router de fan-out sin disco. El POST del emisor a /api/v1/pipe/[path]?n=30 se bloquea hasta que treinta receptores se conectan a la misma URL con el mismo n. Entonces los bytes fluyen del contenedor de build directo a cada runner, simultáneamente, a la velocidad del receptor más lento.
tar c | curl -T - https://pipe/.../build?n=30El contenedor de build canaliza el tarball directo a curl. Sin archivo escrito, sin push a registry.
POST /api/v1/pipe/[path]?n=30El servidor retiene al emisor hasta que los treinta receptores se conectan. Un n distinto devuelve 400. Los receptores pre-conectados están bien.
curl https://pipe/.../build?n=30 | tar xCada runner recibe bytes idénticos. El backpressure fluye desde el receptor más lento, no desde el ancho de banda del emisor.
Nada persiste. Nada se cachea. El pipe corredora la conexión, luego se aparta. Cuando el runner más lento termina, la transferencia termina — y la URL desaparece.
Ingenuo: treinta pulls de registry del mismo tarball de 800 MB, treinta cachés frías, treinta idas y vueltas de red. Pipe: un egress, una transferencia, el receptor más lento marca el ritmo.
12 s
Un egress a velocidad de línea. El receptor más lento marca el ritmo, pero nadie re-descarga.
1× / build
Los bytes salen del builder una vez, fan-out en el pipe. Sin tarifas de S3 GET, sin pulls de Docker Hub.
0 bytes
El pipe no guarda nada en disco. Sin registry que limpiar, sin clave de caché que invalidar.
El tiempo total asume una matriz de 30 vías en la misma red regional que el contenedor de build; las transferencias entre regiones dependen del ancho de banda inter-regional, no del pipe.
Una vez que la build es una URL y treinta curls, una pila de andamiaje de CI desaparece. Sin almacenamiento de artefactos que envejecer. Sin credenciales de registry que rotar. Sin cache action que depurar.
El backpressure está integrado en el pipe. Los workers rápidos no malgastan una ida y vuelta de registry esperando al lento — esperan en el pipe, luego beben al mismo ritmo. Nadie re-descarga.
Nada se sube a un registry, así que nada tiene que autenticarse contra uno. La URL misma es la credencial — efímera, limitada a una transferencia, expulsada cuando la build termina.
Los bytes salen del builder una vez. El pipe difunde. Pagas un egress por build en lugar de treinta pulls de registry por ejecución de matriz.
El pipe es por build, no por clave. No hay caché de GitHub Actions con el que fallar, ni misterio de capa de buildx, ni tarball viejo del main de la semana pasada.
El mismo patrón maneja node_modules, .pnpm-store, target/, la caché de wheels, el shard del dataset. Si se transmite, se reparte en abanico.
Un emisor. Treinta receptores. Cero facturas de S3.
Un push de 30 vías que tomaba noventa segundos y un golpe a S3 toma doce segundos y un solo egress. Nadie re-descarga. No se rotan credenciales de registry. La URL se expulsa sola cuando la matriz termina.
Las piezas que un flujo de CI matricial normalmente tiene que ensamblar — registry, cache action, mirror, paso de subida a medida. El pipe las pliega en una URL.
Deja de empujar el mismo tarball treinta veces. Empújalo una vez. Que treinta curls compartan el stream.