Skip to content

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

yaml
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: 10

weight 字段表示按比例切分流量(而不是按百分比),因此在同一条路由规则内,所有 weight 之和是分母(所有后端共用)。weight可选参数,如果不填,默认值为 1。如果一条路由规则只指定了一个后端,那么无论 weight 取何值(或未指定),它都隐式接收 100% 的流量。

指南

本指南展示如何部署一个 Service 的两个版本,并使用流量切分来渐进式地把流量从 v1 切到 v2。

本示例假设已经部署了下面这个 Gateway:

yaml
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: Same

Canary(金丝雀)发布

一开始,可能只有一个版本的 Service 在为 foo.example.com 的生产用户流量提供服务。下面的 HTTPRoute 没有foo-v1foo-v2 指定 weight,所以它们各自会隐式接收其路由规则所匹配到的 100% 流量。使用金丝雀路由规则(匹配 traffic=test Header)可以在正式把生产用户流量切到 foo-v2 之前,先把合成测试流量打过去。

路由优先级 保证:所有同时满足该主机名和该 Header 的请求(最具体的匹配)都会被发往 foo-v2

yaml
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% 流量:

yaml
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,这样它就被配置为接收零流量

yaml
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 就可以被完全下线

基于 MIT 协议发布