0%

在 k8s 环境中使用 Gateway API

Gateway API 是一个官方 Kubernetes 项目,专注于 Kubernetes 中的 L4 和 L7 路由。该项目代表了下一代 Kubernetes Ingress、负载均衡和服务网格 API。从一开始,它就被设计为通用的、表达能力强的且面向角色的。这篇文章我们将学习如何在 k8s 环境中使用 Gateway API。

k8s Gateway API 简介

Gateway API 是一组 API 类型,用于提供动态基础设施配置与高级流量路由能力。它通过可扩展、面向角色、感知协议的配置机制,将网络服务对外暴露。Gateway API 是一个附加组件,包含可提供动态基础设施配置和高级流量路由的各类 API 资源。

设计原则

Gateway API 的核心设计原则包括:

  • 面向角色:Gateway API 资源按组织中负责 Kubernetes 服务网络管理的角色建模:
    • 基础设施提供者:管理支撑多租户、多隔离集群的基础设施,如云厂商。
    • 集群运维人员:负责集群管理,通常关注策略、网络访问、应用权限等。
    • 应用开发者:管理集群中运行的应用,关注应用级配置与 Service 组合
  • 可移植:Gateway API 规范以自定义资源(CRD)定义,被众多实现所支持
  • 表达力强:原生支持常见流量路由场景,如基于请求头匹配、流量权重分流等,这些能力在 Ingress 中只能靠自定义注解实现
  • 可扩展:允许在 API 各层级挂载自定义资源,支持在 API 结构内合适位置做精细化定制

资源模型

Gateway API 包含 4 个稳定版 API 类型:

  • GatewayClass:定义了一组具有通用配置,并由实现该类别的 Controller 管理的网关。它相当于一个 模板品牌,定义了网关的底层实现方式
  • Gateway:定义流量处理基础设施的实例,如云负载均衡器。
  • HTTPRoute:定义 HTTP 专属规则,将网关监听器流量映射到后端网络端点(通常是 Service)
  • GRPCRoute:定义 gRPC 专属规则,将网关监听器流量映射到后端网络端点(通常是 Service)

Gateway API 由相互依赖的 API 类型构成,以适配组织的角色分工:

  • 一个 Gateway 仅关联一个 GatewayClass;GatewayClass 声明负责管理该类网关的 Controller
  • 一个或多个路由类型(如 HTTPRoute)可关联到 Gateway
  • Gateway 可过滤允许挂载到其 listeners 的路由,与路由形成双向信任模型

请求流

以下是通过 Gateway + HTTPRoute 将 HTTP 流量路由到 Service 的简单示例:

以实现反向代理的网关为例,请求流程:

  • 客户端开始针对 URL http://www.example.com 准备一个 HTTP 请求。
  • 客户端的 DNS 解析器查询目标域名,并获取到与该网关(Gateway)关联的一个或多个 IP 地址的映射。
  • 客户端向该网关 IP 地址发送请求;反向代理接收到该 HTTP 请求,并利用 Host: 请求头来匹配由网关(Gateway)及关联的 HTTP 路由(HTTPRoute)所生成的配置。
  • (可选)反向代理可以根据 HTTP 路由(HTTPRoute)的匹配规则,执行请求头匹配和/或路径匹配。
  • (可选)反向代理可以根据 HTTP 路由(HTTPRoute)的过滤规则修改请求;例如,添加或移除请求头。
  • 最后,反向代理将请求转发给一个或多个后端服务。

和 Ingress 的对比

Gateway API 是 Ingress 的继任者。Ingress 的一个重要缺点是:将基础设施配置(如负载均衡器、TLS 证书)和应用层路由规则(如域名、路径)混杂在同一个对象中。这导致职责不清,应用开发者可能需要修改本应由集群运维人员管理的底层配置,在多团队协作时容易产生冲突和权限问题。而 Gateway API 将网络配置的职责清晰地拆分给了不同的角色,实现了关注点分离:

  • 基础设施提供商 (Infrastructure Provider): 负责提供网关控制器的实现,对应 GatewayClass 资源
  • 集群运维者 (Cluster Operator): 负责实例化一个具体的网关,对应 Gateway 资源。他们配置监听端口、协议、TLS 证书等,为应用团队提供一个统一的流量入口。
  • 应用开发者 (Application Developer): 负责定义自己应用的路由规则,对应 HTTPRoute、GRPCRoute 等资源。他们只需关心如何将流量引向自己的服务,而无需触碰底层网关配置

