Envoy Gateway 狀態與除錯手冊:Accepted、ResolvedRefs、Programmed 到底在說什麼

7 min read

工程師最怕的不是報錯,而是:

YAML 套上去了,kubectl apply 也成功了,但流量就是沒通。

這時候如果你只盯著 spec 看,很容易越看越像在占卜。
Gateway API 真正的救命資訊,很多都在 status 裡。

這篇的目標很簡單:幫你建立一套最短除錯路徑。讓你遇到 GatewayHTTPRouteListener 不生效時,知道先看哪裡,而不是一開場就懷疑宇宙。

先記住:除錯先看 status,不是先改 YAML

最常用的幾個指令:

kubectl get gateway -A
kubectl get httproute -A
kubectl get grpcroute -A
kubectl describe gateway <name>
kubectl describe httproute <name>
kubectl get gateway <name> -o yaml
kubectl get httproute <name> -o yaml

重點不是把 YAML 再讀一百遍,而是看 controller 有沒有真的接受你的設定。

你可以把 status 想成考試成績單:

  • spec 是你交上去的答案
  • status 是系統批改後的結果

只看交卷內容,不看成績,很多時候真的只是心靈安慰。

三個最常見的 condition:先看懂這些就夠用了

Accepted

這通常表示資源有沒有被父層接納。
以 route 來說,意思通常接近:

  • 有沒有成功附掛到對應 Gateway / listener
  • 規則本身有沒有明顯衝突或不合法

如果 AcceptedFalse,先懷疑:

  • parentRefs 指錯 Gateway 或 listener
  • hostname / listener 條件不匹配
  • 該 listener 不接受這種 route 類型
  • allowedRoutes 把你擋掉了

ResolvedRefs

這表示資源裡引用到的其他物件有沒有成功解析。
例如:

  • backendRefs 指到的 Service 存不存在
  • certificateRefs 指到的 Secret 能不能合法引用
  • 跨 namespace 引用有沒有配好 ReferenceGrant

這個 condition 超實用。
因為很多設定不是路由邏輯有錯,而是你引用的東西根本不存在,或沒有權限引用。

Programmed

這通常代表設定有沒有真的被實作層落地。
你可以把它理解成:

  • controller 已經接受
  • 也把設定推進資料面或基礎設施

如果 Accepted 已經是 True,但實際流量還是不通,這時就值得去看 Programmed、Gateway address、listener 狀態,以及底下的 Envoy 相關資源。

💡 不同資源會看到的 condition 可能不完全相同,但 AcceptedResolvedRefsProgrammed 是最值得優先建立感覺的一組。

最短排錯流程:照這個順序通常夠用

第一步:先看 Gateway 有沒有真的站起來

kubectl get gateway -A
kubectl get gateway eg -o yaml

先確認:

  • status.addresses 有沒有值
  • listener condition 有沒有異常
  • listener 的 hostname / protocol / port 是不是你以為的那組

如果連 Gateway 都沒 address,後面 route 寫得再漂亮都只是文學創作。

第二步:看 Route 有沒有被接上

kubectl get httproute -A
kubectl get httproute app-route -o yaml

優先看:

  • status.parents
  • Accepted
  • ResolvedRefs
  • observedGeneration

observedGeneration 很值得注意。
如果它還沒追上 metadata.generation,代表 controller 可能還沒處理到你最新那版設定。

第三步:看引用資源是不是都存在

這一步超多人漏掉:

kubectl get svc -A
kubectl get secret -A
kubectl get referencegrant -A

常見問題像是:

  • backend service 名字打錯
  • port 寫錯
  • Secret 不在你以為的 namespace
  • 跨 namespace 引用少了 ReferenceGrant

如果 ResolvedRefsFalse,幾乎就該沿著這條線查。

第四步:再看資料面與 controller

如果 Gateway 與 Route 狀態都看起來差不多對了,但流量還是不通,再往下看:

kubectl get pods -n envoy-gateway-system
kubectl logs -n envoy-gateway-system deployment/envoy-gateway

這時候你在查的已經不是「規則有沒有被接受」,而是控制平面與資料面有沒有正常工作。

如果你有裝 egctl,也可以用它快速看狀態。
但就算沒有,kubectl get/describe -o yaml 其實已經能解大部分問題。

四個超常見故障模式

1. Route 寫對了,但沒掛到你以為的 listener

症狀:

  • YAML 很像對
  • 但流量沒有命中規則

先查:

  • parentRefs.name
  • parentRefs.sectionName
  • Gateway listener 名稱有沒有拼對

多 listener 場景裡,sectionName 拼錯一個字就足夠讓你白忙一輪。

2. Accepted 成功,但 ResolvedRefs 失敗

這通常代表邏輯上可以掛,但引用的東西有問題。
最常見就是:

  • backend Service 不存在
  • Secret 名稱錯
  • cross-namespace reference 沒授權

這種問題最煩的地方在於,表面上看起來「快好了」,結果其實只是卡在引用層。

3. Gateway 有 listener,卻沒有你預期的 address

這很常出現在本地叢集或沒有 LoadBalancer 實作的環境。
不是 Gateway API 壞掉,而是底層根本沒有幫你配出外部位址。

這時可以:

  • 檢查叢集有沒有 LoadBalancer 能力
  • 改用 port-forward 先驗證路徑

4. YAML 生效了,但請求還是 404 / 503

這時通常不是單一欄位錯,而是鏈路某一段沒接上:

  • Host header 不對
  • path 沒命中
  • backend Pod 不健康
  • Service selector 沒對到 Pod

入口層問題有時候看起來像 Gateway 壞掉,實際上只是後端根本沒站好。不要把所有鍋都丟給代理層,代理層也很委屈。

一句話總結

除錯 Gateway API 最有效的方式,不是一直改 YAML,而是先讀懂 status
Accepted 看有沒有接單,ResolvedRefs 看引用有沒有通,Programmed 看設定有沒有真的落地。這三層拆開看,排錯速度會快很多。

下一步

到這裡,這套 Envoy Gateway 系列就湊成完整 10 篇了。
如果你想重新從地圖看一次整體脈絡,可以回到:

👉 系列總覽