CKA [Networking] – Ingress和Gateway的区别
在 Kubernetes 中,Ingress
和 Gateway
都是用于管理集群外部流量进入集群服务的机制,但它们各自适用的场景、控制能力和架构设计不同
✅ 一、有了 Ingress,为什么还需要 Gateway?
Ingress 的局限性:
- 耦合太紧:
- Ingress 通常依赖于特定的控制器(如 NGINX、Traefik),它的行为和功能依赖于这些控制器实现。
- 不同控制器支持的 annotation、配置方式不一致,缺乏标准化。
- 功能有限:
- Ingress 只支持 L7 HTTP/HTTPS 路由,不支持 L4(如 TCP、gRPC、TLS passthrough)流量。
- 复杂场景(如多协议支持、多租户、多路径转发)难以配置。
- 扩展性差:
- 想要对路由进行更复杂的控制(如权重转发、重写 header、限流)时,必须依赖控制器扩展。
✅ 二、Ingress 和 Gateway 的区别
项目 | Ingress | Gateway (Gateway API) |
---|---|---|
定义 | Ingress 是 Kubernetes 最早期引入的资源类型,用于管理 HTTP/HTTPS 入口流量 | Gateway 是 Kubernetes 新一代标准,来源于 Gateway API 项目,设计上更灵活、可扩展 |
支持协议 | 主要支持 HTTP/HTTPS | 支持 HTTP、HTTPS、TCP、TLS、gRPC 等多协议 |
控制器耦合 | 强依赖特定 Ingress Controller | Gateway 与 Controller 解耦,Controller 实现了 GatewayClass,可被替换 |
可扩展性 | 差,扩展依赖 annotation | 好,原生 CRD 支持更复杂的路由策略(HTTPRoute、TCPRoute 等) |
安全性 | 难以做细粒度权限管理 | 更好支持 RBAC、多租户控制(Gateway 与 Route 可分开授权) |
多租户支持 | 弱,Ingress 通常在单一 namespace 管理 | 强,Gateway 和 Route 可以分别在不同 namespace 中定义和控制 |
状态反馈 | 状态反馈不标准,用户体验差 | 状态清晰标准化,调试和排错更容易 |
✅ 三、Gateway 的优点
- 协议丰富:支持 HTTP、TCP、TLS、gRPC、UDP(部分实现)等多种协议,支持更多真实世界的流量场景。
- 清晰分层架构:
GatewayClass
:定义控制器类型(例如 Istio、NGINX)。Gateway
:声明资源入口点(监听端口、证书等)。Route
(如HTTPRoute
,TCPRoute
):定义路由规则。
- 跨 namespace 管理:
- 一个 Gateway 可以由 platform team 管理,而 Route 可以由 app team 在不同 namespace 独立管理,真正实现平台与业务解耦。
- 更好的标准化与可观测性:
- Gateway API 规范提供标准状态反馈和错误信息,便于调试和监控。
- 与服务网格(如 Istio)深度集成,有天然优势。
新版本发布控制的多样性
httproute需要配合gateway, 在httproute当中可以设置weight, 这个weight可以根据不同的比重来分发流量到不同的service。
1. 灰度/金丝雀发布(Canary Releases)
当你发布一个新版本(foo-v2
)时,不想一下子把所有流量都切给它,而是先把绝大多数请求留给旧版本(foo-v1
),比如 90%→10% 的比例流转。这样即便新版本有问题,也只影响小部分用户,便于快速回
rules:
- backendRefs:
- name: foo-v1
port: 8080
weight: 90
- name: foo-v2
port: 8080
weight: 10
weight
值 90 和 10 的和(100)就是“分母”,每个后端实例获得的流量占比即为 weight/100
2. A/B 测试
你可以把不同的后端(A 版本、B 版本)设置不同权重,比如 50/50,或者按照 70/30 分流给不同实验组,以收集用户行为数据、对比效果。一次性在同一条路由下搞定,不必再额外引入 Service Mesh 的流量分发规则
3. 蓝绿部署(Blue-Green Deployment)
当新旧环境同时在线时,可以先把 100% 流量给“蓝”(旧环境),确认没问题后,把“绿”(新环境)的权重调到 1(此时占比 50%:50%),再切到 0(100% 都给新环境)。
# 切换完成时的新配置
rules:
- backendRefs:
- name: blue-svc
port: 8080
weight: 0
- name: green-svc
port: 8080
weight: 1
只需更新 weight,就能实现平滑切换和快速回滚
Canary Deployment里,如何确保同一个用户都固定在同一个service当中?
在 Gateway API 里,weight
只是按比例(随机)把每个请求分给不同后端,它并不会“记住”同一个用户之前去了哪里。要让 同一个用户 在整个会话/浏览器里「一以贯之」地命中同一个版本,你需要在路由层面做会话粘滞 (session affinity),常用的模式就是:
- 首次请求 随机分流(按 weight),并在响应里写入一个 Cookie,比如
canary=true
- 后续请求 根据这个 Cookie 匹配路由,把它始终导向同一个后端
下面给出一个基于 HTTPRoute 的简化示例(假设你的 Controller 支持 HTTPRouteFilter 中的 RequestHeaderModifier 和 HeaderMatch):
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: canary-release
spec:
parentRefs:
- name: my-gateway
# 1. 如果请求带了 canary=true,就走 canary-svc
rules:
- matches:
- headers:
- name: Cookie
value: "canary=true"
backendRefs:
- name: canary-svc
port: 80
weight: 100
# 2. 默认流量,按比例先给 canary,再给 stable
- matches:
- path:
type: Prefix
value: /
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
# 在响应里给客户端写 Cookie,后续它会带上
- name: Set-Cookie
value: "canary=true; Path=/; Max-Age=3600"
backendRefs:
- name: canary-svc
port: 80
weight: 10
- name: stable-svc
port: 80
weight: 90
1. 默认情况走这一条规则
- 当请求里没有
Cookie: canary=true
时,就会匹配到第 2 条规则(因为第 1 条需要带这个 Cookie)。
2. 按权重(weight)分流
- 在这一条规则里,我们给了两个后端:
canary-svc
的weight: 10
stable-svc
的weight: 90
- 这表示“把 100% 的默认流量里,有 10% 随机发给 canary,剩下 90% 发给 stable”。
- 实际上 Controller 会把请求分成 10:90 的概率,你的客户端每次来,随机地有 10% 的机会被路由到
canary-svc
,90% 的机会被路由到stable-svc
。
3.设置 Cookie 以便粘滞
对于被分到 canary-svc
的那 10% 请求,规则里又附带了一个 RequestHeaderModifier 过滤器:
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: Set-Cookie
value: "canary=true; Path=/; Max-Age=3600"
- 它会在 响应 头里加上
Set-Cookie: canary=true
,告诉浏览器这个用户“以后你就是 canary 组的”。
4.后续请求保持一致
- 浏览器拿到这个 Cookie 后,每次再来就带上
Cookie: canary=true
,这样就会命中第 1 条规则,100% 发给canary-svc
,保证用户体验一致,不会“新旧页面混用”。