Envoy Gateway Multi-Namespace y Propiedad de Equipos: allowedRoutes, ReferenceGrant y Gobernanza entre Equipos

5 min read

Uno de los mayores valores de Gateway API no es solo un YAML más bonito — finalmente responde con claridad una pregunta que llevaba mucho tiempo sin respuesta:

¿Quién es dueño de la capa de ingreso? ¿Quién puede cambiar rutas? ¿Pueden los namespaces hacer referencias cruzadas entre sí?

Muchos de los problemas de Ingress venían de que todo estaba enredado. Los equipos de plataforma temían cambios de exposición no autorizados. Los equipos de aplicación sentían que tenían que abrir un ticket solo para cambiar un path. Todos terminaban torturándose mutuamente con YAML.

El enfoque de Gateway API es decir claramente:

  • El ingreso de plataforma puede gobernarse de forma independiente
  • Las rutas pueden delegarse a los equipos de aplicación
  • El comportamiento entre namespaces requiere autorización explícita

Este artículo explica ese modelo de propiedad de arriba a abajo.

Empezar aquí: Adjunción y Referencia son dos cosas distintas

Esta es la confusión más común.

Adjunción de Route a Gateway / Listener

Esto está gobernado por:

  • El parentRefs de la ruta
  • El allowedRoutes del listener

En otras palabras, si una ruta puede adjuntarse a un listener no lo determina ReferenceGrant — lo determina si el listener está dispuesto a aceptarla.

Referencias de recursos entre namespaces

Aquí es donde ReferenceGrant suele entrar en juego. Por ejemplo:

  • Un Gateway quiere referenciar un Secret en otro namespace
  • Un HTTPRoute quiere referenciar un Service en otro namespace

Esto no es una cuestión de adjunción — es "¿ha autorizado formalmente el namespace de destino que uses sus recursos?"

Muchas personas mezclan ambos conceptos y empiezan a cuestionarse su cordura. Las reglas no son tan misteriosas una vez que se separan los roles.

allowedRoutes: Decide quién puede adjuntarse primero

El listener más restrictivo tiene este aspecto:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: shared-gateway
  namespace: infra
spec:
  gatewayClassName: eg
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      allowedRoutes:
        namespaces:
          from: Same

Esto significa que solo las rutas en el namespace infra pueden adjuntarse a este listener.

Para permitir que namespaces de equipos específicos se adjunten, usa Selector:

allowedRoutes:
  namespaces:
    from: Selector
    selector:
      matchLabels:
        shared-gateway-access: "true"

Este patrón funciona muy bien para los equipos de plataforma. No tienes que bloquear todo completamente, pero tampoco tienes que abrirlo con from: All y dejar entrar a todos sin restricción. Puedes exigir que los namespaces se ganen el derecho de adjuntarse llevando una etiqueta específica.

💡 allowedRoutes es por listener, no por Gateway. Distintos listeners pueden tener diferentes políticas de acceso.

ReferenceGrant: El namespace de destino decide

Si una ruta o un gateway quiere referenciar recursos en otro namespace, el namespace de destino tiene que autorizarlo.

Por ejemplo, el HTTPRoute de un equipo de aplicación quiere enviar tráfico a un backend en un namespace compartido:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app-route
  namespace: team-a
spec:
  parentRefs:
    - name: shared-gateway
      namespace: infra
      sectionName: https
  rules:
    - backendRefs:
        - name: shared-api
          namespace: shared-services
          port: 8080

El namespace shared-services necesitaría un ReferenceGrant:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-team-a-route
  namespace: shared-services
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: team-a
  to:
    - group: ""
      kind: Service

En términos simples:

  • Los recursos HTTPRoute en team-a
  • Están autorizados a referenciar recursos Service en shared-services

Nótese que la autorización es creada por el namespace de destino, no por el origen. El origen no puede simplemente declarar que quiere acceso — el propietario del recurso decide. Este diseño es bastante principista, porque los propietarios deberían controlar quién accede a sus recursos.

División común entre equipos de plataforma y aplicación

El modelo de propiedad más común tiene este aspecto:

El equipo de plataforma posee

  • GatewayClass
  • Gateway
  • Listener
  • Gestión de certificados TLS
  • Políticas de allowedRoutes

Los equipos de aplicación poseen

  • HTTPRoute / GRPCRoute en sus propios namespaces
  • Servicios de backend
  • Ajustes de reglas de enrutamiento

Los beneficios de esta división son claros:

  • El equipo de plataforma protege la exposición de ingreso y el perímetro de seguridad
  • Los equipos de aplicación pueden seguir moviéndose rápido con sus propias reglas de tráfico
  • Nadie necesita tocar el Gateway compartido solo para cambiar un path

También puedes dar todos los permisos a un solo grupo — eso no está mal. Pero en equipos más grandes, ese modelo tiende a evolucionar hacia "cualquiera puede cambiarlo, así que cuando se rompe nadie sabe quién hizo qué."

Consejos prácticos: Cómo evitar desastres multi-tenant

Hábitos genuinamente útiles:

  • Los Gateways compartidos usan por defecto allowedRoutes.namespaces.from: Selector
  • Las convenciones de etiquetas de namespace deben ser estables — no cambies team-a a allow-gw el mes que viene
  • Todas las referencias cross-namespace a backends o Secrets pasan por ReferenceGrant
  • Los nombres de las rutas deben indicar el equipo o servicio — por ejemplo, team-a-api-route
  • Los listeners compartidos deben usar siempre sectionName para evitar que las rutas se adjunten a la entrada equivocada

Un principio que vale la pena mantener:

Si puedes hacer cumplir un límite en la capa de ingreso, no te apoyes en la documentación y en esperar que las personas se autogestionen.

En ingeniería, el proceso supera al acuerdo verbal. Eso suena como un consejo de alguien mucho mayor, pero es genuinamente útil.

Resumen en una línea

En Gateway API, allowedRoutes controla "quién puede entrar", y ReferenceGrant controla "a qué pueden acceder una vez dentro." Mantén esos dos conceptos claros y los escenarios multi-namespace y multi-equipo se vuelven mucho más manejables.

Siguiente paso

Con la propiedad y los permisos resueltos, la pieza final es: Cuando la configuración no surte efecto, ¿qué status, qué condition y qué comando miras primero?

El próximo artículo cubre el debugging e interpretación de status: 👉 Manual de Status y Debugging