bigywater.tech
微服务 · 94

Ingress 与 Gateway API

Ingress 和 Gateway API 到底差在哪?流量比例、请求头匹配能不能直接写在规范里?谁能把路由挂到网关上?配置写错了 kubectl 能告诉你什么?这篇用 kind 集群里同一个 Traefik 同时跑 Ingress 和 Gateway API 两种写法,逐项量出来。

450 / 50
HTTPRoute 权重 90 对 10 时,500 个请求里 v1 与 v2 各得多少(规范字段,不是注解)
404 / 500
同样是指向不存在的 Service:Ingress 请求得 404 且 status 没有信息,HTTPRoute 请求得 500 且有 BackendNotFound
< 0.3 s
Ingress 与 HTTPRoute 切流量从 kubectl apply 到客户端看到新后端的时间(含 kubectl 进程)

Ingress 的边界

实测 · 本机执行输出
  (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,没有权重和请求头匹配;按比例分流要靠控制器的注解或自定义资源。

HTTPRoute

实测 · 本机执行输出
  (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 以内生效,差别在测量误差内。

分步演示

Ingress 与 Gateway API
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / Go / nginx / Envoy / etcd / Consul / Nacos / OpenTelemetry / Prometheus(按各篇注明用到哪些及版本);所有服务都是本机自己起的进程,端口 9150 以上,只监听 127.0.0.1,不连任何外部服务,不碰本机已有的实例;故障用 kill -9 进程、让连接断开或在代码里注入延迟与错误来制造;计时用 time.perf_counter,数字每次运行会有小幅抖动。kind 集群,Gateway API 标准通道 CRD v1.6.3,Traefik v3.7.15(同时开启 Ingress 与 Gateway API 两个 provider,同一个数据面);后端是 busybox httpd;客户端是集群里的 Pod;全部是这一个实现的结果,其它控制器(ingress-nginx、Envoy Gateway、Istio)的注解和对 Gateway API 特性的支持程度不同;每个场景只跑了一次,传播延迟是 5 次,从宿主机 kubectl apply 开始算,时钟差用 kubectl exec 对表估计,误差在 0.1 s 量级;开发时在另一次运行里,同一个 host 和 path 在两个命名空间里各有一条 HTTPRoute,Traefik 只让先创建的那条生效(日志里有 does not create router 的警告),这个行为没有单独做成实验
    • 没有验证:TLS 终止与证书(Gateway 的 certificateRefs、Ingress 的 tls);ingress-nginx 等其它控制器(我记得 ingress-nginx 项目已经宣布停止维护,没有核实,也没有测);GRPCRoute、TCPRoute 与实验通道的特性;多个 Gateway 共享一个入口;云上负载均衡器后面的行为(kind 里没有 LoadBalancer);Traefik 对权重分配是否在所有版本里都是精确比例;大规模路由(上千条)下的生效时间
    京ICP备2026067502号-1京公网安备11010502063487号