HTTP 流量切分
原文:https://gateway-api.sigs.k8s.io/guides/user-guides/traffic-splitting/
HTTPRoute 资源 允许你指定权重来在不同后端之间切分流量。这在发布过程中的流量分批、变更的金丝雀验证,或紧急情况下都非常有用。
HTTPRoute.spec.rules.backendRefs 接受一个后端列表,路由规则会把流量分发到这些后端上。这些后端的相对权重决定了它们之间流量的分配比例。下面这段 YAML 片段展示了在一条路由规则里两个 Service 是如何被列为后端的。这条路由规则会把 90% 的流量分给 foo-v1、10% 的流量分给 foo-v2:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: simple-split
spec:
rules:
- backendRefs:
- name: foo-v1
port: 8080
weight: 90
- name: foo-v2
port: 8080
weight: 10weight 字段表示按比例切分流量(而不是按百分比),因此在同一条路由规则内,所有 weight 之和是分母(所有后端共用)。weight 是可选参数,如果不填,默认值为 1。如果一条路由规则只指定了一个后端,那么无论 weight 取何值(或未指定),它都隐式接收 100% 的流量。
指南
本指南展示如何部署一个 Service 的两个版本,并使用流量切分来渐进式地把流量从 v1 切到 v2。
本示例假设已经部署了下面这个 Gateway:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-web
spec:
gatewayClassName: example
listeners:
- protocol: HTTP
port: 80
name: prod-web-gw
allowedRoutes:
namespaces:
from: SameCanary(金丝雀)发布
一开始,可能只有一个版本的 Service 在为 foo.example.com 的生产用户流量提供服务。下面的 HTTPRoute 没有为 foo-v1 或 foo-v2 指定 weight,所以它们各自会隐式接收其路由规则所匹配到的 100% 流量。使用金丝雀路由规则(匹配 traffic=test Header)可以在正式把生产用户流量切到 foo-v2 之前,先把合成测试流量打过去。
路由优先级 保证:所有同时满足该主机名和该 Header 的请求(最具体的匹配)都会被发往 foo-v2:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: foo-route
labels:
gateway: prod-web-gw
spec:
hostnames:
- foo.example.com
rules:
- backendRefs:
- name: foo-v1
port: 8080
- matches:
- headers:
- name: traffic
value: test
backendRefs:
- name: foo-v2
port: 8080蓝绿发布
内部测试已经验证 foo-v2 的响应符合预期之后,下一步就期望把小比例流量切到新 Service,进行更渐进、更真实的测试。下面的 HTTPRoute 把 foo-v2 也加入后端列表并指定权重。权重合计为 100,所以 foo-v1 接收 90/100=90% 流量,foo-v2 接收 10/100=10% 流量:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: foo-route
labels:
gateway: prod-web-gw
spec:
hostnames:
- foo.example.com
rules:
- backendRefs:
- name: foo-v1
port: 8080
weight: 90
- name: foo-v2
port: 8080
weight: 10完成发布
最后,如果所有信号都是正向的,就可以把流量完全切到 foo-v2 来完成发布。把 foo-v1 的权重设为 0,这样它就被配置为接收零流量:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: foo-route
labels:
gateway: prod-web-gw
spec:
hostnames:
- foo.example.com
rules:
- backendRefs:
- name: foo-v1
port: 8080
weight: 0
- name: foo-v2
port: 8080
weight: 1到这一步,100% 的流量都被路由到了 foo-v2,发布完成。如果出于任何原因 foo-v2 出现错误,只需更新权重就能快速把流量切回 foo-v1。一旦发布被认定为最终状态,v1 就可以被完全下线。