【Envoy Gateway】角色与附着:GatewayClass / Gateway / Route 各保证什么

💡 原文中文,约13100字,阅读约需31分钟。
📝

内容提要

本文介绍Envoy Gateway v1.9.0中Gateway API的附着与状态机制。核心是三层资源分离:GatewayClass认领实现,Gateway声明入口并控制允许附着的路由,Route声明规则。关键区分Accepted(配置被接受)与Programmed(已交付数据面),跨命名空间引用需ReferenceGrant授权。排障时先查status条件,注意错误parentRef可能无状态反馈。

🔎

延伸解读

三层资源分离:权限边界与路由意图不自动合并

Gateway API 将 Ingress 拆为 GatewayClass、Gateway、Route 三层,分别对应基础设施提供者、集群运维和应用开发者的职责。关键不变量是:权限边界写在 Gateway listener 的 allowedRoutes 上,路由意图写在 Route 上,二者不会自动合并。因此,即使 Route 的 parentRefs 正确,若 listener 的 allowedRoutes 不允许该 namespace 或 kind,Route 也不会被附着。排障时应先检查 listener

Accepted 与 Programmed 的差异:状态语义的精确区分

Accepted 表示配置被控制器接受并会产生某些数据面配置,但不保证全部合法;Programmed 表示配置已解析并送往数据面,但“soon”未定义,不宣称数据面已服务流量。v1.9.0 起,listener 因缺证书未 Programmed 时,不再将已附着 Route 的 Accepted 置为 False。因此,看到 Route Accepted=True 而 listener 未 Programmed 是合法状态,不应误判为 Route 配置错误。

跨命名空间引用:allowedRoutes 与 ReferenceGrant 是

Route 挂到 Gateway 的跨 namespace 由 listener 的 allowedRoutes 控制,而 Route 引用后端 Service 或证书等跨 namespace 对象时,需要目标 namespace 的 ReferenceGrant 授权。两者不可混淆:前者失败表现为 Route 无匹配 listener,后者失败表现为 ResolvedRefs=False 且 reason 为 RefNotPermitted。排障时先看 reason,再决定是调整 allowedRoutes 还是

错误 parentRef 可能无状态反馈:scope 决定 status 写入

实现只能给自己所有权链上的对象写 status。若 parentRef 指向非本实现拥有的 Gateway,实现不会写入错误条件,导致 Route status.parents 为空或缺少本 controller 条目。这并非控制器故障,而是对象不在其 scope。排障时应核对 GatewayClass 的 controllerName 与 parentRefs 是否指向本实现管理的 Gateway,而不是盲目重装控制器。

Q&A

Envoy Gateway 中 GatewayClass、Gateway、Route 三层资源各自保证什么?

GatewayClass 声明一种实现(spec.controllerName),保证控制器会认领它,但不保证集群里已有数据面 Pod;Gateway 声明入口(端口、协议、TLS、allowedRoutes),保证入口配置被接受,但不保证已有 Route 挂上来或地址已分配;Route(如 HTTPRoute)声明匹配与后端,保证规则被接受,但不保证父 Gateway 允许该 namespace/kind 或引用的 Service 存在。

Gateway API 中 Accepted 和 Programmed 状态有什么区别?

Accepted 表示配置在语义和句法上可接受,将被控制器接受并产生某些数据面配置;Programmed 表示配置已解析并送往数据面,即将就绪,但不宣称数据面此刻已在服务流量。Programmed 是比 Accepted 更进一步的交付状态。

跨 namespace 引用时,ReferenceGrant 的作用是什么?

ReferenceGrant 用于允许跨 namespace 的引用,例如 Route 的 backendRefs 指向其他 namespace 的 Service,或 Gateway listener 的 certificateRefs 指向其他 namespace 的 Secret。它必须存在于目标 namespace,并明确允许哪种 From(源 kind+namespace)指向哪种 To(目标 kind)。没有 Grant 时,引用会被拒绝,导致 ResolvedRefs=False,reason 为 RefNotPermitted。

为什么 Route 的 parentRefs 指向错误的 Gateway 时,可能看不到任何错误状态?

因为实现只能给自己所有权链上的对象写 status。如果 parentRef 指向一个不属于该实现的父对象,实现无法判断那是别人的责任,因此不会写错误状态。表象是 Route 的 status.parents 为空或缺少该 controller 的条目,而不是醒目的错误条件。

Envoy Gateway v1.9.0 中,listener 因缺 TLS 证书未 Programmed 时,Route 的 Accepted 状态会怎样?

v1.9.0 起,listener 未 Programmed(缺证书)不再把 Route 的 Accepted 打成 False。因此可能出现 Route Accepted=True、HTTPS listener 未 Programmed 的情况。证书 Grant 应补在 infra namespace,而不是修改 HTTPRoute。

排障时,如果 Route 的 ResolvedRefs=False 且 reason 为 RefNotPermitted,应该怎么处理?

RefNotPermitted 表示跨 namespace 引用存在但握手不同意,即目标 namespace 缺少匹配的 ReferenceGrant。应检查并补充 ReferenceGrant,而不是去检查 Service 是否存在(那是另一个 reason,如 InvalidRef 或 BackendNotFound)。

Gateway 的 Programmed 条件在 Envoy Gateway 中是如何计算的?

Gateway 的 Programmed 条件由 Kubernetes provider 的 updateStatusForGateway 计算,它会读取集群中的 Envoy Service 和 Deployment/DaemonSet,填充 status.addresses,并根据副本或 remote infra 就绪情况设置 Programmed。如果地址未分配则为 AddressNotAssigned,无可用副本则为 NoResources。

🏷️

标签

➡️

继续阅读