Ingress 和 Gateway API 到底差在哪?流量比例、请求头匹配能不能直接写在规范里?谁能把路由挂到网关上?配置写错了 kubectl 能告诉你什么?这篇用 kind 集群里同一个 Traefik 同时跑 Ingress 和 Gateway API 两种写法,逐项量出来。
(a)GET /a:200:v1 × 200;GET /b:200:v2 × 200 (b)两条 path 都是 / 的规则(先写 app-v1,后写 app-v2):GET /:200:v2 × 200 (c)kubectl explain ingress.spec.rules.http.paths 列出的字段:['backend', 'path', 'pathType'] (c)kubectl explain ingress.spec.rules 列出的字段:['host', 'http'] Ingress 的规则只有 host、path、pathType 和一个后端 Service;每条路径只指一个后端,没有权重、请求头匹配这些字段;两条同样的 path 时流量不会按比例分,全部去了同一个后端(上面 (b) 的结果),想要流量比例或按请求头分流,只能用具体控制器自己的注解或自定义资源,换一个控制器就要重写
规则只有 host、path、pathType 和一个后端 Service,没有权重和请求头匹配;按比例分流要靠控制器的注解或自定义资源。
(a)app-v1 权重 90、app-v2 权重 10:200:v1 × 450, 200:v2 × 50 (b)权重 50 对 50:200:v1 × 250, 200:v2 × 250 (c)权重 0 对 100:200:v2 × 500 (d)带 x-canary: 1:200:v2 × 200;不带:200:v1 × 200 权重和请求头匹配是 HTTPRoute 规范里的字段,不是某个控制器的注解;这个实现按权重轮转,500 个请求的分配是精确的比例(不是随机抽样)
权重和请求头匹配是规范里的字段,这个实现按精确的比例分配。
(a)from: Same:路由状态 Accepted=False(NotAllowedByListeners), ResolvedRefs=True(ResolvedRefs);GET other.local:404 × 100 (b)from: All:路由状态 Accepted=True(Accepted), ResolvedRefs=True(ResolvedRefs);GET other.local:200:v3 × 100 (c)后端是另一个命名空间的 Service,没有 ReferenceGrant:路由状态 Accepted=True(Accepted), ResolvedRefs=False(RefNotPermitted);GET other.local:500 × 100 (d)加上 ReferenceGrant:路由状态 Accepted=True(Accepted), ResolvedRefs=True(ResolvedRefs);GET other.local:200:v1 × 100 Gateway API 把 “谁拥有网关” 和 “谁写路由” 分开,并且在规范里规定了越界时怎么办:路由要经过监听器的 allowedRoutes 才能挂上去,引用别的命名空间的 Service 要对方用 ReferenceGrant 授权;Ingress 没有这一层,任何命名空间的 Ingress 都能挂到同一个控制器上
路由要经过监听器的 allowedRoutes 才能挂上去,引用别的命名空间的 Service 要对方用 ReferenceGrant 授权,规范规定了越界时的行为。
(a)Ingress 指向不存在的 Service:status = {"loadBalancer": {}};GET /:404 × 100
(b)HTTPRoute 指向不存在的 Service:路由状态 Accepted=True(Accepted), ResolvedRefs=False(BackendNotFound);GET /:500 × 100
(b)ResolvedRefs 的 message:Cannot load HTTPBackendRef v94/no-such-svc: getting service: service "no-such-svc" not found
Ingress 的 status 里只有负载均衡器地址,规则写错了从 kubectl 看不出来(得去看控制器日志);HTTPRoute 的 status.parents[*].conditions 是规范规定的,控制器必须写 Accepted / ResolvedRefs,指向不存在的后端会有明确的原因HTTPRoute 的状态条件会写明 BackendNotFound、RefNotPermitted 这类原因;Ingress 的 status 里只有地址。
Ingress:从 kubectl apply 开始(含 kubectl 进程本身的启动和请求 API 的时间)到客户端第一次看到 v2,中位数 0.11 s(5 次:0.17, 0.10, 0.12, 0.11, 0.08) HTTPRoute:从 kubectl apply 开始(含 kubectl 进程本身的启动和请求 API 的时间)到客户端第一次看到 v2,中位数 0.22 s(5 次:0.12, 0.22, 0.16, 0.28, 0.27) 两种写法最终都是控制器监听 API 对象的变化再更新数据面,生效的时间取决于控制器,不取决于 API 本身;这是同一个实现(Traefik)里两种写法的数字,换一个控制器会不同 说明(哪些是测到的,哪些没有测) 全部是一个实现(Traefik v3.7.15)在 kind 集群里的结果;每个场景只跑了一次(传播延迟 5 次);没有测:TLS 终止与证书(Gateway 的 certificateRefs、Ingress 的 tls)、其它控制器(ingress-nginx、Envoy Gateway、Istio)对 Ingress 注解和 Gateway API 特性的支持差异、GRPCRoute / TCPRoute 与实验通道的特性、多个 Gateway 的共享、真实云负载均衡器后面的行为(kind 里没有 LoadBalancer),以及 Traefik 对权重分配是否在所有版本里都是精确比例
两种写法都在 0.3 s 以内生效,差别在测量误差内。