Cuando varios equipos deben publicar aplicaciones HTTP desde un mismo clúster, el modelo de Ingress puede resultar limitado: normalmente concentra la infraestructura y las reglas de enrutamiento en recursos administrados por un mismo responsable.
Gateway API amplía este modelo mediante recursos con responsabilidades diferenciadas:
GatewayClass: identifica la implementación o clase de infraestructura disponible en el clúster.Gateway: define listeners, puertos, protocolos y qué rutas pueden asociarse.HTTPRoute: contiene las reglas de una aplicación, como hostname, path y backend.Service: distribuye el tráfico hacia los Pods de la aplicación.
Esta separación permite que el equipo de infraestructura controle el punto de entrada mientras cada equipo de desarrollo administra sus propias rutas. Además, la asociación entre un Gateway y una ruta puede atravesar namespaces mediante una autorización explícita de ambas partes. Documentación oficial sobre enrutamiento entre namespaces.
¿Cuándo conviene utilizar Gateway API?
Gateway API resulta especialmente útil cuando se necesita:
- Compartir una misma dirección IP o balanceador entre varios equipos.
- Separar la administración de red del despliegue de aplicaciones.
- Enrutar tráfico por hostname, path, encabezados o método HTTP.
- Distribuir solicitudes entre distintas versiones mediante pesos.
- Centralizar listeners y certificados TLS.
- Migrar gradualmente desde Ingress por dominio o aplicación.
La disponibilidad de filtros, políticas y funciones avanzadas depende del controlador. Antes de diseñar una ruta, comprueba la matriz de compatibilidad de la implementación elegida.
Arquitectura del ejemplo
El procedimiento utilizará dos namespaces:
infra-ns: contiene el Gateway administrado por infraestructura.app-ns: contiene elHTTPRoute, el Service y los Pods de la aplicación.
El flujo de tráfico será:
Cliente → Gateway → HTTPRoute → Service → Pods
GatewayClass no se encuentra en el flujo de datos: es el recurso de ámbito de clúster que indica qué controlador debe gestionar el Gateway.
Ver la Imagen 1: arquitectura compartida entre namespaces.
Requisitos previos
Antes de comenzar, verifica que dispones de:
- Un clúster Kubernetes operativo.
- Los CRD de Gateway API instalados.
- Un controlador compatible, como NGINX Gateway Fabric, Envoy Gateway o Istio.
kubectlconfigurado con permisos para consultar y crear los recursos utilizados.- Un Service llamado
apienapp-ns, escuchando en el puerto8080. - Un mecanismo para asignar una dirección externa al Gateway.
El DNS todavía no es obligatorio: primero se debe obtener y probar la dirección publicada por el Gateway. Después podrá crearse el registro para api.ejemplo.com.
Paso 1. Verificar los CRD y el controlador
Comprueba que estén disponibles los recursos utilizados por la guía:
kubectl get crd gatewayclasses.gateway.networking.k8s.io
kubectl get crd gateways.gateway.networking.k8s.io
kubectl get crd httproutes.gateway.networking.k8s.ioLuego consulta las clases existentes:
kubectl get gatewayclass
kubectl describe gatewayclass NOMBRE_DE_LA_CLASELa GatewayClass elegida debe existir y mostrar la condición Accepted=True. El nombre depende del controlador y de cómo fue instalado; no debe asumirse que siempre será nginx.
También puedes comprobar los permisos actuales:
kubectl auth can-i create gateways.gateway.networking.k8s.io -n infra-ns
kubectl auth can-i create httproutes.gateway.networking.k8s.io -n app-nsSi no aparece ninguna GatewayClass, instalar únicamente los CRD no será suficiente: también se necesita un controlador que observe y materialice la configuración.
Paso 2. Crear y autorizar los namespaces
Crea un archivo namespaces.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: infra-ns
---
apiVersion: v1
kind: Namespace
metadata:
name: app-ns
labels:
shared-gateway-access: "true"Aplícalo:
kubectl apply -f namespaces.yamlLa etiqueta de app-ns será utilizada por allowedRoutes. Así, solo los namespaces autorizados podrán asociar rutas al Gateway compartido.
Paso 3. Configurar el Gateway compartido
Crea gateway.yaml y reemplaza nombre-de-la-clase por una GatewayClass real obtenida en el paso anterior:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: web-gateway
namespace: infra-ns
spec:
gatewayClassName: nombre-de-la-clase
listeners:
- name: http
hostname: api.ejemplo.com
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
shared-gateway-access: "true"
kinds:
- group: gateway.networking.k8s.io
kind: HTTPRouteEl listener acepta únicamente rutas HTTP procedentes de namespaces que tengan la etiqueta indicada. Además, el hostname del HTTPRoute deberá intersectar con api.ejemplo.com para que la asociación sea válida. Documentación oficial sobre hostnames.
Valida el manifiesto en el API server antes de aplicarlo:
kubectl apply --dry-run=server -f gateway.yaml
kubectl diff -f gateway.yamlkubectl diff puede finalizar con código 1 cuando encuentra diferencias; esto no significa necesariamente que el manifiesto sea inválido.
Si la configuración es correcta:
kubectl apply -f gateway.yamlPaso 4. Comprobar el backend antes de publicar la ruta
Verifica que el Service exista en el mismo namespace donde se creará el HTTPRoute:
kubectl get service api -n app-ns
kubectl get endpointslice -n app-ns \
-l kubernetes.io/service-name=apiEl puerto declarado en backendRefs debe coincidir con spec.ports[].port del Service, no necesariamente con el containerPort del Pod.
Si no aparecen endpoints, revisa los selectores del Service, el estado de los Pods y sus readiness probes antes de continuar.
Paso 5. Publicar la ruta de la aplicación
Crea httproute.yaml:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api
namespace: app-ns
spec:
parentRefs:
- name: web-gateway
namespace: infra-ns
sectionName: http
hostnames:
- api.ejemplo.com
rules:
- backendRefs:
- name: api
port: 8080Los campos namespace y sectionName evitan ambigüedades: la ruta apunta al Gateway de infra-ns y específicamente al listener http.
No se necesita un ReferenceGrant para esta asociación. El acceso de una ruta a un Gateway de otro namespace se controla mediante parentRefs y allowedRoutes. ReferenceGrant se utiliza para otras referencias entre namespaces, por ejemplo cuando un HTTPRoute intenta usar un Service ubicado en un namespace diferente.
Valida y aplica la ruta:
kubectl apply --dry-run=server -f httproute.yaml
kubectl diff -f httproute.yaml
kubectl apply -f httproute.yamlGateway API permite que varias rutas se asocien a un mismo Gateway siempre que cumplan las restricciones del listener y no generen conflictos. Guía oficial de enrutamiento HTTP.
Paso 6. Verificar las condiciones
Empieza por el estado declarado en los recursos, antes de revisar logs:
kubectl describe gateway web-gateway -n infra-ns
kubectl describe httproute api -n app-nsTambién puedes inspeccionar el estado completo:
kubectl get gateway web-gateway -n infra-ns -o yaml
kubectl get httproute api -n app-ns -o yamlComprueba principalmente:
- Gateway:
Accepted=TrueyProgrammed=True. - HTTPRoute:
Accepted=TrueyResolvedRefs=True. observedGeneration: debe coincidir con la generación actual del recurso.
Accepted=True no garantiza por sí solo que el backend exista. Una ruta puede ser aceptada y mostrar ResolvedRefs=False si el Service no se encuentra o la referencia no está permitida. Programmed=True indica que la configuración fue enviada al plano de datos, aunque la disponibilidad final todavía debe probarse con una solicitud. Guía oficial de estado y diagnóstico.
Ver la Imagen 2: secuencia de configuración, validación, aplicación y comprobación.
Paso 7. Obtener la dirección y probar el tráfico
Consulta la dirección publicada por el Gateway:
kubectl get gateway web-gateway -n infra-ns -o wide
kubectl get gateway web-gateway -n infra-ns \
-o jsonpath='{range .status.addresses[*]}{.value}{"\n"}{end}'Si el proveedor entrega una dirección IP, prueba el enrutamiento antes de modificar el DNS:
curl --resolve api.ejemplo.com:80:IP_DEL_GATEWAY \
http://api.ejemplo.com/healthTambién puede utilizarse directamente el encabezado Host:
curl -H 'Host: api.ejemplo.com' \
http://IP_DEL_GATEWAY/healthUna respuesta válida confirma el recorrido Gateway → HTTPRoute → Service → Pod. Finalmente, crea o actualiza el registro DNS de api.ejemplo.com y verificalo:
dig +short api.ejemplo.com
curl -i http://api.ejemplo.com/healthTen en cuenta el TTL del registro: una respuesta DNS antigua puede deberse a caché y no a Kubernetes.
Distribución de tráfico por peso
Para una migración progresiva, una regla puede repartir solicitudes entre dos Services del mismo namespace:
rules:
- backendRefs:
- name: api-v1
port: 8080
weight: 90
- name: api-v2
port: 8080
weight: 10Los pesos expresan una proporción, no una garantía exacta para una cantidad pequeña de solicitudes. Verifica además que el controlador declare soporte para esta funcionalidad.
Seguridad y uso en producción
El listener HTTP del ejemplo simplifica las primeras pruebas. Para una publicación real, utiliza HTTPS y almacena el certificado como Secret en infra-ns:
listeners:
- name: https
hostname: api.ejemplo.com
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: api-ejemplo-tlsAdemás:
- Limita
allowedRoutesmediante selectores de namespace. - Aplica RBAC separado para Gateways y rutas.
- No incluyas claves privadas ni credenciales dentro de manifiestos versionados.
- Separa hostnames de producción, pruebas y desarrollo.
- Revisa las funciones compatibles y el nivel de conformidad del controlador.
- Versiona los manifiestos y revisa
kubectl diffantes de aplicarlos. - Migra desde Ingress por dominio o aplicación y conserva un procedimiento de reversión.
- Supervisa condiciones, direcciones, errores HTTP y disponibilidad de endpoints.
Problemas frecuentes
El HTTPRoute no muestra estado
Comprueba que parentRefs apunte a un Gateway existente y gestionado por el controlador. Una referencia a un padre inexistente puede dejar la ruta sin condiciones porque ningún controlador la considera dentro de su ámbito.
Accepted=False
Revisa:
- El namespace indicado en
parentRefs. - El nombre y
sectionNamedel listener. - La etiqueta requerida por
allowedRoutes. - La intersección entre el hostname del listener y el de la ruta.
- Los eventos mostrados por
kubectl describe.
ResolvedRefs=False
Verifica que el Service exista en el namespace del HTTPRoute, que el puerto sea correcto y que cualquier referencia entre namespaces cuente con el ReferenceGrant correspondiente.
El Gateway no tiene dirección
Comprueba GatewayClass, Accepted, Programmed y los eventos del Gateway. Algunos controladores requieren configuración adicional del proveedor o no crean automáticamente un balanceador externo.
El DNS resuelve, pero la aplicación no responde
Prueba primero con curl --resolve, revisa el listener y confirma que el Service tenga EndpointSlices listos. Un error de ruta, un backend sin endpoints y una aplicación que falla su health check requieren diagnósticos diferentes.
Conclusión
Gateway API permite compartir infraestructura de entrada sin entregar a todos los equipos control sobre el mismo recurso. El Gateway establece puertos, protocolos, dominios y límites de asociación; cada HTTPRoute declara cómo debe publicarse una aplicación.
La implementación resulta más segura y predecible cuando se sigue siempre la misma secuencia: configurar → validar → aplicar → comprobar.
