El repositorio kubernetes/ingress-nginx está archivado. Solo lectura. La última versión del controlador, controller-v1.15.1, se publicó el 19 de marzo: hace 187 días. No es un proyecto que se haya ido apagando por descuido —está retirado a propósito, con fecha y con comunicado—, y lo que firmaron el Steering Committee y el Security Response Committee de Kubernetes para explicarlo no fue un fallo de seguridad. Fue una frase sobre plantilla: «maintained solely by one or two people working in their free time».
Tres fechas y dos frases
El 11 de noviembre de 2025, el blog de Kubernetes anunció la retirada para marzo de 2026. El 29 de enero de 2026, los dos comités publicaron un comunicado conjunto para, en sus palabras, «reinforce the scale of this change». Y en marzo se cerró: el repositorio quedó archivado en solo lectura. Eso es lo que dice la historia oficial; lo hemos comprobado hoy contra la API de GitHub, que devuelve "archived": true, el último push fechado el 23 de marzo de 2026 y tres versiones del controlador publicadas el 19 de marzo —controller-v1.15.1, controller-v1.14.5 y controller-v1.13.9, con sus tres charts de Helm correspondientes—, las últimas que existirán. El proyecto acumula 19.469 estrellas.
Las dos frases del comunicado que importan son estas. La primera acota el alcance: Ingress NGINX es «a piece of critical infrastructure for about half of cloud native environments», y más abajo lo cifran citando su fuente —«According to internal Datadog research, about 50% of cloud native environments currently rely on this tool»—. Es investigación interna de un tercero citada por Kubernetes, no un censo; la tomamos por lo que es, un orden de magnitud. La segunda frase no tiene matiz posible: «There will be no more releases for bug fixes, security patches, or any updates of any kind after the project is retired». Y el comité lo remata sin diplomacia: «choosing to remain with Ingress NGINX after its retirement leaves you and your users vulnerable to attack».
El dato que había que mirar no era un CVE
Aquí es donde este caso se separa de los demás. Un fabricante que se retrasa con un parche es un problema de plazos. Un proyecto que se cierra porque nunca tuvo gente es otra cosa, y el comunicado lo dice con todas las letras: hubo «years of public warnings that the project was in dire need of contributors and maintainers». Años. El aviso estaba dado y no tenía dónde aterrizar, porque ese componente no estaba en la ficha de nadie: nadie lo compró, nadie firmó nada por él, y por tanto nadie tuvo nunca que contestar a la pregunta que lo predecía todo —cuánta gente hay detrás y si cobra por estar ahí—.
Conviene decir qué NO es esto, porque se presta al titular fácil. No es un argumento contra el software libre: nuestra propia infraestructura es libre casi de arriba abajo —Proxmox VE, Ceph, Zabbix, WireGuard, Docker Swarm y Kubernetes— y no pensamos cambiarla. Es un argumento a favor de mirar quién mantiene cada dependencia crítica, que es una pregunta neutral respecto a la licencia. El software de pago tiene su versión exacta del mismo problema: se llama fin de soporte, y el aparato se queda igual de quieto. Ya lo escribimos a cuenta de otro ecosistema con el mismo agujero de gobernanza: quién mantiene tu web es una pregunta con nombre y apellidos, o no es una pregunta. Y cuando la respuesta es «nadie», a veces directamente no hay nada que parchear.
La parte más incómoda del comunicado es la que describe el silencio: «Existing deployments will continue to work, so unless you proactively check, you may not know you are affected until you are compromised». Nada se cae. Ningún panel se pone en rojo. El mismo comunicado da el comando para salir de dudas, y es de una línea:
kubectl get pods --all-namespaces \
--selector app.kubernetes.io/name=ingress-nginx
Traducir el YAML es la parte fácil
El 20 de marzo, tres días antes de archivar el repositorio, SIG Network publicó Ingress2Gateway 1.0, la herramienta que traduce recursos Ingress a Gateway API. El salto de esa versión da la medida del problema: antes soportaba tres anotaciones de Ingress-NGINX; la 1.0 soporta más de treinta. Los autores del anuncio son explícitos sobre lo que no es: «Ingress2Gateway is a migration assistant, not a one-shot replacement» y «Migration is not a “one-click” affair».
La herramienta avisa por escrito de lo que no puede traducir, y esos avisos son la lista de decisiones que alguien tendrá que tomar a mano. Tres ejemplos del propio anuncio: la anotación configuration-snippet no está soportada; proxy-body-size no tiene equivalente en Gateway API y se queda sin traducir; y la normalización de URL no se puede configurar en Gateway API —«Gateway API does not support configuring URL normalization (RFC 3986, Section 6)»—. Lo que la herramienta no puede avisarte es de lo contrario: de lo que traduce de más, porque el original hacía algo que tú no sabías que hacía.
Cinco cosas que tu enrutado hace y nadie eligió
En febrero, Steven Jin (Microsoft) publicó en el blog de Kubernetes un artículo previo a la migración con cinco comportamientos por defecto de Ingress-NGINX. Los resumimos porque son, en nuestra opinión, la parte cara de esta mudanza:
| Comportamiento por defecto | Lo que significa en tu clúster |
|---|---|
| Un patrón regex casa por prefijo y sin distinguir mayúsculas | La ruta /[A-Z]{3} deja pasar /uuid |
use-regex no se aplica por cada Ingress | Aplica a todas las rutas de ese host, en todos los Ingress: un equipo cambia el enrutado de otro |
rewrite-target implica regex | Activas el modo expresión regular sin haberlo pedido |
| Falta la barra final | Devuelve un 301 a la ruta con barra, aunque el pathType sea Exact |
| Normaliza la URL antes de casar reglas | /ip/abc/../../uuid llega a /uuid; ////uuid responde 301 |
Nuestra lectura, dicha como opinión: el primero y el último de esa lista no son detalles de enrutado, son control de acceso. Si alguien escribió hace tres años una regla creyendo que restringía a tres letras mayúsculas, lleva tres años sin restringir nada. Esa regla no la va a descubrir un escáner ni una auditoría de YAML: solo aparece cuando alguien traduce el fichero a otro lenguaje y tiene que decir en voz alta qué quería decir. Por eso esta migración no es una traducción, es una lectura.
A favor del destino hay que decir esto: en normalización de URL, el propio artículo dice que la mayoría de implementaciones de Gateway API ya limpian los segmentos . y .. por defecto, y cita a Istio, Envoy Gateway y Kgateway. Así que el riesgo no es tanto perder la normalización como no saber que tu aplicación llevaba años apoyándose en ella.
No traduzcas: mide primero
Cambiar el controlador de entrada de un clúster es, en la clasificación que de verdad importa, un cambio de configuración a mano en producción. Y ahí hay literatura: el estudio de Oppenheimer, Ganapathi y Patterson presentado en USENIX en 2003 sobre por qué fallan los grandes servicios de internet puso los cambios de configuración de los operadores en cabeza de las causas de caída grave, con el hardware explicando solo entre el 10 y el 25 %. Veintitrés años después seguimos viendo lo mismo en las guardias. La diferencia entre un fallo y una avería no la pone el componente: la pone el procedimiento con el que lo tocas.
Así lo planteamos nosotros. Primero, el inventario real no está en el YAML sino en el log de acceso del propio ingress: hosts, rutas y códigos de respuesta de un par de semanas, que es la única lista de lo que de verdad usa alguien. Segundo, se traduce y se lee cada aviso, porque un «no soportado» es una decisión de producto disfrazada de advertencia. Tercero, el nuevo controlador se levanta en paralelo y se compara comportamiento con tráfico real antes de tocar el DNS: mismas rutas, mismos códigos, mismos redirects. Y cuarto, se cambia con vuelta atrás preparada y ensayada, no «documentada». Es la misma disciplina de despliegues reproducibles y reversibles que aplicamos en todo lo demás, y que ya contamos cuando escribimos que «latest» no es una versión.
El calendario que nadie presupuestó
Esto no acaba con el ingress, y ese es el punto que se le escapa a mucha dirección al aprobar un proyecto con Kubernetes. La política de soporte del proyecto es pública y está escrita en su página de versiones: «the Kubernetes Community will support active patch release series for a period of roughly fourteen (14) months» —doce meses de soporte estándar más dos de modo mantenimiento solo para fallos críticos—. Con tres versiones menores al año, el calendario vigente hoy es este:
| Versión | Fin de soporte estándar | Fin de vida |
|---|---|---|
| 1.34 | 27-08-2026 | 27-10-2026 |
| 1.35 | 28-12-2026 | 28-02-2027 |
| 1.36 | 28-04-2027 | 28-06-2027 |
| 1.37 | 28-08-2027 | 28-10-2027 |
Leído del derecho: si hoy estás en 1.34, tienes hasta el 27 de octubre. Y cuando llegues a 1.37 volverás a tener otra fecha. El coste de Kubernetes no es el clúster, es el calendario: una actualización mayor cada pocos meses, para siempre, más el calendario propio de cada pieza del ecosistema que hay alrededor —y ese segundo calendario no lo firma nadie—. Ingress NGINX es justo eso: una fecha que no estaba en ninguna hoja de ruta y que ha aparecido igual.
Y ahora lo que nos va en contra decir, porque ofrecemos Kubernetes gestionado: no todo el mundo necesita Kubernetes. Operamos clústeres de Kubernetes y también de Docker Swarm, y elegimos según el caso, no según lo que quede mejor en una propuesta. Si tu producto son cuatro servicios y una base de datos, con un equipo que no tiene a nadie dedicado a plataforma, el calendario de arriba se lo va a comer alguien que debería estar escribiendo producto. Esa conversación es más barata tenerla antes que después.
Qué haríamos esta semana
- Comprobar si te toca, con el comando del comunicado y con
kubectl get ingressclass. En clústeres gestionados por terceros, preguntar también qué controlador puso el proveedor: esto suele estar instalado por un chart que nadie recuerda haber elegido. - Medir el tamaño real de la migración, que no es el número de Ingress sino el de anotaciones distintas que usas. Esta línea lo dice en diez segundos:
kubectl get ingress -A -o json \
| jq -r '.items[].metadata.annotations // {} | keys[]' \
| grep '^nginx.ingress.kubernetes.io/' \
| sort | uniq -c | sort -rn
- Sacar del log de acceso la lista real de host + ruta + código de los últimos catorce días. Esa lista es el criterio de aceptación de la migración; sin ella, «funciona» significa «me he metido en la portada y cargaba».
- Traducir con Ingress2Gateway y leer los avisos uno a uno. Cada «unsupported» es una funcionalidad que hoy tienes y mañana no, y alguien tiene que decidir si eso importa. No lo decide la herramienta.
- Y la que no es técnica: añadir a la ficha de cada dependencia crítica una línea con cuánta gente la mantiene y si alguien cobra por hacerlo. Es una pregunta de dos minutos que en este caso llevaba años contestada en público —el propio comunicado habla de «years of public warnings»— y que habría dado margen en vez de dos meses.
Lo que nos deja este caso: durante años, la pregunta de gobernanza que todo el mundo hacía sobre una dependencia era «¿tiene CVE abiertos?». Resulta que la que predecía el cierre de la puerta de entrada de medio ecosistema no salía en ningún escáner, la contestaban los propios mantenedores en voz alta, y era de plantilla. Estaba publicada. Nadie la leyó porque ese componente no era de nadie.
¿Sabes quién mantiene lo que publica tu producto?
Operamos Kubernetes y Docker Swarm en producción, propios y de clientes, con despliegues reproducibles y vuelta atrás ensayada. En la infraestructura y cloud que gestionamos, cada pieza crítica tiene versión fijada, dueño y fecha de caducidad conocida; y si lo que hace falta es decidir si te conviene Kubernetes o no, eso es consultoría y la hacemos sin vender licencias de nadie. Si tu respuesta a la pregunta del título es «creo que sí», es que no.
Hablar con everyWANNota de fuentes
Todo consultado el 22 de septiembre de 2026. Uno: el comunicado conjunto del Kubernetes Steering Committee y el Security Response Committee, publicado en el blog de Kubernetes el 29 de enero de 2026, de donde salen las citas literales que la abren: el alcance de «about half of cloud native environments», la atribución del 50 % a investigación interna de Datadog, la frase sobre «one or two people working in their free time», la de que no habrá más versiones ni parches, la advertencia de que quedarse expone a ataque, la del silencio hasta el compromiso y el comando de comprobación. Dos: el anuncio de retirada del 11 de noviembre de 2025, también en el blog de Kubernetes, que fija marzo de 2026 y recomienda migrar a Gateway API o a otro controlador. Tres: la API pública de GitHub para kubernetes/ingress-nginx, consultada hoy: campo archived a verdadero, pushed_at del 23 de marzo de 2026, las tres etiquetas de versión publicadas el 19 de marzo de 2026 y el recuento de estrellas. Los 187 días son nuestros, restando fechas de calendario entre el 19 de marzo y hoy. Cuatro: «Announcing Ingress2Gateway 1.0», blog de Kubernetes del 20 de marzo de 2026 (Beka Modebadze, Google, y Steven Jin, Microsoft): el salto de tres a más de treinta anotaciones, las dos frases sobre que no es un reemplazo de un clic y los avisos sobre configuration-snippet, proxy-body-size y la normalización de URL. Cinco: «Before You Migrate: Five Surprising Ingress-NGINX Behaviors You Need to Know», blog de Kubernetes del 27 de febrero de 2026 (Steven Jin, Microsoft): los cinco comportamientos de la tabla y la nota de que Istio, Envoy Gateway y Kgateway normalizan por defecto. Seis: la página de versiones de parche de kubernetes.io, de donde sale la cita de los catorce meses de soporte —doce de estándar más dos de mantenimiento— y las fechas de 1.34 a 1.37. Siete: Oppenheimer, Ganapathi y Patterson, «Why Do Internet Services Fail, and What Can Be Done About It?», USENIX 2003, para la causa principal de caídas graves. Lo que no afirmamos: no hemos auditado el código de Ingress-NGINX ni reproducido los cinco comportamientos en un clúster propio —los recogemos de la fuente citada—; no tenemos una cifra propia de cuántos clústeres siguen usándolo; no afirmamos que exista hoy ninguna vulnerabilidad sin parchear en él, solo que si aparece no habrá parche; y no recomendamos aquí ninguna implementación concreta de Gateway API porque la elección depende de qué más corra en ese clúster. Opinión nuestra: que la pregunta útil sobre una dependencia es de plantilla y no de CVE, que esta migración es una lectura del enrutado y no una traducción, que los puntos uno y cinco de la tabla son control de acceso, el método de medir antes de traducir, y que hay casos en los que Kubernetes no compensa.
Imagen de portada: fotografía de dominio público de una batería de torniquetes de acceso, recortada por nosotros. Los textos y la marca los añadimos nosotros encima.