A/B test via cookie canary
, used for sticky sessions.
step0
- all traffic goes to backend
variant-b
, Kubernetes service-b-v1
apiVersion: zalando.org/v1
kind: RouteGroup
metadata:
name: my-routes
spec:
hosts:
- api.example.org
backends:
- name: variant-b
type: service
serviceName: service-b-v1
servicePort: 80
defaultBackends:
- backendName: variant-b
routes:
- pathSubtree: /
step1
- A canary route for team foo was added, that needs a Cookie
canary
with contentteam-foo
to validate backendvariant-a
, before customers will get the traffic.
apiVersion: zalando.org/v1
kind: RouteGroup
metadata:
name: my-routes
spec:
hosts:
- api.example.org
backends:
- name: variant-a
type: service
serviceName: service-a
servicePort: 80
- name: variant-b
type: service
serviceName: service-b-v1
servicePort: 80
defaultBackends:
- backendName: variant-b
routes:
- pathSubtree: /
- pathSubtree: /
predicates:
- Cookie("canary", "team-foo")
backends:
- backendName: variant-a
step2
- After successful test delete team cookie
- A/B test: 10% chance to get cookie for backend
variant-a
- the rest of the traffic goes to backend
variant-b
apiVersion: zalando.org/v1
kind: RouteGroup
metadata:
name: my-routes
spec:
hosts:
- api.example.org
backends:
- name: variant-a
type: service
serviceName: service-a
servicePort: 80
- name: variant-b
type: service
serviceName: service-b-v1
servicePort: 80
defaultBackends:
- backendName: variant-b
routes:
- pathSubtree: /
filters:
- responseCookie("canary", "A")
predicates:
- Traffic(.1)
backends:
- backendName: variant-a
- pathSubtree: /
filters:
- responseCookie("canary", "B")
- pathSubtree: /
predicates:
- Cookie("canary", "A")
backends:
- backendName: variant-a
- pathSubtree: /
predicates:
- Cookie("canary", "B")
step3
- service-b will be traffic switched from v1 to v2, v2 will get 20% traffic, rest to v1
- service-a stays unchanged and all customers that have cookie
canary=A
apiVersion: zalando.org/v1
kind: RouteGroup
metadata:
name: my-routes
spec:
hosts:
- api.example.org
backends:
- name: variant-a
type: service
serviceName: service-a
servicePort: 80
- name: variant-b
type: service
serviceName: service-b-v1
servicePort: 80
- name: variant-b-v2
type: service
serviceName: service-b-v2
servicePort: 80
defaultBackends:
- backendName: variant-b
weight: 80
- backendName: variant-b-v2
weight: 20
routes:
- pathSubtree: /
filters:
- responseCookie("canary", "A")
predicates:
- Traffic(.1)
backends:
- backendName: variant-a
- pathSubtree: /
filters:
- responseCookie("canary", "B")
- pathSubtree: /
predicates:
- Cookie("canary", "A")
backends:
- backendName: variant-a
- pathSubtree: /
predicates:
- Cookie("canary", "B")
step4
- variant-b will be completely switched to
service-b-v2
- variant-a stays unchanged and all customers that have cookie
canary=A
apiVersion: zalando.org/v1
kind: RouteGroup
metadata:
name: my-routes
spec:
hosts:
- api.example.org
backends:
- name: variant-a
type: service
serviceName: service-a
servicePort: 80
- name: variant-b
type: service
serviceName: service-b-v2
servicePort: 80
defaultBackends:
- backendName: variant-b
routes:
- pathSubtree: /
filters:
- responseCookie("canary", "A")
predicates:
- Traffic(.1)
backends:
- backendName: variant-a
- pathSubtree: /
filters:
- responseCookie("canary", "B")
- pathSubtree: /
predicates:
- Cookie("canary", "A")
backends:
- backendName: variant-a
- pathSubtree: /
predicates:
- Cookie("canary", "B")
As we see in step0 till step4 we can create an A/B test with
manual pre-validating variant-a
. We do ongoing A/B test and can do
traffic switching for one backend while having a running A/B test.