Portaron Kubernetes al navegador
(ngrok.com)- webernetes es un proyecto que llevó parte de Kubernetes a TypeScript para ejecutar un clúster dentro del navegador; se creó en 2 meses con 552 commits, 629 archivos y casi 100.000 líneas
- No compila Kubernetes tal cual a WebAssembly, sino que reimplementa partes de kubelet, varios controladores, un CNI y un runtime de contenedores basados en el navegador, además de una API para manipular el clúster
- No descarga imágenes desde registros reales; las imágenes se definen con una API de TypeScript. El objetivo no es ser una distribución de producción, sino crear contenido interactivo sobre Kubernetes
- Aunque la mayor parte del código fue escrita por un LLM, cada línea fue revisada por una persona y se validó con 204 pruebas de integración que ejecutan las mismas pruebas que k3s, más 1.855 pruebas unitarias portadas desde la base de código Go de Kubernetes
- Durante el port, el LLM repetía errores como simplificar de más, crear helpers arbitrarios y omitir pruebas; para aprovechar la generación rápida de código hay que combinarla con revisión y pruebas
Qué ejecuta webernetes en el navegador
- webernetes es un proyecto que porta parcialmente Kubernetes a TypeScript para poder ejecutar un clúster en el navegador
- El clúster de demo funciona por completo dentro del navegador y realiza buena parte de las tareas que hace un clúster real de Kubernetes
-
Ciclo de vida de Pods
- DNS y networking del clúster
- Recolección de basura de contenedores
- Asignación de IP
- Seguimiento de
DeploymentyReplicaSet - Los puntos azules de la demo representan Pods enviándose solicitudes entre sí
-
Port parcial en lugar de compilar a WebAssembly
- No compilaron Kubernetes a WebAssembly
- Incluso un programa Go simple de
hello, world!compilado a WebAssembly pesa alrededor de 540 KiB con gzip; webernetes pesa cerca de 140 KiB con gzip - Compilar Kubernetes completo a WebAssembly probablemente requeriría transferir varios megabytes, y además produciría errores de compilación por llamadas a APIs de nivel sistema que no se pueden usar en el navegador
- webernetes está compuesto por estos elementos
- Un port parcial del binario kubelet de Kubernetes necesario para ejecutar Pods y probes
- Ports de varios controladores de Kubernetes, como el scheduler de Pods, el namespace controller, kube-proxy y el deployment controller
- Una interfaz de red de contenedores (CNI) basada en el navegador para la comunicación entre Pods
- Un runtime de contenedores basado en el navegador que permite que kubelet ejecute contenedores a través de la interfaz de runtime de contenedores (CRI)
- La API de clúster de webernetes para tareas como aplicar manifests y hacer watch de recursos
Definición de imágenes y uso de la API
- Para mantener el tamaño reducido, webernetes no descarga imágenes reales desde registros como Docker Hub
- En su lugar, tiene un registro basado en el navegador, y las imágenes se definen con una API de TypeScript
- La imagen de ejemplo
HelloWorldhereda dew8s.BaseImagey, dentro deexec, responde"Hello, world!"a solicitudes HTTP en el puerto 8080 - El flujo de uso del clúster es el siguiente
- Se crea un clúster con
new w8s.Cluster() - Se registra la imagen con
cluster.registerImage(HelloWorld) - Se aplica un manifest de
Deploymentdeapps/v1concluster.apply() - Se consulta la lista de Pods con
cluster.api.corev1.listNamespacedPod() - Se observan cambios de Pods con
cluster.informer("pods", ...) - Se observan eventos de solicitudes y respuestas entre Pods con
cluster.on("request")ycluster.on("response") - Se pueden enviar solicitudes HTTP a una IP de Pod a través de la red del clúster con
cluster.fetch()
- Se crea un clúster con
- Hay más ejemplos en webernetes repository examples
Usos y limitaciones actuales
- El objetivo de webernetes es crear contenido interactivo sobre Kubernetes
- No es una distribución de Kubernetes lista para producción, ni necesita ejecutar imágenes reales
- Al creador de contenido le basta con poder configurar una carga de trabajo específica para mostrar el concepto de Kubernetes que quiere explicar
- Entre las funciones que actualmente no soporta se incluyen
- ConfigMaps
- Secrets
- Pod resources
- persistent volumes
- Varias funciones de Kubernetes que todavía no han sido necesarias
- Planean implementar más funciones de Kubernetes a medida que hagan falta durante la creación de contenido
Por qué, aunque fue hecho con LLM, no lo dejaron solo
- Casi todo el código de webernetes fue escrito por un LLM
- Para la confiabilidad del proyecto hicieron dos cosas en paralelo
- Revisar personalmente cada línea de código
- Crear cientos de pruebas para comprobar que webernetes se comporta igual que un clúster real
- La revisión manual les dio confianza de que la mayor parte del código era idéntica línea por línea a la base de código Go de Kubernetes
- Las pruebas sirven para confirmar que esa similitud léxica se traduce en equivalencia de comportamiento real
- Los errores que queden tras la revisión son responsabilidad del autor del proyecto, quien pide abrir un issue si se encuentra un problema
Por qué el código portado necesitaba revisión
- En casos como escribir un compilador de C con LLM o portar Bun de Zig a Rust había formas de validar automáticamente la corrección
- Anthropic tenía compiladores de C existentes con los cuales comparar
- Bun tenía una suite de pruebas grande, lo bastante confiable como para fusionar más de 1 millón de líneas nuevas de Rust sin revisión manual
- webernetes no contaba con esa base
- Si necesitaban una suite de pruebas, tenían que escribirla ellos mismos
- Si querían comparar contra Kubernetes real, también tenían que crear el método de comparación
- La mayoría del código de webernetes fue portado desde la base de código Go de Kubernetes, y usaron LLM porque estimaron que sería más rápido que escribirlo a mano
- Durante el proceso de port, el LLM cometía errores repetidamente
- Simplificación excesiva: podía reemplazar la LRU cache, expiring cache, FIFO cache, transforming cache y otras estructuras de Kubernetes por un
Map, generando comportamientos incorrectos - Limpieza excesiva: podía crear funciones helper que no existían en el código Go original, dificultando la revisión o introduciendo diferencias sutiles
- Omisiones: al portar table tests de Go, a menudo omitía arbitrariamente casos de prueba
- Simplificación excesiva: podía reemplazar la LRU cache, expiring cache, FIFO cache, transforming cache y otras estructuras de Kubernetes por un
- Para confiar en el resultado de un port hecho por LLM hay que revisar la salida; el autor considera que no sabe qué atajos se puede permitir
Pruebas comparadas contra un clúster real
- Aunque el código se parezca lado a lado al original, los runtimes de Go y JavaScript son distintos, por lo que el comportamiento puede diferir
- webernetes también necesitó versiones JavaScript de channels, mutexes, la sentencia
selectde Go y otros comportamientos propios de Go - Ejecutan el mismo código de pruebas tanto contra webernetes como contra un clúster k3s para comparar el comportamiento
- Como objetivo de compatibilidad de API eligieron el cliente oficial de Kubernetes para JavaScript con tipos TypeScript, kubernetes-client/javascript
- El arnés de pruebas cambia el entorno de ejecución mediante
kubernetes.describe(..)pnpm test:nodeejecuta las pruebas en entorno Node contra k3spnpm test:browserejecuta las pruebas en un navegador headless contra webernetes
- Las pruebas de integración verifican no solo el código portado, sino también que el container runtime y la cluster network personalizados y basados en el navegador se comporten igual que en un clúster real
- Cuando encuentran un bug, primero crean una prueba que pase en k3s y falle en webernetes; luego usan ese ciclo de feedback, con ayuda del LLM, para entender y corregir la causa
- Al momento de escribir, webernetes tiene 204 pruebas de integración y 1.855 pruebas unitarias
Por qué hay que combinar revisión y pruebas
- El código creado por LLM necesita buenas pruebas y buen código, igual que un PR escrito por una persona
- La diferencia en 2026 es que antes se esperaba cierto nivel de buen trabajo de un colega humano, pero con un LLM es más seguro asumir que no hará un buen trabajo
- Si ni siquiera se revisa el código de pruebas, es difícil saber contra qué criterio de éxito está trabajando el LLM
- Aunque se revise todo el código, sin pruebas es difícil confiar en que una persona pueda inferir todas las posibilidades
- Como el LLM no se cansa y escribe rápido, resulta útil pedirle que proponga edge cases que a una persona no se le habrían ocurrido y, si son válidos, que escriba las pruebas
- La combinación del criterio y la comprensión humanos con la velocidad de escritura del LLM se sintió como el mayor cambio desde que el autor empezó su carrera en 2012
Tamaño del proyecto y uso de tokens
- El primer commit entró el 21 de abril en el repositorio actual de webernetes
- Parte del trabajo inicial se hizo en una rama del repositorio detrás de este sitio de blog, así que el gráfico no refleja toda la realidad
- El gráfico de líneas de código muestra 126.642 líneas para la semana del 15 de junio
- Las aproximadamente 100.000 líneas mencionadas al inicio excluyen código que no es TypeScript, comentarios y la demo app
- El total semanal de líneas creció así
- Semana del 20 de abril: 11.640 líneas
- Semana del 27 de abril: 20.660 líneas
- Semana del 4 de mayo: 25.048 líneas
- Semana del 11 de mayo: 30.417 líneas
- Semana del 18 de mayo: 42.301 líneas
- Semana del 25 de mayo: 54.155 líneas
- Semana del 1 de junio: 79.704 líneas
- Semana del 8 de junio: 98.532 líneas
- Semana del 15 de junio: 126.642 líneas
- En las sesiones de Codex y Claude, el uso de cached input tokens fue mucho mayor que el de otros tokens, algo especialmente marcado al llenar con frecuencia ventanas de contexto largas
- En la semana del 15 de junio se usaron 104.155.857 uncached input tokens, 2.196.467.968 cached input tokens y 6.420.826 output tokens
El pico de la última semana y el costo
- En la última semana, intentar agregar soporte para Deployments a la demo app terminó siendo más trabajo de lo esperado
- El primer intento de port del LLM omitió muchas funciones de los componentes necesarios
- Después usaron varios agentes para identificar la cadena de dependencias, portaron cada componente con más subagentes y realizaron revisiones con otros subagentes
- Este método terminó el trabajo más rápido que hacerlo manualmente, pero fue muy ineficiente en tokens y al final todavía hizo falta revisión manual
- El costo de tokens de LLM convertido a precios de API aumentó semana a semana; en la semana del 15 de junio fue de US$1.811,64
- En todo el proyecto, el tiempo del autor siguió siendo el rubro más caro hasta el final
Material final y cómo participar
- También hay una serie de videos que registra el proceso de creación
- En los videos se puede ver el optimismo inicial equivocado y la forma de trabajar casi completamente hands-free mediante control por voz y seguimiento ocular
- El autor invita a probar el proyecto, abrir issues o escribir a
s.rose@ngrok.comsi crearon algo o se quedaron bloqueados
1 comentarios
Opiniones en Hacker News
Por ejemplo, hice esto: https://kubernetes-made-simple.vercel.app/ y ahora podría agregarlo ahí
Aun así, el sitio está genial
Estaría bien ampliar más la parte de Gateway y, si es posible, mencionar también CRD
Si tuvieras que elegir una sola cosa que la mayoría de la gente malinterpreta sobre k8s y que hace el aprendizaje innecesariamente más difícil, ¿cuál sería?
Si mal no recuerdo, al principio usé Katacoda y después otras plataformas similares, y eran muy útiles porque levantaban al instante una nueva instancia con cierta configuración para cada usuario
Aun así, ahora esto parece encajar mejor para enseñar conceptos o arquitectura. La verdadera diversión empieza cuando ya comienzas a manejar kubectl con soltura
Otras plataformas parecidas también parecen haber desaparecido porque ya no había quién pagara los costos, y es una pena
Ojalá esto pueda ser una alternativa. Corre el riesgo de quedarse obsoleto al diferir de la realidad, pero aun así lo esencial casi siempre seguirá siendo válido
Esto se siente como la forma correcta de ver la ingeniería asistida por LLM. La IA puede generar una cantidad sorprendente de código, pero el valor real está en la disciplina de revisión y en las pruebas alrededor de eso
El ángulo de manejar Kubernetes en el navegador está bueno, pero lo más interesante es el flujo de trabajo, especialmente la parte de probar el comportamiento en k8s en vez de confiar en “se ve razonable”. Me pregunto cuántos equipos ya estarán validando a este nivel el código escrito por IA, y podría ser hacia donde todos vayamos en los próximos años
Lamentablemente, no todos los trabajos de programación tienen esa oportunidad
https://youtu.be/t7L2iROVaRg?is=xoV4aiCXcYMVvVDL
La complejidad adicional o la pérdida de rendimiento necesitarán cierta justificación, pero en algunos casos de uso parece que sí podría compensar suficientemente
Es similar a la distinción de Fred Brooks entre complejidad esencial y complejidad accidental
Claro, si usas kube para algo que podría hacerse de forma más simple, entonces kube se convierte rápidamente en complejidad accidental
Por analogía, si alguien portó DOOM al navegador, eso significa que ahora puedes jugarlo en el navegador. Pero eso no significa que realmente puedas ejecutar en el navegador las bases de datos que aparecen en la pestaña, ¿o sí?
Si levantas ruby2d, no puedes decir de repente que ahora existe soporte de Ruby del lado del cliente. Para que realmente corra en una pestaña del navegador, hace falta todo tipo de trabajo personalizado
En cambio, los servicios de contenedores backend normales de verdad se pueden mover de un lado a otro y ejecutarse en cualquier parte
Así que no termino de ver el punto; si estoy equivocado, corríjanme. Ni siquiera parece coincidir con lo que se está afirmando
No ejecuta imágenes de contenedor reales. Tal vez sería mejor llamarlo “Kubernetes simulado”
Lo que se portó fue el control plane. El scheduler, kube-proxy, deployment controller y demás fueron trasladados desde el código fuente real en Go, y se prueba la coincidencia de comportamiento con k3s usando la misma API de cliente. El “renderizado” es una app demo que visualiza con puntos las solicitudes entre Pods
Fue divertido