Sustituir ingress-nginx: Gateway API en práctica

ingress-nginx se detiene en marzo de 2026. Cómo migrar a la Gateway API con Kong, Traefik o NGINX Gateway Fabric: config, comandos, costes.

Fotografía en blanco y negro de una mujer escribiendo código en un portátil apoyado sobre sus rodillas

Respuesta corta: el proyecto ingress-nginx está al final de su vida útil: el equipo de Kubernetes ha anunciado el cese del mantenimiento y de los parches de seguridad en marzo de 2026. El sucesor oficial no es otro controlador Ingress, sino una API: la Gateway API, que alcanzó la GA (v1) en octubre de 2023. La migración consiste en instalar los CRD de la Gateway API, despliegar un controlador conforme (Kong, Traefik o NGINX Gateway Fabric), traducir cada Ingress a Gateway + HTTPRoute y luego conmutar el DNS. Es posible mantener ambos en paralelo durante la transición.

Muchos equipos que gestionan un clúster para una pyme se enteran de la noticia leyendo un boletín de seguridad: «ingress-nginx retirement». El controlador instalado hace tres años con un helm install y nunca tocado desde entonces se convierte, de un día para otro, en un componente sin mantenimiento expuesto a Internet. No es una urgencia que haya que resolver en una noche, pero sí un proyecto que conviene planificar ya, porque afecta al punto de entrada de todo el tráfico HTTP de producción.

Fotografía en blanco y negro de una mujer escribiendo código en un portátil apoyado sobre sus rodillas

Por qué se detiene ingress-nginx y qué cambia

ingress-nginx es el controlador Ingress histórico del proyecto Kubernetes, mantenido por el SIG Network. El anuncio de retirada, publicado en el blog de Kubernetes en noviembre de 2025, apunta a dos razones: un equipo de mantenedores reducido a un puñado de voluntarios para un componente crítico usado por la mayoría de los clústeres, y una deuda técnica difícil de sostener, en particular la famosa configuración mediante anotaciones y los configuration-snippet, origen de varias CVE de alto impacto (entre ellas CVE-2025-1974, «IngressNightmare», que permitía ejecutar código arbitrario en el controlador).

En concreto:

  • tras el cese, ninguna release más, ni parches de seguridad, ni imágenes actualizadas;
  • tu clúster seguirá funcionando: nada se rompe el día señalado;
  • pero cualquier nueva CVE en NGINX, en Lua o en el propio controlador se quedará sin parche oficial.

Un controlador Ingress está expuesto públicamente y dispone, por diseño, de un ClusterRole capaz de leer todos los Secrets del clúster (para los certificados TLS). Eso es precisamente lo que hacía devastador a IngressNightmare. Mantener un componente sin mantenimiento en ese punto del sistema no es una opción sostenible más allá de unos meses.

No confundir: ingress-nginx (el controlador comunitario de Kubernetes) y NGINX Ingress Controller, el producto mantenido por F5/NGINX. Este último sigue existiendo. La mayoría de los clústeres instalados con helm repo add ingress-nginx usan el primero.

Ingress también está en la recta final

El problema va más allá de un único controlador. La API networking.k8s.io/v1 Ingress está congelada: solo cubre el enrutado HTTP por host y por ruta. Todo lo demás —reescrituras, timeouts, mTLS, reparto de tráfico entre dos versiones, cabeceras, gRPC, TCP— se expresa mediante anotaciones propietarias, distintas en cada fabricante. Un Ingress con diez anotaciones nginx.ingress.kubernetes.io/* no es portable a ningún sitio.

La Gateway API responde a eso con recursos tipados, validados por el servidor de API, y un modelo de responsabilidades compartidas entre el equipo de plataforma y los equipos de aplicaciones.

El modelo de la Gateway API en tres recursos

RecursoQuién lo gestionaFunción
GatewayClassProveedor / plataformaDesigna la implementación (Kong, Traefik, NGINX…)
GatewayEquipo de plataformaLos listeners: puertos, protocolos, hostnames, certificados TLS
HTTPRouteEquipo de aplicaciónEl enrutado: rutas, cabeceras, backends, pesos, filtros

La ganancia operativa es inmediata: el equipo de plataforma posee el punto de entrada y los certificados, los desarrolladores declaran sus rutas en su propio namespace, sin poder tocar el listener 443 ni robar un hostname. La autorización pasa por allowedRoutes en el Gateway y por ReferenceGrant para las referencias entre namespaces.

Las versiones útiles en noviembre de 2026: GATEWAY_API_VERSION=v1.3.0 aporta HTTPRoute, GRPCRoute y GatewayClass en v1 (estable), mientras que TCPRoute, UDPRoute y TLSRoute siguen en v1alpha2. Los CRD no vienen incluidos con Kubernetes: hay que instalarlos explícitamente.

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml
kubectl get crd | grep gateway.networking.k8s.io

El canal standard basta para HTTP/HTTPS clásico. El canal experimental es necesario para TCPRoute, BackendTLSPolicy o el enrutado por porcentaje avanzado, según la implementación.

Elegir implementación: Kong, Traefik o NGINX Gateway Fabric

Tres candidatos serios para el clúster de una pyme, según lo que ya hicieras con tus anotaciones.

Kong Ingress Controller: si necesitas una auténtica pasarela de API

Kong es la opción pertinente en cuanto el punto de entrada hace algo más que enrutar: autenticación por clave u OIDC, rate limiting por consumidor, transformación de peticiones, registro estructurado. El controlador (KIC 3.x) es conforme a la Gateway API y expone sus funciones mediante KongPlugin asociados a un HTTPRoute.

helm repo add kong https://charts.konghq.com
helm repo update
helm install kong kong/ingress -n kong --create-namespace \
  --set controller.ingressController.image.tag=3.5 \
  --set gateway.env.database=off

El modo DB-less (database=off) es el recomendado: la configuración vive en los CRD de Kubernetes, no en una base PostgreSQL que haya que respaldar. Un plugin de limitación de caudal se asocia después a una ruta concreta:

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: rate-limit-api
  namespace: production
plugin: rate-limiting
config:
  minute: 120
  policy: local
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api
  namespace: production
  annotations:
    konghq.com/plugins: rate-limit-api
spec:
  parentRefs:
    - name: public-gateway
      namespace: infra
  hostnames:
    - api.ejemplo.es
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /v1
      backendRefs:
        - name: api-svc
          port: 8080

El coste: Kong Gateway OSS es gratuito (licencia Apache 2.0), pero los plugins empresariales (OIDC completo, RBAC, Konnect) son de pago. Cuenta con dos pods de 256 Mi a 512 Mi de RAM para un tráfico moderado.

Traefik: el más sencillo de poner en marcha

Traefik v3 soporta la Gateway API además de sus IngressRoute históricos. Si ya usabas Traefik o si tus necesidades se limitan a enrutado + TLS y algunos middlewares, es la migración menos costosa.

helm repo add traefik https://traefik.github.io/charts
helm install traefik traefik/traefik -n traefik --create-namespace \
  --set providers.kubernetesGateway.enabled=true \
  --set gateway.enabled=false

Cuidado con un detalle que hace perder media jornada: por defecto, el chart de Traefik crea él mismo un Gateway. Si gestionas el tuyo en GitOps, desactívalo (gateway.enabled=false) o acabarás con dos objetos disputándose el mismo listener.

NGINX Gateway Fabric: para seguir con NGINX

NGF es la implementación de la Gateway API mantenida por NGINX/F5, con NGINX como data plane. Es el camino con menos sorpresas si tus equipos leen con soltura directivas NGINX y quieres conservar el mismo comportamiento de proxy (buffering, keepalive, timeouts). A cambio, el ecosistema de políticas es más joven que el de Kong.

Manos de un hombre adulto escribiendo en un portátil que muestra código en un editor oscuro

Traducir tus Ingress a HTTPRoute

Este es el ejercicio concreto. Un Ingress típico sacado de un clúster de producción:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: site
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts: [www.ejemplo.es]
      secretName: site-tls
  rules:
    - host: www.ejemplo.es
      http:
        paths:
          - path: /api(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service: { name: api-svc, port: { number: 8080 } }
          - path: /
            pathType: Prefix
            backend:
              service: { name: web-svc, port: { number: 3000 } }

El Gateway equivalente, propiedad del equipo de plataforma:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: public-gateway
  namespace: infra
spec:
  gatewayClassName: kong
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      hostname: "*.ejemplo.es"
      tls:
        mode: Terminate
        certificateRefs:
          - name: site-tls
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: "true"

Y la ruta, del lado de la aplicación, con la reescritura expresada mediante un filtro tipado en lugar de una anotación:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: site
  namespace: production
spec:
  parentRefs:
    - name: public-gateway
      namespace: infra
  hostnames:
    - www.ejemplo.es
  rules:
    - matches:
        - path: { type: PathPrefix, value: /api }
      filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplacePrefixMatch
              replacePrefixMatch: /
      backendRefs:
        - name: api-svc
          port: 8080
    - matches:
        - path: { type: PathPrefix, value: / }
      backendRefs:
        - name: web-svc
          port: 3000

Tres puntos que conviene retener:

  1. La regex desaparece. rewrite-target: /$2 se convierte en un filtro URLRewrite con ReplacePrefixMatch. Más legible, pero las reescrituras realmente regulares (capturas múltiples) no tienen equivalente estándar: pasan por una política propia de la implementación.
  2. ReferenceGrant es obligatorio si el Secret TLS o un Service de backend vive en un namespace distinto al del objeto que lo referencia. Sin él, el estado de la ruta se queda en ResolvedRefs: False y el tráfico cae en 500.
  3. cert-manager sabe emitir certificados para un Gateway: activa --enable-gateway-api en el controlador y anota el Gateway con cert-manager.io/cluster-issuer. Está soportado desde cert-manager 1.15.

La herramienta que hace el 80 % del trabajo

El proyecto Gateway API ofrece ingress2gateway, que lee tus Ingress (incluidas ciertas anotaciones de nginx y de kong) y genera los manifiestos correspondientes:

go install github.com/kubernetes-sigs/ingress2gateway@latest
ingress2gateway print --providers ingress-nginx --all-namespaces > gateway-api.yaml

El resultado es un punto de partida, no una entrega final: revísalo, factoriza los Gateway (la herramienta suele crear uno por Ingress) y comprueba cada anotación no traducida.

Conmutar sin cortes

La buena noticia: ambos mundos conviven. Un controlador Ingress y un Gateway pueden funcionar en paralelo, cada uno detrás de su propio Service de tipo LoadBalancer y, por tanto, de su propia IP.

  1. Instalar los CRD y el nuevo controlador en un namespace dedicado. Comprobar que la IP se asigna: kubectl get gateway -A -o wide.
  2. Probar sin DNS, con la cabecera Host forzada hacia la nueva IP:
    curl -sk --resolve www.ejemplo.es:443:203.0.113.42 https://www.ejemplo.es/api/health -i
    
  3. Validar el estado de las rutas antes de cualquier conmutación: kubectl describe httproute site -n production debe mostrar Accepted: True y ResolvedRefs: True.
  4. Bajar el TTL del DNS a 60 s el día anterior y luego conmutar el registro A/AAAA. En OVHcloud o Scaleway, prevé unos minutos de propagación real más allá del TTL anunciado.
  5. Observar durante 24 a 48 h los códigos 4xx/5xx y las latencias p95 en la IP antigua y en la nueva. El rollback es un simple retorno del DNS mientras el controlador antiguo siga funcionando.
  6. Desinstalar ingress-nginx solo tras una semana sin tráfico residual en su Service.

La trampa clásica son los WebSocket y las conexiones largas: no se reproducen, se cortan en el momento en que el cliente reabre. Prevé la conmutación fuera de las horas punta y revisa los timeouts en el nuevo Gateway (Kong: KongIngress/KongUpstreamPolicy; Traefik: ServersTransport).

Pantalla de ordenador mostrando líneas de código Python en colores, vista en primer plano y en diagonal

En cuanto al coste, la partida a vigilar no es la licencia, sino el balanceador de carga. Cada Gateway con un listener expuesto crea un servicio LoadBalancer y, por tanto, una IP facturada por el proveedor: en torno a 10-15 €/mes en OVHcloud o Scaleway para un LB gestionado de gama de entrada. Durante la fase de convivencia, pagas los dos. Después, mutualiza: un único Gateway compartido por varios namespaces gracias a allowedRoutes, en lugar de un Gateway por aplicación. Es exactamente el tipo de decisión que abordamos en nuestros proyectos de infraestructura y operación cloud.

Piensa también en los secretos de registro si tus imágenes son privadas: los pods del nuevo controlador y, sobre todo, tus aplicaciones redespliegadas en nuevos namespaces necesitan su imagePullSecret. El tema está detallado en nuestra guía sobre las imágenes GitLab privadas en Kubernetes.

Preguntas frecuentes

¿Hay que migrar sin falta antes de marzo de 2026?

No: técnicamente nada se detiene en esa fecha. Lo que se detiene es la publicación de parches. El criterio real es tu exposición: un clúster público con datos de clientes debería migrarse en el trimestre; un clúster interno detrás de una VPN puede esperar una ventana más cómoda. En cualquier caso, documenta la decisión y vigila los anuncios de CVE de NGINX.

¿Se puede mantener ingress-nginx y añadir un Gateway?

Sí, y es la estrategia recomendada para la transición. Ambas API coexisten en el mismo clúster. Solo hay que cuidar que un mismo hostname no se sirva por las dos a la vez: obtendrías un comportamiento dependiente del DNS y, por tanto, incidencias imposibles de reproducir.

Kong, Traefik o NGINX Gateway Fabric: ¿cuál para una pyme?

Traefik si quieres la mínima fricción y te basta con enrutado + TLS. Kong si el punto de entrada debe actuar como pasarela de API (claves, cuotas, OIDC, registro). NGINX Gateway Fabric si tu equipo quiere conservar NGINX como data plane. Los tres son conformes a HTTPRoute v1, así que tus rutas siguen siendo portables: solo las políticas específicas (plugins, middlewares) te atan a un fabricante.

¿Qué pasa con las anotaciones que no tienen equivalente?

Pasan por CRD propios de cada implementación: KongPlugin y KongUpstreamPolicy en Kong, Middleware en Traefik, ClientSettingsPolicy y ObservabilityPolicy en NGF. Aprovecha la migración para hacer inventario: en la práctica, un tercio de las anotaciones acumuladas con los años ya no sirve para nada.

¿La Gateway API gestiona TCP y gRPC?

GRPCRoute es estable desde la v1.1 del canal standard. TCPRoute, UDPRoute y TLSRoute siguen en v1alpha2 y requieren el canal experimental, con un soporte variable según la implementación. Para exponer PostgreSQL o Redis fuera del clúster, comprueba primero la matriz de conformidad del proyecto Gateway API.

En resumen

  • ingress-nginx deja de mantenerse después de marzo de 2026: sin parches de seguridad en un componente expuesto que puede leer todos los Secrets del clúster.
  • El sucesor es la Gateway API (v1.3.0), que se instala mediante sus CRD, con un controlador conforme: Kong (pasarela de API), Traefik (simplicidad), NGINX Gateway Fabric (continuidad con NGINX).
  • La migración traduce cada Ingress a Gateway + HTTPRoute: las anotaciones se convierten en filtros tipados e ingress2gateway genera un primer borrador.
  • Ambos controladores conviven: prueba con curl --resolve, conmuta por DNS con TTL reducido y conserva el antiguo una semana para el rollback.
  • Vigila el coste de los balanceadores de carga durante la convivencia y mutualiza después un único Gateway mediante allowedRoutes.
  • ¿Necesitas una mirada externa sobre tu punto de entrada o tu clúster? Conoce al equipo y hablemos de tu proyecto.