Gateway API 在功能上对 Ingress 进行了全面的增强,许多在 Ingress 中需要依赖特定控制器注解(Annotation)才能实现的高级功能,在 Gateway API 中都成为了原生支持的标准特性。

  • Gateway API 覆盖了 L4/L7 全场景流量,原生支持 HTTP/HTTPS/TCP/UDP/gRPC/TLS
  • Gateway API 支持更精细化的流量调度,如 A/B 测试
  • 原生支持 weight 字段,标准化了金丝雀发布和蓝绿部署
  • 标准化的策略附件(Policy Attachment)机制,配置在不同 Gateway 实现间具有更好的可移植性
  • 跨命名空间引用服务

Ingress API 功能已被冻结停止新功能开发。新的 Kubernetes 项目推荐使用 Gateway 而不是 Ingress。 对于老的 k8s 项目,你可以将现有的 Ingress 资源一次性转换为 Gateway API 资源。关于如何将 Ingress 资源迁移到 Gateway API 资源的具体细节,可以参考 Ingress 迁移指南

服务网格与 GAMMA 倡议

GAMMA(Gateway API for Mesh Management and Administration,即 面向网格管理的 Gateway API)是 Gateway API 子项目下的专项工作流,目标是定义如何将 Gateway API 用于配置服务网格(Service Mesh)。该倡议旨在:

  • 对 Gateway API 本身进行最小化修改,始终保留其面向角色的核心特性
  • 推动服务网格项目(istio、kuma 等等)在实现 Gateway API 时的一致性,无论其技术栈或底层代理是什么

Gateway API 最初是为了处理集群外到集群内的流量(也就是所谓的 入口南北向流量)。不过后来,服务网格用户的需求推动了 GAMMA 倡议在 2022 年的诞生,旨在定义如何用 Gateway API 来处理同一集群内的服务间流量(也就是 东西向流量)。

到目前为止,GAMMA 引入的最重大的变更是:在配置服务网格时,独立的路由资源(例如 HTTPRoute)会直接与 Service 资源关联这主要是因为集群中通常只会有一个活跃的网格,所以在使用网格时不会用到 Gateway 和 GatewayClass 资源。反过来,这就使得 Service 资源成为了路由信息最自然的绑定点

由于 Service 资源本身的设计比较复杂,有些功能被过度重载,有些定义又不够明确,GAMMA 认为必须正式区分 Service 的前端和后端两个层面。具体定义如下:

  • Service 前端(Service frontend):指的是它的名称和集群 IP。
  • Service 后端(Service backend):指的是它包含的一组端点 IP。

这种区分非常关键,它让 Gateway API 能够精确地描述服务网格内部的路由是如何运作的,同时也避免了引入那些与 Service 功能大量重复的新资源

连接路由与服务

GAMMA 规定,独立的 Route 资源会直接附加到 Service 上,这代表了一种配置,旨在应用于所有定向到该 Service 的流量。

  • 传统入口网关模式(南北向)
1
2
3
4
5
6
7
8
9
10
11
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-route
spec:
parentRefs:
- name: my-gateway # 绑定到 Gateway 实例
rules:
- matches:
- path:
value: /api
  • GAMMA 服务网格模式(东西向)
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-route
spec:
parentRefs:
- name: backend-svc
kind: Service
group: "" # Service 属于 core 组,group 留空
rules:
- matches:
- path:
value: /api

在这种模式下:

  • 路由直接附加到 Service 上,表示 所有发往该 Service 的流量都将遵循此路由规则
  • 当一个 Service 附加了多个路由时,未匹配任何路由规则的请求会被拒绝
  • 无需再创建 Gateway 和 GatewayClass 资源,适配服务网格单集群单网格的典型场景

parentRefs

在 Gateway API 的设计中,parentRefs(父资源引用)是一个非常核心的概念。简单来说,它定义了 这份配置要挂载到哪里 或者说 谁来负责实现这份路由规则

在传统的 Ingress 中,路由和网关是耦合在一起的;而在 Gateway API 中,路由(如 HTTPRoute)通过 parentRefs 明确告诉集群:我这份路由规则是给哪个网关(Gateway)或哪个服务(Service)定义的。

在南北流量场景下(对接 Gateway),需要指定这个路由规则由哪个具体的 入口网关 来执行。即需要指定一个 Gateway 资源:

1
2
3
4
5
spec:
parentRefs:
- name: my-internet-gateway # 引用名为 my-internet-gateway 的 Gateway 资源
namespace: infra-ns
sectionName: https # (可选) 仅挂载到该网关名为 https 的监听器上

在东西流量场景下(对接 Service,即 GAMMA),在服务网格(Service Mesh)中,流量不经过物理网关,而是服务之间直接通信。parentRefs 通常指向一个 Service 资源。此时,声明这些路由规则(如负载均衡、重试、超时)适用于所有发往该 Service 的请求。此时,Service 充当了 逻辑上的父资源

1
2
3
4
5
6
spec:
parentRefs:
- name: user-service # 引用名为 user-service 的 Service
kind: Service
group: core
port: 8080 # (可选) 仅当访问该服务的 8080 端口时生效

对于 GAMMA,当你定义一个路由(如 HTTPRoute)时,parentRef 绑定的就是 服务前端,它代表了流量的目标地址。路由规则(如权重转发)最终会将流量分发到这些具体的后端实例上。

假设你正在开发一个名为 order-service(订单服务)的应用:

  • 你有一个正在运行的旧版本(v1)
  • 刚刚部署了一个新版本(v2),你想让 10% 的流量去 v2,90% 的流量留在 v1

在 Gateway API 中,服务前端只有一个:

  • 你依然只暴露一个名为 order-service 的 Kubernetes Service。所有的客户端依然访问 http://order-service。这个名称就是 Frontend
  • 在 K8S 层面,你会定义两个不同的 Deployment:order-v1order-v2
  • 通过路由(HTTPRoute)进行解耦:
    • 它的 parentRef 指向:order-service(前端/身份)
    • 它的 rules 指向:
      • backendRef 1:指向 Pod 标签为 version: v1 的后端(权重 90)
      • backendRef 2:指向 Pod 标签为 version: v2 的后端(权重 10)

部署 Envoy Gateway

Envoy Gateway 是一个 Kubernetes 原生的 API 网关和反向代理控制平面。它利用标准的 k8s Gateway API 及其自身的可扩展 API,简化了将 Envoy Proxy 作为数据平面进行部署和运维的流程。通过将 Envoy 的性能与灵活性和 Kubernetes 原生配置相结合,Envoy Gateway 可以帮助平台团队以极低的运维开销,对外暴露并管理安全、可观测且可扩展的 API。

接下来我们将通过实际部署 Envoy Gateway 来熟悉如何在 k8s 环境中使用 Gateway API。基础环境仍然是基于之前搭建的 k8s Kind 集群。我们将使用 Helm 来完成相关安装。

Helm 简介

Helm 是 Kubernetes 的包管理器,类似于 apt/yum 之于 Debian/RedHat、pip 之于 Python、npm 之于 Node.js。在没有 Helm 的时候,部署一个稍复杂的应用(比如带有数据库、缓存、前端和后端的应用),你可能需要编写大量的 YAML 文件:

  • deployment.yaml (好几个)
  • service.yaml
  • ingress.yaml
  • configmap.yaml
  • secret.yaml

Helm 引入了一些关键概念,使得部署和管理 Kubernetes 应用变得更加简单:

概念 说明
Repository Chart 存放的仓库
Chart 应用打包模板,包含一组 K8s 资源定义,包含了部署一个应用所需的所有 YAML 模板,定义了应用的结构
Values 这是 配置文件。它包含了你想要自定义的参数,Helm 会把这些参数填入 Chart 的模板中
Release 这是 安装后的实例。当你运行一次安装命令,Helm 就会创建一个 Release。你可以在同一个集群里,用同一个 Chart 安装出两个不同的 Release

