HTTP traffic splitting¶
The HTTPRoute resource allows you to specify weights to shift
traffic between different backends. This is useful for splitting traffic during
rollouts, canarying changes, or for emergencies. The HTTPRoute
spec.rules.forwardTo
accepts a list of backends that a route rule will send
traffic to. The relative weights of these backends define the split of traffic
between them. The following YAML snippet shows how two Services are listed as
backends for a single route rule. This route rule will split traffic 90% to
foo-v1
and 10% to foo-v2
.
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: simple-split
spec:
rules:
- forwardTo:
- serviceName: foo-v1
port: 8080
weight: 90
- serviceName: foo-v2
port: 8080
weight: 10
weight
indicates a proportional split of traffic (rather than percentage)
and so the sum of all the weights within a single route rule is the
denominator for all of the backends. weight
is an optional parameter and if
not specified, defaults to 1. If only a single backend is specified for a
route rule it implicitly recieves 100% of the traffic, no matter what (if any)
weight is specified.
Guide¶
This guide shows the deployment of two versions of a Service. Traffic splitting is used to manage the gradual splitting of traffic from v1 to v2.
This example assumes that the following Gateway is deployed:
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata:
name: prod-web
spec:
gatewayClassName: acme-lb
listeners:
- protocol: HTTP
port: 80
routes:
kind: HTTPRoute
selector:
matchLabels:
gateway: prod-web-gw
Canary traffic rollout¶
At first, there may only be a single version of a Service that serves
production user traffic for foo.example.com
. The following HTTPRoute has no
weight
specified for foo-v1
or foo-v2
so they will implicitly
recieve 100% of the traffic matched by each of their route rules. A canary
route rule is used (matching the header traffic=test
) to send synthetic test
traffic before splitting any production user traffic to foo-v2
. Routing
precedence ensures that
all traffic with the matching host and header (the most specific match) will
be sent to foo-v2
.
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: foo-route
labels:
gateway: prod-web-gw
spec:
hostnames:
- foo.example.com
rules:
- forwardTo:
- serviceName: foo-v1
port: 8080
- matches:
- headers:
type: Exact
values:
traffic: test
forwardTo:
- serviceName: foo-v2
port: 8080
Blue-green traffic rollout¶
After internal testing has validated succesful responses from foo-v2
,
it's desirable to shift a small percentage of the traffic to the new Service
for gradual and more realistic testing. The HTTPRoute below adds foo-v2
as a backend along with weights. The weights add up to a total of 100 so
foo-v1
recieves 90/100=90% of the traffic and foo-v2
recieves
10/100=10% of the traffic.
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: foo-route
labels:
gateway: prod-web-gw
spec:
hostnames:
- foo.example.com
rules:
- forwardTo:
- serviceName: foo-v1
port: 8080
weight: 90
- serviceName: foo-v2
port: 8080
weight: 10
Completing the rollout¶
Finally, if all signals are positive, it is time to fully shift traffic to
foo-v2
and complete the rollout. The weight for foo-v1
is set to
0
so that it is configured to accept zero traffic.
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: foo-route
labels:
gateway: prod-web-gw
spec:
hostnames:
- foo.example.com
rules:
- forwardTo:
- serviceName: foo-v1
port: 8080
weight: 0
- serviceName: foo-v2
port: 8080
weight: 1
At this point 100% of the traffic is being routed to foo-v2
and the
rollout is complete. If for any reason foo-v2
experiences errors, the
weights can be updated to quickly shift traffic back to foo-v1
. Once
the rollout is deemed final, v1 can be fully decommissioned.