路由与流量分发
本文将介绍 Envoy Gateway 中的各种流量路由机制,包括 HTTP 和 gRPC 路由、请求镜像、多协议支持、跨集群路由、流量分割以及 Kubernetes 外部路由。通过这些功能,用户可以灵活配置流量的分发方式,满足不同应用场景的需求。
HTTP 路由
HTTP 路由是基于请求的路径、方法、头信息等条件来路由 HTTP 请求的核心功能。在 EG 中,你可以通过配置 HTTPRoute 对象来定义多种匹配规则,将请求路由到相应的后端服务。
配置示例:
定义一个 HTTPRoute 资源,用于将所有对以 /foo 开头的 URL 请求路由到名为 foo-service 的服务的 80 端口。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-route
spec:
parentRefs:
- name: example-gateway
rules:
- matches:
- path:
type: Prefix
value: "/foo"
backendRefs:
- name: foo-service
port: 80
GRPC 路由
GRPC 路由功能允许你根据 GRPC 服务的方法和消息类型来路由请求。在 Envoy Gateway 中,这通过 GRPCRoute 对象来实现,提供了细粒度的流量控制。
配置示例:
定义一个 GRPCRoute 资源,用于将匹配到的 gRPC 请求(服务为 example-service,方法为 ExampleMethod)路由到名为 grpc-service 的服务的 50051 端口。
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: example-grpc-route
spec:
parentRefs:
- name: example-gateway
rules:
- matches:
- method:
service: "example-service"
method: "ExampleMethod"
backendRefs:
- name: grpc-service
port: 50051
HTTPRoute 请求镜像
请求镜像功能允许你将请求的副本发送到不同的后端服务,而不影响原始请求的处理。这对于在生产环境中测试新服务,或实现数据流复制非常有用。请求镜像是在 HTTPRoute 上使用 Gateway API 的
HTTPRequestMirrorFilter
完成的。
配置示例:
定义一个 HTTPRoute 资源,用于将所有匹配到的请求(路径以 / 开头)镜像到名为 backend-2 的服务,同时将原始请求转发到名为 backend 的服务。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-mirror
spec:
parentRefs:
- name: example-gateway
hostnames:
- backends.example
rules:
- matches:
- path:
type: PathPrefix
value: /
filters:
- type: RequestMirror
requestMirror:
backendRef:
kind: Service
name: backend-2
port: 3000
backendRefs:
- group: ""
kind: Service
name: backend
port: 3000
多协议支持的路由
Envoy Gateway 不仅支持 HTTP 和 GRPC,还支持 TCP 和 UDP 协议的路由。通过 TCPRoute 和 UDPRoute 对象,你可以根据端口号等条件来路由相应的流量,确保在不同协议下流量的正确分发。
TCPRoute 和 UDPRoute 资源是 Kubernetes Gateway API 中的实验阶段。使用步骤:
- 定义 Gateway 和 GatewayClass:
- 首先,创建一个
GatewayClass和一个Gateway资源。 - 在
Gateway中配置 TCP 监听器,指定监听的端口和允许的路由类型(如TCPRoute)。
- 首先,创建一个
- 配置
TCPRoute/UDPRoute:- 创建
TCPRoute/UDPRoute资源,为每个 TCP/UDP 监听器定义路由规则。 - 在
TCPRoute/UDPRoute中,通过parentRefs将其与Gateway的特定监听器关联。 - 在
rules中指定要将流量路由到的后端服务和端口。
- 创建
- 部署后端服务:
- 部署相应的后端服务(如 Kubernetes 的
Service和Deployment),这些服务将接收来自 Gateway 的 TCP/UDP 流量。
- 部署相应的后端服务(如 Kubernetes 的
详细步骤请参考 Envoy Gateway 文档 。
TCP 路由配置示例:
定义一个 TCPRoute 资源,用于将所有发送到 3306 端口的 TCP 请求路由到名为 db-service 的服务的 3306 端口。
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: example-tcp-route
spec:
parentRefs:
- name: example-gateway
rules:
- matches:
- port: 3306
backendRefs:
- name: db-service
port: 3306
UDP 路由配置示例:
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: UDPRoute
metadata:
name: example-udp-route
spec:
parentRefs:
- name: example-gateway
rules:
- matches:
- port: 53
backendRefs:
- name: dns-service
port: 53
多集群服务路由
Envoy Gateway 支持多集群服务路由,这允许您将来自一个 Kubernetes 集群的请求路由到另一个集群中的服务。多集群服务路由通过结合使用
Multicluster Service API
的 ServiceImport 对象和 Gateway API 的 HTTPRoute 来实现。这种设置通常用于跨集群的服务调用,适合在多区域或多数据中心的部署环境中使用。
使用步骤:
设置多集群环境:
- 使用
Submariner项目来配置多集群环境,使服务能够跨集群暴露和访问。 - 在多个集群中安装
Submariner并配置ServiceImport对象以导出服务。
- 使用
安装 Envoy Gateway:
- 在主集群(Cluster1)中安装 Envoy Gateway 并配置 Gateway API 的 CRD。
部署应用程序并导出服务:
- 在另一个集群(Cluster2)中部署后端应用程序,并使用
subctl命令导出服务,使其在多集群环境中可用。
- 在另一个集群(Cluster2)中部署后端应用程序,并使用
配置 Gateway API 对象:
- 在主集群中创建
GatewayClass、Gateway和HTTPRoute对象。 - 在
HTTPRoute中,通过backendRefs引用ServiceImport对象,将流量从主集群路由到另一个集群中的服务。
- 在主集群中创建
配置示例:
以下是一个简单的多集群路由配置示例,定义了一个 GatewayClass 和一个 Gateway,允许 Envoy 代理在 80 端口上监听 HTTP 请求,并将所有匹配到的以 / 开头的请求转发到名为 backend-default-cluster2 的 ServiceImport 服务(位于 submariner-operator 命名空间的 3000 端口),同时指定了主机名为 www.example.com:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg
namespace: default
spec:
gatewayClassName: eg
listeners:
- name: http
protocol: HTTP
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: backend
namespace: default
spec:
parentRefs:
- name: eg
hostnames:
- "www.example.com"
rules:
- backendRefs:
- group: multicluster.x-k8s.io
kind: ServiceImport
name: backend-default-cluster2
namespace: submariner-operator
port: 3000
matches:
- path:
type: PathPrefix
value: /
核心要点:
- ServiceImport:
ServiceImport对象由 Multicluster Service API 定义,用于跨集群访问服务。在HTTPRoute中,可以通过backendRefs引用ServiceImport来实现跨集群路由。 - ReferenceGrant:为了使
HTTPRoute能够跨命名空间引用ServiceImport,需要配置ReferenceGrant对象。这允许来自一个命名空间的资源(如HTTPRoute)访问另一个命名空间中的资源(如ServiceImport)。
HTTP 流量分割
Envoy Gateway 支持通过 HTTPRoute 资源进行流量分割,将流量根据比例分配到多个后端服务。这可以用于蓝绿部署、A/B 测试等场景。
配置步骤:
单一后端配置:
- 当
HTTPRoute仅配置一个backendRef时,所有流量都会被路由到该后端服务。
- 当
多后端配置:
- 如果配置了多个
backendRef,默认情况下流量将平均分配到这些后端。你也可以通过设置weight字段来调整流量分配比例。
- 如果配置了多个
流量权重配置:
- 使用
weight字段控制流量分配比例。例如,将 80% 的流量分配给一个后端,20% 的流量分配给另一个后端。
- 使用
处理无效的后端引用:
- 如果配置了无效的
backendRef(例如,引用了不存在的服务或端口),Envoy Gateway 会对本应路由到该后端的请求返回500错误。
- 如果配置了无效的
配置示例:
定义了一个 HTTPRoute 资源,将所有以 / 开头的请求路由到两个后端服务(backend-1 和 backend-2),并根据指定的权重(8:2)进行流量分配。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-headers
spec:
parentRefs:
- name: eg
hostnames:
- backends.example
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ""
kind: Service
name: backend-1
port: 3000
weight: 8
- group: ""
kind: Service
name: backend-2
port: 9000
weight: 2
Kubernetes 外部路由
Envoy Gateway 支持将流量路由到 Kubernetes 集群外的端点,这一功能在许多需要与外部服务集成的场景中非常有用。你可以通过定义 FQDN(完全限定域名)地址的 EndpointSlice 或使用 Backend 资源来实现这一目的。
配置步骤:
- 定义外部服务:
- 在 Kubernetes 内部创建一个服务(Service),并使用
EndpointSlice将该服务与外部服务(例如httpbin.org)的 FQDN 进行关联。这样,Envoy Gateway 可以将流量路由到这个外部服务。
- 在 Kubernetes 内部创建一个服务(Service),并使用
- 更新 Gateway 配置:
- 在 Gateway 中添加一个 TLS 监听器,设置为透传模式。这允许 Gateway 将接收到的加密流量直接传递给外部服务,而不进行解密处理。
- 创建路由规则:
- 使用
TLSRoute配置,将 Gateway 接收到的流量根据定义的规则路由到外部服务。通过这种方式,可以将外部服务视为 Kubernetes 内部的一部分进行流量管理。
- 使用
详细步骤请参考 Envoy Gateway 文档 。