Skip to content

Instantly share code, notes, and snippets.

@aryszka
Created June 30, 2020 15:43
Show Gist options
  • Save aryszka/f32b5f679664c40295d0fe4c66429f39 to your computer and use it in GitHub Desktop.
Save aryszka/f32b5f679664c40295d0fe4c66429f39 to your computer and use it in GitHub Desktop.

A/B test with traffic switching

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 content team-foo to validate backend variant-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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment