Ingress vs Gateway API: dos formas de exponer tráfico en Kubernetes
La idea central: dos caminos para resolver el mismo problema
Ingress y Gateway API resuelven un problema parecido: permitir que el tráfico externo llegue a servicios dentro de Kubernetes. La diferencia está en cómo modelan ese problema.
Ingress es un recurso estable de Kubernetes para publicar servicios HTTP/HTTPS usando reglas de host y path. Es
simple, muy conocido y todavía sigue siendo válido. Pero tiene una limitación importante: la API está congelada. Es GA,
no se va a remover, pero ya no está pensada para crecer con nuevas capacidades.
Gateway API aparece como una evolución de ese modelo. No es un proxy ni un producto específico. Es una familia de CRDs oficiales del proyecto Kubernetes SIG Network que permite describir networking L4/L7 de una forma más expresiva, extensible, portable y con una separación más clara de responsabilidades.
A mí me sirve resumirlo así:
Ingress publica aplicaciones. Gateway API modela una plataforma de entrada de tráfico.
La comparación rápida sería esta:
| Tema | Ingress | Gateway API |
|---|---|---|
| Modelo | Un recurso principal: Ingress | Varios recursos: GatewayClass, Gateway, HTTPRoute, GRPCRoute, TLSRoute, ReferenceGrant, policies |
| Enfoque | Centrado en la aplicación | Centrado en roles y responsabilidades |
| Entrada de tráfico | Implícita en el Ingress Controller | Explícita mediante Gateway y listeners |
| Routing | HTTP/HTTPS básico por host y path | Routing por host, path, headers, query params, method, weights, filters, timeouts, etc. |
| Extensibilidad | Principalmente annotations del controller | Campos estructurados, filters, policies, extensionRefs, backendRefs |
| Multi-team | Limitado | Diseñado para infraestructura compartida |
| Portabilidad | Baja cuando dependés de annotations | Mejor, aunque depende del soporte real de cada implementación |
| Estado | Estable, pero congelado | Línea moderna de evolución del networking en Kubernetes |
Ingress: el modelo clásico para publicar aplicaciones
El problema que resuelve Ingress
Ingress expone rutas HTTP y HTTPS desde fuera del clúster hacia Services dentro del clúster.
Sirve para cosas como:
- dar URLs externas a servicios;
- terminar TLS;
- balancear tráfico;
- hacer virtual hosting basado en nombre.
No sirve para exponer cualquier protocolo o puerto de forma genérica. Para tráfico que no sea HTTP/HTTPS, normalmente se
usan otros mecanismos, como NodePort, LoadBalancer o configuraciones específicas del controller.
Un modelo mental simple sería:
Cliente
↓
DNS
↓
Load Balancer / VIP / NodePort
↓
Ingress Controller
↓
Ingress rule
↓
Service
↓
Pod
El recurso Ingress por sí solo no alcanza. Necesitás un Ingress Controller que lo observe y lo convierta en
configuración real para algún dataplane: NGINX, Traefik, HAProxy, Kong, Envoy, etc.
En otras palabras: el YAML de Ingress describe la intención, pero el controller es quien la hace funcionar.
Cómo se ve un Ingress por dentro
Un Ingress típico define:
ingressClassName;- reglas por host;
- reglas por path;
- backend
Service; - TLS opcional.
Ejemplo básico:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: apps
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
Esto se puede leer así:
Para app.example.com,
entrando por HTTPS,
mandá todo lo que matchee con "/" hacia app-service:80.
Para casos simples funciona muy bien. El problema aparece cuando necesitás algo más fino que host, path y TLS básico.
El límite real de Ingress: cuando todo termina en annotations
Ingress soporta de forma estándar un conjunto bastante acotado de capacidades:
- terminación TLS;
- routing HTTP simple;
- routing por host;
- routing por path.
Cuando necesitás features más avanzadas, la solución suele pasar por annotations específicas del controller.
Un Ingress real en producción puede terminar así:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
ingressClassName: nginx
rules:
...
Eso funciona, pero ya no es una configuración portable de Kubernetes. Es una configuración atada a NGINX Ingress.
Si mañana cambiás a Traefik, HAProxy, Kong o Envoy, esas annotations no se traducen solas. Ese es uno de los dolores más
grandes de Ingress: muchas capacidades útiles quedaron fuera de spec y terminaron como strings key/value dentro de
metadata.annotations.
Gateway API: una forma más moderna de modelar el tráfico
El problema que viene a resolver Gateway API
Gateway API intenta resolver el mismo problema base que Ingress, pero con una arquitectura más explícita.
El modelo se parece más a esto:
GatewayClass
↓
Gateway
↓
Listener
↓
Route
↓
BackendRef / Service
↓
Pods
Los recursos viven en el grupo:
gateway.networking.k8s.io
y se instalan como CRDs.
El modelo principal gira alrededor de tres tipos de objetos:
GatewayClass;Gateway;Route.
GatewayClass define una clase de gateways.
Gateway pide un punto de entrada para tráfico.
Las Routes describen cómo ese tráfico se manda hacia los servicios.
La diferencia importante no es solo que haya más objetos. La diferencia es que cada objeto representa una responsabilidad distinta.
Gateway API no es un proxy: es una interfaz declarativa
Este punto conviene dejarlo claro:
Gateway API no es Envoy, no es Kong, no es Traefik y no es NGINX.
Gateway API es una interfaz declarativa. Después necesitás una implementación que la reconcilie.
El modelo real sería:
Kubernetes API Server
↓ watches
Gateway API Controller
↓ programs
Dataplane real
↓ handles traffic
Services / Pods
Algunos ejemplos:
| Implementación | Dataplane típico |
|---|---|
| Envoy Gateway | Envoy |
| Kong | Kong Gateway |
| Traefik | Traefik Proxy |
| Cilium | Envoy/eBPF, según el caso |
| NGINX Gateway Fabric | NGINX |
| Contour | Envoy |
La API define el contrato. La implementación decide cómo convertir ese contrato en tráfico real.
Las piezas principales de Gateway API
GatewayClass: la clase que define quién controla el Gateway
GatewayClass define qué controller maneja un tipo de gateway.
Es un recurso cluster-scoped y cumple un rol parecido a IngressClass para Ingress o StorageClass para volúmenes.
Ejemplo:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy-gateway
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
Esto no abre ningún puerto ni publica tráfico. Solo dice:
Los Gateways que usen esta clase serán manejados por este controller.
En muchas implementaciones, el GatewayClass lo crea el chart, el operator o el manifiesto de instalación del
controller.
Gateway: el punto de entrada al clúster
Gateway representa el punto de entrada.
Define direcciones y listeners. Las direcciones indican cómo se alcanza al Gateway. Los listeners describen puerto, protocolo, hostname, TLS y qué routes pueden adjuntarse.
Ejemplo:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: public-gateway
namespace: gateway-system
spec:
gatewayClassName: envoy-gateway
listeners:
- name: http
protocol: HTTP
port: 80
hostname: "*.example.com"
allowedRoutes:
namespaces:
from: All
Esto se puede leer así:
Quiero un punto de entrada público,
manejado por la clase envoy-gateway,
escuchando HTTP en el puerto 80,
para hosts *.example.com,
y aceptando routes desde todos los namespaces.
En Ingress, los entrypoints HTTP/HTTPS suelen venir dados por el controller. En Gateway API, esos entrypoints se
declaran explícitamente en el Gateway.
Listener: donde se define cómo entra el tráfico
Un listener es parte de un Gateway.
Define preguntas concretas:
¿Qué protocolo escucho?
¿En qué puerto?
¿Para qué hostname?
¿Termino TLS o hago passthrough?
¿Qué routes pueden adjuntarse?
Ejemplo:
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: app.example.com
tls:
mode: Terminate
certificateRefs:
- name: app-tls
allowedRoutes:
namespaces:
from: Same
Gateway API también define reglas para evitar listeners ambiguos o en conflicto. Por ejemplo, dos listeners HTTPS en el mismo puerto pueden convivir si se distinguen por hostname.
HTTPRoute: donde vive la lógica de routing HTTP
HTTPRoute define reglas específicas para HTTP.
Sirve para HTTP o HTTPS terminado, y permite tomar decisiones usando datos de la request, como path, headers, query params o método HTTP.
Ejemplo:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
namespace: apps
spec:
parentRefs:
- name: public-gateway
namespace: gateway-system
hostnames:
- app.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: app-service
port: 80
Esto dice:
Quiero adjuntarme al Gateway public-gateway.
Acepto tráfico para app.example.com.
Si el path empieza con /, mando la request a app-service:80.
HTTPRoute permite matches más ricos que Ingress:
- path;
- headers;
- query params;
- método HTTP.
También soporta pesos en backendRefs, lo que permite dividir tráfico entre dos versiones, por ejemplo 90% a v1 y 10%
a v2.
Filters: cómo modificar o procesar requests
Los filters permiten modificar o procesar requests y responses.
Algunos casos típicos son:
- modificar headers;
- hacer redirects;
- hacer rewrites;
- aplicar request mirroring;
- aplicar timeouts;
- conectar extensiones específicas de la implementación.
El soporte concreto depende del tipo de filtro y de la implementación.
Ejemplo:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-route
namespace: apps
spec:
parentRefs:
- name: public-gateway
namespace: gateway-system
hostnames:
- app.example.com
rules:
- filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: X-From-Gateway
value: "true"
backendRefs:
- name: app-service
port: 80
En Ingress, algo así normalmente terminaría como una annotation específica del controller. En Gateway API, al menos una parte de esas capacidades pasa a vivir en una API estructurada.
Rutas por protocolo: HTTP, gRPC, TLS, TCP y UDP
Gateway API define recursos de routing por protocolo, pero no todos tienen el mismo nivel de madurez ni el mismo soporte.
HTTPRoute sirve para HTTP o HTTPS terminado.
GRPCRoute está pensado para enrutar tráfico gRPC de forma más idiomática.
TLSRoute sirve para enrutar tráfico TLS usando SNI, especialmente cuando no querés inspeccionar HTTP.
TCPRoute y UDPRoute cubren tráfico L4, pero conviene tratarlos con más cuidado porque siguen dependiendo del canal
experimental y del soporte de cada implementación.
Este punto es importante: usar Gateway API no significa que todo esté soportado igual en todos lados. Algunas features son core, otras extended, otras experimentales y otras directamente específicas de implementación.
ReferenceGrant: control seguro entre namespaces
ReferenceGrant resuelve un problema clave: las referencias entre namespaces.
Ejemplo típico:
Un HTTPRoute en el namespace apps
quiere mandar tráfico a un Service en el namespace shared-services.
Por seguridad, eso no debería permitirse automáticamente.
ReferenceGrant permite que el namespace dueño del recurso referenciado autorice esa referencia de forma explícita.
Ejemplo:
apiVersion: gateway.networking.k8s.io/v1
kind: ReferenceGrant
metadata:
name: allow-apps-to-backend
namespace: shared-services
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: apps
to:
- group: ""
kind: Service
Esto dice:
Permito que HTTPRoutes del namespace apps referencien Services de este namespace.
Sin ReferenceGrant, una referencia cross-namespace es inválida.
Este mecanismo también puede usarse para permitir que Routes referencien backends en otros namespaces, o que Gateways referencien Secrets en otros namespaces.
Ingress no tiene un mecanismo equivalente tan claro dentro de su propia API.
Qué pasa detrás de escena: el plano de control
Cómo se reconcilia Ingress
Con Ingress, el flujo de control suele ser:
Usuario aplica Ingress
↓
API Server guarda el recurso
↓
Ingress Controller observa Ingress, Services, EndpointSlices y Secrets
↓
Genera configuración del proxy
↓
Recarga o actualiza el dataplane
↓
El proxy empieza a enrutar tráfico
Ejemplo con NGINX Ingress:
Ingress YAML
↓
nginx-ingress-controller
↓
nginx.conf dinámico
↓
NGINX worker processes
↓
Service / Pod
La complejidad real depende del controller. Por eso, cuando hay problemas, no alcanza con mirar solo el recurso
Ingress: también hay que revisar eventos, logs del controller y documentación específica de la implementación.
Cómo se reconcilia Gateway API
Con Gateway API, el flujo de control queda más separado:
Se instalan los CRDs
↓
Se instala una implementación de Gateway API
↓
Se crea GatewayClass
↓
El equipo de plataforma crea Gateway
↓
Los equipos crean HTTPRoute, GRPCRoute o TLSRoute
↓
El controller valida allowedRoutes, parentRefs, hostnames, ReferenceGrant y backendRefs
↓
El controller programa el dataplane
↓
El dataplane enruta tráfico real
Gateway API también tiene conformance tests para verificar que las implementaciones respeten la especificación.
Las features se suelen separar en:
- Core: pensadas para portabilidad amplia;
- Extended: portables, pero no necesariamente soportadas por todas las implementaciones;
- Implementation-specific: propias de cada implementación.
Esto es clave para producción. Gateway API da una API común y un modelo de conformance más formal, pero no significa que todas las implementaciones soporten exactamente lo mismo.
El recorrido real de una request
Cómo viaja una request con Ingress
Ejemplo:
curl https://app.example.com/api/users
Flujo:
- DNS resuelve
app.example.coma una IP pública, VIP o LoadBalancer. - El tráfico llega al Ingress Controller.
- El controller o proxy termina TLS, si corresponde.
- El proxy mira
Host: app.example.com. - El proxy mira el path
/api/users. - Busca la regla Ingress correspondiente.
- Envía la request al Service.
- El Service balancea hacia Pods usando endpoints.
La regla Ingress podría verse así:
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
Cómo viaja una request con Gateway API
Ejemplo:
curl https://app.example.com/api/users
Flujo:
- DNS resuelve
app.example.coma la IP o dirección del Gateway. - El tráfico llega al dataplane del Gateway.
- Se selecciona un listener del Gateway: HTTPS, puerto 443,
app.example.com. - El listener termina TLS usando el Secret configurado.
- Se buscan
HTTPRoutesadjuntas a ese listener. - Se evalúa el hostname
app.example.com. - Se evalúan las reglas: path, headers, query params o method.
- Se aplican filters, si existen.
- Se selecciona el
backendRef. - El tráfico va al Service.
- El Service envía la request a los Pods.
Ejemplo:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: public-gateway
namespace: gateway-system
spec:
gatewayClassName: envoy-gateway
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: app.example.com
tls:
mode: Terminate
certificateRefs:
- name: app-tls
allowedRoutes:
namespaces:
from: All
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-route
namespace: apps
spec:
parentRefs:
- name: public-gateway
namespace: gateway-system
sectionName: https
hostnames:
- app.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-service
port: 80
La diferencia importante es que el entrypoint está modelado en el Gateway, no escondido dentro del controller.
La diferencia de fondo: simpleza contra modelo de plataforma
Un solo objeto contra un modelo distribuido
En Ingress, muchas cosas viven en un solo recurso:
Ingress = entrada + reglas + TLS + backend
En Gateway API, el modelo se divide:
GatewayClass = implementación
Gateway = infraestructura de entrada
Listener = puerto/protocolo/hostname/TLS
Route = reglas de tráfico
BackendRef = destino
Policy = comportamiento adicional
Esta separación no es solo una cuestión de estilo. Tiene sentido cuando el clúster deja de ser de una sola app o de un solo equipo.
Gateway API está pensado para que distintas personas o equipos puedan administrar partes distintas del problema: infraestructura, plataforma y aplicaciones.
Desarrolladores, plataforma y responsabilidades mejor separadas
Con Ingress, un desarrollador suele crear el recurso completo:
kind: Ingress
metadata:
name: app
spec:
ingressClassName: nginx
tls:
...
rules:
...
En Gateway API, el equipo de plataforma puede crear esto:
kind: Gateway
metadata:
name: public-gateway
namespace: gateway-system
spec:
listeners:
...
Y el equipo de aplicación crea solamente la route:
kind: HTTPRoute
metadata:
name: app-route
namespace: apps
spec:
parentRefs:
- name: public-gateway
namespace: gateway-system
rules:
...
Ese modelo permite repartir responsabilidades de una forma más sana.
El equipo de plataforma puede controlar:
- IPs;
- listeners;
- TLS;
allowedRoutes;- clases de gateway;
- políticas globales.
Los equipos de aplicaciones pueden controlar:
- hostnames permitidos;
- paths;
- backends;
- pesos;
- filtros de aplicación.
Para plataformas compartidas, esta separación es una de las razones más fuertes para mirar Gateway API.
Cómo cambia la implementación en la práctica
Implementar Ingress en un clúster
Para implementar Ingress, normalmente hacés algo así:
- Instalás un Ingress Controller.
- Exponés el controller con
ServicetipoLoadBalancer,NodePort,hostNetworkoDaemonSet. - Creás un
IngressClass. - Creás un Ingress por aplicación.
- Configurás DNS hacia el LB o VIP.
- Configurás
cert-managero Secrets TLS.
En un escenario on-prem, el modelo mental podría ser:
Internet
↓
HAProxy / Keepalived VIP
↓
NodePort / LoadBalancer con MetalLB
↓
NGINX Ingress Controller
↓
Ingress
↓
Service
↓
Pod
Implementar Gateway API en un clúster
Para implementar Gateway API, el flujo típico sería:
- Instalás los CRDs de Gateway API.
- Instalás una implementación: Envoy Gateway, Kong, Traefik, Cilium, etc.
- Confirmás que exista un
GatewayClass. - Creás un
Gatewaycon listeners. - Creás
HTTPRoutes,GRPCRoutesoTLSRoutes. - Configurás
ReferenceGrantsi hay referencias cross-namespace. - Configurás DNS hacia la IP o dirección del Gateway.
- Validás el status de
Gateway, listeners y Routes.
En on-prem, el flujo podría ser:
Internet
↓
HAProxy / Keepalived VIP
↓
MetalLB LoadBalancer IP del Gateway dataplane
↓
Gateway implementation dataplane: Envoy / Kong / Traefik / etc.
↓
Gateway + HTTPRoute
↓
Service
↓
Pod
Otra variante posible:
Internet
↓
HAProxy SNI/TCP routing
↓
Gateway dataplane por cluster
↓
HTTPRoute / TLSRoute
↓
Service / Pod
Para una arquitectura con HAProxy, Keepalived y MetalLB, Gateway API no elimina necesariamente HAProxy del edge.
Puede reemplazar o complementar al Ingress Controller dentro del clúster. El diseño correcto depende de dónde querés terminar TLS:
- en HAProxy;
- en el Gateway;
- en la aplicación.
TLS: una diferencia importante entre ambos modelos
TLS en Ingress
En Ingress, TLS vive en spec.tls:
spec:
tls:
- hosts:
- app.example.com
secretName: app-tls
Es simple y funciona bien para casos básicos.
Pero la lógica avanzada —redirect HTTP a HTTPS, TLS passthrough, mTLS, selección avanzada de certificados— suele depender del controller y de sus annotations.
TLS en Gateway API
En Gateway API, TLS vive en el listener:
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: app.example.com
tls:
mode: Terminate
certificateRefs:
- name: app-tls
Esto es más claro cuando pensás en una plataforma.
Un listener HTTPS define:
- hostname;
- puerto;
- protocolo;
- certificado;
- modo TLS;
- routes permitidas.
En vez de repartir la intención entre Ingress, spec.tls y annotations específicas, Gateway API ubica esa
configuración en el punto de entrada.
También existe BackendTLSPolicy, que sirve para describir cómo el Gateway se conecta por TLS hacia un backend. Esto es
útil cuando no querés solamente TLS en el borde, sino también TLS desde el dataplane hacia los servicios internos.
Routing: de reglas simples a decisiones más avanzadas
Routing en Ingress
Ingress rutea principalmente por:
- host;
- path;
pathType.
Los pathType principales son:
Exact;Prefix;ImplementationSpecific.
ImplementationSpecific deja el matching en manos de la clase o del controller.
Routing en Gateway API
HTTPRoute puede rutear por:
- hostname;
- path;
- headers;
- query params;
- método HTTP;
- weights;
- filters;
- timeouts;
backendRefs.
Ejemplo de canary:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-canary
namespace: apps
spec:
parentRefs:
- name: public-gateway
namespace: gateway-system
hostnames:
- app.example.com
rules:
- backendRefs:
- name: app-v1
port: 80
weight: 90
- name: app-v2
port: 80
weight: 10
En Ingress, algo parecido normalmente se resolvería con annotations o con recursos propios del controller.
Extensibilidad: annotations contra APIs estructuradas
Cómo se extendió Ingress
Ingress se extendió principalmente con annotations:
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/rewrite-target: /
El problema es bastante directo:
- esas annotations son del controller;
- no son portables;
- no están tipadas como parte de
spec; - no todas las implementaciones tienen equivalentes.
Por eso, migrar de un Ingress Controller a otro puede ser difícil si tu configuración depende mucho de annotations específicas.
Cómo se extiende Gateway API
Gateway API usa mecanismos más estructurados:
- campos dentro de
spec; - filters;
extensionRef;BackendObjectReference;SecretObjectReference;- policies;
- custom resources de implementación.
Esto no elimina toda configuración específica de implementación. Eso sería poco realista.
Pero sí ordena mejor el modelo: lo estándar va a campos estándar; lo extendido puede ir a filters o policies; lo específico queda más delimitado.
Seguridad y multitenancy: donde Gateway API empieza a brillar
Seguridad y aislamiento con Ingress
Con Ingress, si un equipo puede crear recursos Ingress en su namespace, puede intentar declarar hosts, paths, TLS,
annotations, etc.
El control fino suele depender de varias capas externas:
- controller;
- admission policies;
- validaciones externas;
- convenciones internas;
- RBAC;
- políticas del clúster.
Se puede operar así, pero no es el modelo más cómodo cuando varias aplicaciones o equipos comparten infraestructura de entrada.
Seguridad y control de acceso con Gateway API
Gateway API trae controles nativos más claros.
allowedRoutes: quién puede adjuntarse a un Gateway
En el listener:
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
shared-gateway-access: "true"
Esto permite que el dueño del Gateway controle qué namespaces pueden adjuntar routes.
parentRefs: a qué Gateway quiere conectarse una Route
En la route:
parentRefs:
- name: public-gateway
namespace: gateway-system
sectionName: https
La route declara a qué Gateway y a qué listener quiere adjuntarse.
ReferenceGrant: permisos explícitos entre namespaces
El namespace dueño del recurso referenciado debe autorizar referencias cross-namespace.
Sin ReferenceGrant, la referencia cross-namespace es inválida.
El modelo queda más claro:
La app pide adjuntarse.
El Gateway decide si acepta.
El backend o Secret remoto decide si puede ser referenciado.
Eso encaja mejor con plataformas multi-team.
Conflictos de rutas: qué pasa cuando varios equipos comparten entrada
En Ingress, muchos controllers mergean reglas de múltiples recursos Ingress, pero la API no define con el mismo nivel
de detalle cómo resolver todos los conflictos.
Ejemplo:
Dos equipos publican rutas en el mismo dominio.
Uno declara /api.
Otro declara /api/v1.
Otro declara el mismo host con otra configuración TLS.
¿Quién gana?
Con Ingress, muchas veces la respuesta depende del controller.
Gateway API intenta que esto sea más determinista. La implementación debe mergear las reglas de los HTTPRoutes
adjuntos a un listener y manejar conflictos siguiendo las reglas de diseño de la API, por ejemplo priorizando matches
más específicos.
Esto importa mucho cuando varias aplicaciones comparten el mismo Gateway.
Troubleshooting: cómo diagnosticar problemas en cada modelo
Diagnosticar problemas con Ingress
Con Ingress, normalmente revisás:
kubectl describe ingress app -n apps
kubectl get ingress app -n apps
kubectl logs deploy/ingress-nginx-controller -n ingress-nginx
kubectl describe svc app-service -n apps
kubectl get endpointslice -n apps
El status puede mostrar la dirección asignada, pero muchos errores reales terminan apareciendo en eventos o logs del controller.
Diagnosticar problemas con Gateway API
Con Gateway API tenés más niveles de status:
kubectl get gateway -A
kubectl describe gateway public-gateway -n gateway-system
kubectl get httproute -A
kubectl describe httproute app-route -n apps
Conviene revisar:
Gateway.status.conditions;Gateway.status.addresses;- listener status;
attachedRoutes;HTTPRoute.status.parents;Accepted;ResolvedRefs;Programmed.
Este modelo ayuda a separar mejor los problemas.
| Síntoma | Posible causa |
|---|---|
| Gateway no tiene address | El controller no pudo programar LB/IP |
| Listener no está listo | Conflicto de listener, Secret TLS faltante o protocolo no soportado |
attachedRoutes = 0 | Problema con allowedRoutes, namespace, hostname o parentRef |
Accepted=False | La route no fue aceptada por el listener |
ResolvedRefs=False | Backend o Secret inválido, o referencia cross-namespace sin ReferenceGrant |
| 404/503 en dataplane | Match incorrecto, backend sin endpoints o Service mal configurado |
Cuándo conviene seguir usando Ingress
Usaría Ingress cuando:
- ya tenés un Ingress Controller estable funcionando;
- tus reglas son simples: host, path y TLS;
- no necesitás un modelo multi-team avanzado;
- no querés introducir CRDs y controllers nuevos;
- tenés mucha configuración legacy basada en annotations;
- la operación actual ya está madura y no hay presión de migración.
Ejemplo típico:
Una app interna.
Un dominio.
TLS simple.
Un backend.
NGINX Ingress funcionando bien.
En ese escenario, Ingress sigue siendo una opción válida.
Cuándo conviene empezar a usar Gateway API
Usaría Gateway API cuando:
- estás diseñando una plataforma Kubernetes más moderna;
- querés separar responsabilidades entre plataforma y aplicaciones;
- querés compartir gateways entre namespaces o equipos;
- necesitás routing más avanzado;
- querés reducir dependencia de annotations;
- querés acercarte al estándar moderno de networking en Kubernetes;
- estás evaluando Envoy, Kong, Cilium, Traefik o NGINX Gateway Fabric;
- querés un modelo más claro para TLS, listeners y attachment.
Ejemplo típico:
Cluster productivo con varios equipos.
Un gateway público compartido.
Gateways internos por ambiente.
TLS controlado por plataforma.
Routes autogestionadas por equipos.
Canary o weighted routing.
Políticas de seguridad.
Ahí Gateway API empieza a tener mucho más sentido.
18. Resumen final
| Dimensión | Ingress | Gateway API |
|---|---|---|
| Futuro | Estable, pero congelado | Evolución moderna del networking Kubernetes |
| Tipo de API | Built-in Kubernetes API | CRDs oficiales del proyecto Gateway API |
| Recurso principal | Ingress | GatewayClass, Gateway, Route, policies |
| Entry points | Implícitos por controller | Explícitos con listeners |
| Routing HTTP | Básico | Avanzado |
| TLS | En spec.tls del Ingress | En listener del Gateway |
| Canary / weights | Usualmente annotations | backendRefs.weight |
| Headers/query/method matching | Usualmente annotations o controller-specific | Parte de HTTPRoute |
| Multi-namespace | Limitado | allowedRoutes + ReferenceGrant |
| Multi-team | Débil | Diseñado para eso |
| Portabilidad | Buena solo con features básicas | Mejor en Core/Extended; lo implementation-specific sigue existiendo |
| Extensibilidad | Annotations | Filters, policies, extensionRefs |
| Troubleshooting | Muy dependiente del controller | Status más estructurado por Gateway, listener y Route |
| Migración | Muy usado en entornos legacy | Mejor punto de partida para nuevos diseños |
La idea que me queda es esta:
Ingress publica aplicaciones; Gateway API modela una plataforma de entrada de tráfico.
Para un clúster simple, Ingress todavía puede ser suficiente.
Para una plataforma productiva con varios equipos, varios namespaces, TLS serio, tráfico compartido, routing avanzado y una arquitectura más preparada para crecer, Gateway API ofrece un modelo más claro.