Helm 的作用:

  • 简化复杂应用的部署(一个命令安装几十个 K8s 资源)
  • 支持版本管理和回滚
  • 支持配置模板化(同一 Chart 不同配置)
  • 便于应用分发和复用

使用如下命令完成 Helm 的[安装](https://helm.sh/zh/docs/v3/intro/install/:

1
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 && chmod 700 get_helm.sh && ./get_helm.sh

使用 Helm 安装 Envoy Gateway

使用 Helm 安装 Gateway API CRDs 和 Envoy Gateway:

1
# helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.7.2 -n envoy-gateway-system --create-namespace

等待部署完成:

1
kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available
  • 安装的命名空间是 envoy-gateway-system

检查 Gateway API CRDs

安装完成后,我们可以检查下当前环境下的 Gateway API CRDs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# kubectl get crd | grep gateway
backends.gateway.envoyproxy.io 2026-04-27T06:36:31Z
backendtlspolicies.gateway.networking.k8s.io 2026-04-27T06:36:31Z
backendtrafficpolicies.gateway.envoyproxy.io 2026-04-27T06:36:31Z
clienttrafficpolicies.gateway.envoyproxy.io 2026-04-27T06:36:31Z
envoyextensionpolicies.gateway.envoyproxy.io 2026-04-27T06:36:31Z
envoypatchpolicies.gateway.envoyproxy.io 2026-04-27T06:36:31Z
envoyproxies.gateway.envoyproxy.io 2026-04-27T06:36:31Z
gatewayclasses.gateway.networking.k8s.io 2026-04-27T06:36:31Z
gateways.gateway.networking.k8s.io 2026-04-27T06:36:31Z
grpcroutes.gateway.networking.k8s.io 2026-04-27T06:36:31Z
httproutefilters.gateway.envoyproxy.io 2026-04-27T06:36:32Z
httproutes.gateway.networking.k8s.io 2026-04-27T06:36:31Z
referencegrants.gateway.networking.k8s.io 2026-04-27T06:36:31Z
securitypolicies.gateway.envoyproxy.io 2026-04-27T06:36:32Z
tcproutes.gateway.networking.k8s.io 2026-04-27T06:36:31Z
tlsroutes.gateway.networking.k8s.io 2026-04-27T06:36:31Z
udproutes.gateway.networking.k8s.io 2026-04-27T06:36:31Z
xbackendtrafficpolicies.gateway.networking.x-k8s.io 2026-04-27T06:36:31Z
xlistenersets.gateway.networking.x-k8s.io 2026-04-27T06:36:31Z
xmeshes.gateway.networking.x-k8s.io 2026-04-27T06:36:31Z

这些 CRD 可以分为两类:

  1. 标准 Gateway API CRDs (gateway.networking.k8s.io):
  • gatewayclasses - GatewayClass 定义
  • gateways - Gateway 实例
  • httproutes - HTTP 路由规则
  • grpcroutes - GRPC 路由规则
  • tcproutes/udproutes - TCP/UDP 路由
  • tlsroutes - TLS 路由
  • referencegrants - 跨命名空间引用授权
  1. Envoy Gateway 扩展 CRDs (gateway.envoyproxy.io):
  • envoyproxies - Envoy Proxy 自定义配置
  • securitypolicies - 安全策略
  • clienttrafficpolicies - 客户端流量策略
  • backendtrafficpolicies - 后端流量策略

测试 Envoy Gateway

接下来通过一个简答的应用实例,来测试下 Gateway API 和 Envoy Gateway 的使用。

部署业务应用

首先创建 3 个 echo 服务,包含 Deployment 和 Service 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-a
spec:
replicas: 1
selector:
matchLabels:
app: echo-a
template:
metadata:
labels:
app: echo-a
version: v1
spec:
containers:
- name: echo
image: hashicorp/http-echo:0.2.3
args:
- "-text=echo-a"
- "-listen=:80"
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: echo-a
spec:
selector:
app: echo-a
ports:
- port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-b
spec:
replicas: 1
selector:
matchLabels:
app: echo-b
template:
metadata:
labels:
app: echo-b
version: v1
spec:
containers:
- name: echo
image: hashicorp/http-echo:0.2.3
args:
- "-text=echo-b"
- "-listen=:80"
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: echo-b
spec:
selector:
app: echo-b
ports:
- port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-v2
spec:
replicas: 1
selector:
matchLabels:
app: echo-v2
template:
metadata:
labels:
app: echo-v2
version: v2
spec:
containers:
- name: echo
image: hashicorp/http-echo:0.2.3
args:
- "-text=echo-v2"
- "-listen=:80"
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: echo-v2
spec:
selector:
app: echo-v2
ports:
- port: 80
targetPort: 80
  • 应用配置
1
# kubectl apply -f manifests/echo-services.yaml
  • 查看生效的服务和资源
1
2
3
4
5
6
7
8
9
10
11
12
#  kubectl get deployment,svc
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/echo-a 1/1 1 1 56m
deployment.apps/echo-b 1/1 1 1 56m
deployment.apps/echo-v2 1/1 1 1 56m

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/echo-a ClusterIP 10.98.231.116 <none> 80/TCP 56m
service/echo-b ClusterIP 10.96.196.139 <none> 80/TCP 56m
service/echo-v2 ClusterIP 10.108.11.121 <none> 80/TCP 56m
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d3h

创建 GatewayClass

接下来创建 GatewayClass 资源,用以定义 Gateway 的类型和配置:

1
2
3
4
5
6
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
1
# kubectl apply -f manifests/gatewayclass.yaml
  • 使用的 Controller 是 gateway.envoyproxy.io/gatewayclass-controller
1
2
3
# kubectl get gatewayclass
NAME CONTROLLER ACCEPTED AGE
eg gateway.envoyproxy.io/gatewayclass-controller True 62m

创建 Gateway

使用如下配置,创建 Gateway 实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg
spec:
gatewayClassName: eg
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same
  • gatewayClassName: 指定使用哪个 GatewayClass(决定了由谁实现)
  • listeners: 定义监听的端口和协议
  • allowedRoutes: 控制哪些 HTTPRoute 可以绑定到此 Gateway
    • Same: 同命名空间
    • All: 所有命名空间
    • Selector: 通过 Label 选择

查看 Gateway 实例信息:

1
2
3
# kubectl get gateway
NAME CLASS ADDRESS PROGRAMMED AGE
eg eg 172.19.0.100 True 65m
  • ADDRESS: Gateway 的外部访问地址(由 MetalLB 分配的 LoadBalancer IP)
  • PROGRAMMED=True: Gateway 已配置完成,Envoy Proxy 已就绪

Envoy Gateway 创建 Gateway 时,自动创建 Envoy Proxy Service,默认类型是 LoadBalancer(也可以通过 EnvoyProxy CRD 配置改为 NodePort 类型)。由于我们 Kind 环境已经部署了 MetalLB,因此这里的 LoadBalancer 可以正常工作。查看 Gateway 所对应的资源:

1
2
3
4
5
6
7
8
9
10
# kubectl get svc -n envoy-gateway-system

NAME TYPE EXTERNAL-IP PORT(S)
envoy-default-eg-e41e7b31 LoadBalancer 172.19.0.100 80:30947/TCP
envoy-gateway ClusterIP <none> 18000/TCP,18001/TCP...

# kubectl get pods -n envoy-gateway-system
NAME READY STATUS RESTARTS AGE
envoy-default-eg-e41e7b31-68749fc97c-khlnx 2/2 Running 0 7m20s
envoy-gateway-db9b87d6c-cjtq8 1/1 Running 0 8m55s
  • envoy-default-eg-e41e7b31: Envoy Proxy Service,处理实际流量
  • envoy-gateway: 控制面管理端口(xDS 配置下发等)

Envoy Gateway 运行时的核心组件包括两部分:

  • envoy-gateway (控制面):

    • Envoy Gateway Controller
    • 控制面:监听 Gateway API 资源变化,翻译成 Envoy 配置,通过 xDS 下发给数据面(Envoy Proxy)
  • envoy-default-eg-e41e7b31 (数据面):

    • Envoy Proxy 实例
    • 数据面:实际处理流量转发,接收控制面下发的配置
    • 名称格式: envoy-{namespace}-{gateway-name}-{hash}

基本 HTTP 路由

测试最基本的路由,将请求转发到单一后端服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: basic-route
spec:
parentRefs:
- name: eg # 绑定到 Gateway eg
sectionName: http # 绑定到 http listener
hostnames:
- "echo.example.com" # 匹配的 Host 名
rules:
- backendRefs:
- name: echo-a # 后端 Service
port: 80
  • parentRefs: 指定 HTTPRoute 绑定的 Gateway
    • name: Gateway 名称
    • sectionName: 具体的 listener 名称(可以绑定多个 listener)
  • hostnames: 匹配请求的 Host 头(支持精确匹配和通配符)
  • backendRefs: 后端服务引用
    • name: Service 名称
    • port: Service 端口
  • 默认匹配所有路径 (PathPrefix: /)

下发路由:

1
# kubectl apply -f manifests/httproute-basic.yaml

检查路由:

1
2
3
# kubectl get httproute basic-route
NAME HOSTNAMES AGE
basic-route ["echo.example.com"] 78m

实际流量测试:

1
2
# curl -s --noproxy '*' -H "Host: echo.example.com" http://172.19.0.100/
echo-a

多服务路由 (基于路径)

如下配置则测试基于 URL 路径的路由,不同路径转发到不同服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: multi-service-route
spec:
parentRefs:
- name: eg
sectionName: http
hostnames:
- "multi.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /a
backendRefs:
- name: echo-a
port: 80
- matches:
- path:
type: PathPrefix
value: /b
backendRefs:
- name: echo-b
port: 80
  • rules: 规则列表,按顺序匹配(先匹配的生效)
  • matches: 路由匹配条件
    • path.type: 匹配类型
      • Exact: 精确匹配(如 /api 只匹配 /api
      • PathPrefix: 前缀匹配(如 /api 匹配 /api, /api/v1, /api/users
      • RegularExpression: 正则匹配
    • path.value: 匹配的路径值
  • 每个 rule 可以有多个 matches 和多个 backendRefs

应用路由:

1
kubectl apply -f manifests/httproute-multi-service.yaml

查看路由

1
2
3
# kubectl get httproute multi-service-route
NAME HOSTNAMES AGE
multi-service-route ["multi.example.com"] 83m

测试路由:

1
2
3
4
5
# curl -s --noproxy '*' -H "Host: multi.example.com" http://172.19.0.100/a
echo-a

# curl -s --noproxy '*' -H "Host: multi.example.com" http://172.19.0.100/b
echo-b

流量分割

如下则将测试流量按权重分配到多个后端服务(金丝雀发布场景)。

配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: traffic-split-route
spec:
parentRefs:
- name: eg
sectionName: http
hostnames:
- "split.example.com"
rules:
- backendRefs:
- name: echo-a
port: 80
weight: 80
- name: echo-v2
port: 80
weight: 20
  • weight: 权重比例,决定流量分配
    • 权重是相对值,实际比例为 weight/(总weight)
    • 80:20 表示 80% 到 echo-a,20% 到 echo-v2
  • 流量分割用途:
    • 金丝雀发布:新版本先接收少量流量
    • A/B 测试:不同版本接收不同流量比例
    • 蓝绿部署:快速切换流量比例

在下发路由后,我们实际进行测试:

1
2
3
4
5
6
7
# for i in {1..20}; do curl -s --noproxy '*' -H "Host: split.example.com" http://172.19.0.100/; done | sort | uniq -c
15 echo-a
5 echo-v2

# for i in {1..20}; do curl -s --noproxy '*' -H "Host: split.example.com" http://172.19.0.100/; done | sort | uniq -c
16 echo-a
4 echo-v2

小结

这篇文章我们学习了 k8s 的 Gateway API,包括其核心概念、为 Service Mesh 场景所引入的 GAMMA 等等。同时我们实际部署了 Envoy Gateway,并通过 Gateway API 实现了各种路由功能:单一服务、多服务(基于路径)、流量分割等场景。