Envoy Gateway 多 Namespace 與團隊分工:allowedRoutes、ReferenceGrant、跨團隊怎麼管

6 min read

Gateway API 很大的價值,不只是 YAML 比較漂亮,而是它終於把一件老問題講清楚:

入口層誰負責?路由誰能改?跨 namespace 到底能不能互相引用?

以前很多 Ingress 場景的痛點,就是所有事情都揉在一起。
平台團隊怕你亂開洞,應用團隊又覺得每改一條 path 都要提單,最後大家一起在 YAML 裡互相折磨。

Gateway API 比較像是直接說:

  • 平台入口可以獨立治理
  • Route 可以分給應用團隊管理
  • 跨 namespace 行為要明確授權

這篇就是把這套分工邏輯一次講懂。

先記這個原則:附掛跟引用,是兩件不同的事

這是最容易搞混的地方。

Route 附掛到 Gateway / Listener

這件事主要看:

  • Route 的 parentRefs
  • Listener 的 allowedRoutes

也就是說,route 能不能掛上某個 listener,不是靠 ReferenceGrant,而是看 listener 願不願意收你。

跨 namespace 引用其他資源

這件事才常需要 ReferenceGrant
例如:

  • Gateway 想引用別的 namespace 裡的 Secret
  • HTTPRoute 想引用別的 namespace 裡的 Service

這時候就不是「能不能附掛」的問題,而是「目標 namespace 有沒有正式授權你引用它的資源」。

很多人把這兩件事混成一團,然後就開始懷疑人生。其實規則沒有很玄,只是角色不同。

allowedRoutes:先決定誰可以掛上來

最保守的 listener 長這樣:

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

這表示只有 infra namespace 裡的 route 可以掛到這個 listener。

如果你想讓特定團隊 namespace 能附掛,可以用 Selector

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

這種做法很適合平台團隊。
你不需要把入口完全鎖死,也不用直接開成 from: All 全場自由進出。你可以只讓貼上特定 label 的 namespace 有資格附掛。

💡 allowedRoutes 是 listener 級別,不是整個 Gateway 一刀切。這代表你可以讓不同 listener 有不同開放策略。

ReferenceGrant:目標 namespace 說了算

如果 route 或 gateway 要引用別的 namespace 裡的資源,就要看目標 namespace 願不願意授權。

例如應用團隊的 HTTPRoute 想把流量送到共享 namespace 裡的 backend:

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

這時 shared-services namespace 要建立 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

翻成人話就是:

  • team-aHTTPRoute
  • 可以引用 shared-services 裡的 Service

注意這個授權是 目標 namespace 自己開
不是來源 namespace 想用就能自己宣告,這點設計得其實很合理,因為資源的主人應該有決定權。

平台團隊與應用團隊,常見怎麼分

最常見的分工模型大概長這樣:

平台團隊負責

  • GatewayClass
  • Gateway
  • Listener
  • TLS 憑證管理
  • allowedRoutes 政策

應用團隊負責

  • 自己 namespace 裡的 HTTPRoute / GRPCRoute
  • backend service
  • 路由規則調整

這種分法的好處很明顯:

  • 平台團隊守住入口暴露面與安全邊界
  • 應用團隊還是能快速調整自己的流量規則
  • 不需要每次改 path 都碰整個共享 Gateway

如果你把所有權限都丟給同一群人,當然也不是不能跑。
只是團隊一大,這種模式通常會演變成「誰都能改,所以誰改壞了也很難查」。

實戰建議:怎麼避免多租戶場景翻車

幾個非常實用的習慣:

  • 共享 Gateway 預設先用 allowedRoutes.namespaces.from: Selector
  • namespace label 規則要固定,不要今天 team-a 明天 allow-gw
  • 跨 namespace backend/Secret 引用一律走 ReferenceGrant
  • route 命名要能看出團隊或服務,例如 team-a-api-route
  • 共享 listener 盡量搭配 sectionName,避免 route 掛錯入口

還有一個心法很值得記:

能在入口邊界先限制,就不要把規矩全丟給文件靠大家自律。

工程世界裡,制度比口頭約定可靠很多。這句話聽起來像長輩,但真的很有用。

一句話總結

在 Gateway API 裡,allowedRoutes 是「誰能進門」,ReferenceGrant 是「進門後能不能拿別人的東西」。
把這兩件事分清楚,多 namespace 與多團隊場景就會順很多。

下一步

分工和權限搞定後,最後一塊就是:
設定沒生效時,到底該看哪個 status、哪個 condition、哪個指令?

下一篇來講除錯與狀態判讀: 👉 狀態與除錯手冊