Skip to content

Commit 21afb7c

Browse files
committed
add docs for istio sticky canary releases
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
1 parent 14ccda5 commit 21afb7c

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

docs/gitbook/tutorials/istio-progressive-delivery.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,118 @@ Events:
292292
Warning Synced 1m flagger Canary failed! Scaling down podinfo.test
293293
```
294294

295+
## Session Affinity
296+
297+
While Flagger can perform weighted routing and A/B testing individually, with Istio it can combine the two leading to a Canary
298+
release with session affinity. For more information you can read the [deployment strategies docs](../usage/deployment-strategies.md)
299+
300+
Create a canary custom resource \(replace app.example.com with your own domain\):
301+
302+
```yaml
303+
apiVersion: flagger.app/v1beta1
304+
kind: Canary
305+
metadata:
306+
name: podinfo
307+
namespace: test
308+
spec:
309+
# deployment reference
310+
targetRef:
311+
apiVersion: apps/v1
312+
kind: Deployment
313+
name: podinfo
314+
# the maximum time in seconds for the canary deployment
315+
# to make progress before it is rollback (default 600s)
316+
progressDeadlineSeconds: 60
317+
# HPA reference (optional)
318+
autoscalerRef:
319+
apiVersion: autoscaling/v2beta2
320+
kind: HorizontalPodAutoscaler
321+
name: podinfo
322+
service:
323+
# service port number
324+
port: 9898
325+
# container port number or name (optional)
326+
targetPort: 9898
327+
# Istio gateways (optional)
328+
gateways:
329+
- public-gateway.istio-system.svc.cluster.local
330+
# Istio virtual service host names (optional)
331+
hosts:
332+
- app.example.com
333+
# Istio traffic policy (optional)
334+
trafficPolicy:
335+
tls:
336+
# use ISTIO_MUTUAL when mTLS is enabled
337+
mode: DISABLE
338+
# Istio retry policy (optional)
339+
retries:
340+
attempts: 3
341+
perTryTimeout: 1s
342+
retryOn: "gateway-error,connect-failure,refused-stream"
343+
analysis:
344+
# schedule interval (default 60s)
345+
interval: 1m
346+
# max number of failed metric checks before rollback
347+
threshold: 5
348+
# max traffic percentage routed to canary
349+
# percentage (0-100)
350+
maxWeight: 50
351+
# canary increment step
352+
# percentage (0-100)
353+
stepWeight: 10
354+
# session affinity config
355+
sessionAffinity:
356+
# name of the cookie used
357+
cookieName: flagger-cookie
358+
# max age of the cookie (in seconds)
359+
# optional; defaults to 86400
360+
maxAge: 21600
361+
metrics:
362+
- name: request-success-rate
363+
# minimum req success rate (non 5xx responses)
364+
# percentage (0-100)
365+
thresholdRange:
366+
min: 99
367+
interval: 1m
368+
- name: request-duration
369+
# maximum req duration P99
370+
# milliseconds
371+
thresholdRange:
372+
max: 500
373+
interval: 30s
374+
# testing (optional)
375+
webhooks:
376+
- name: acceptance-test
377+
type: pre-rollout
378+
url: http://flagger-loadtester.test/
379+
timeout: 30s
380+
metadata:
381+
type: bash
382+
cmd: "curl -sd 'test' http://podinfo-canary:9898/token | grep token"
383+
- name: load-test
384+
url: http://flagger-loadtester.test/
385+
timeout: 5s
386+
metadata:
387+
cmd: "hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/"
388+
```
389+
390+
Save the above resource as podinfo-canary-session-affinity.yaml and then apply it:
391+
392+
```bash
393+
kubectl apply -f ./podinfo-canary-session-affinity.yaml
394+
```
395+
396+
Trigger a canary deployment by updating the container image:
397+
398+
```bash
399+
kubectl -n test set image deployment/podinfo \
400+
podinfod=ghcr.io/stefanprodan/podinfo:6.0.1
401+
```
402+
403+
You can load `app.example.com` in your browser and refresh it until you see the requests being served by `podinfo:6.0.1`.
404+
All subsequent requests after that will be served by `podinfo:6.0.1` and not `podinfo:6.0.0` because of the session affinity
405+
configured by Flagger with Istio.
406+
295407
## Traffic mirroring
296408

297409
![Flagger Canary Traffic Shadowing](https://raw.githubusercontent.com/fluxcd/flagger/main/docs/diagrams/flagger-canary-traffic-mirroring.png)

docs/gitbook/usage/deployment-strategies.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Flagger can run automated application analysis, promotion and rollback for the f
1010
* Kubernetes CNI, Istio, Linkerd, App Mesh, NGINX, Contour, Gloo Edge, Open Service Mesh, Gateway API
1111
* **Blue/Green Mirroring** \(traffic shadowing\)
1212
* Istio
13+
* **Canary Release with Session Affinity** \(progressive traffic shifting combined with cookie based routing\)
14+
* Istio
1315

1416
For Canary releases and A/B testing you'll need a Layer 7 traffic management solution like
1517
a service mesh or an ingress controller. For Blue/Green deployments no service mesh or ingress controller is required.
@@ -393,3 +395,58 @@ After the analysis finishes, the traffic is routed to the canary (green) before
393395
triggering the primary (blue) rolling update, this ensures a smooth transition
394396
to the new version avoiding dropping in-flight requests during the Kubernetes deployment rollout.
395397

398+
## Canary Release with Session Affinity
399+
This deployment strategy mixes a Canary Release with A/B testing. A Canary Release is helpful when
400+
we're trying to expose new features to users progressively, but because of the very nature of its
401+
routing (weight based), users can land on the application's old version even after they have been
402+
routed to the new version previously. This can be annoying, or worse break how other services interact
403+
with our application. To address this issue, we borrow some things from A/B testing.
404+
405+
Since A/B testing is particularly helpful for applications that require session affinity, we integrate
406+
cookie based routing with regular weight based routing. This means once a user is exposed to the new
407+
version of our application (based on the traffic weights), they're always routed to that version, i.e.
408+
they're never routed back to the old version of our application.
409+
410+
You can enable this, by specifying `.spec.analsyis.sessionAffinity` in the Canary (only Istio is supported):
411+
412+
```yaml
413+
analysis:
414+
# schedule interval (default 60s)
415+
interval: 1m
416+
# max number of failed metric checks before rollback
417+
threshold: 10
418+
# max traffic percentage routed to canary
419+
# percentage (0-100)
420+
maxWeight: 50
421+
# canary increment step
422+
# percentage (0-100)
423+
stepWeight: 2
424+
# session affinity config
425+
sessionAffinity:
426+
# name of the cookie used
427+
cookieName: flagger-cookie
428+
# max age of the cookie (in seconds)
429+
# optional; defaults to 86400
430+
maxAge: 21600
431+
```
432+
433+
`.spec.analysis.sessionAffinity.cookieName` is the name of the Cookie that is stored. The value of the
434+
cookie is a randomly generated string of characters that act as a unique identifier. For the above
435+
config, the response header of a request routed to the canary deployment during a Canary run will look like:
436+
```
437+
Set-Cookie: flagger-cookie=LpsIaLdoNZ; Max-Age=21600
438+
```
439+
440+
After a Canary run is over and all traffic is shifted back to the primary deployment, all responses will
441+
have the following header:
442+
```
443+
Set-Cookie: flagger-cookie=LpsIaLdoNZ; Max-Age=-1
444+
```
445+
This tells the client to delete the cookie, making sure there are no junk cookies lying around in the user's
446+
system.
447+
448+
If a new Canary run is triggered, the response header will set a new cookie for all requests routed to
449+
the Canary deployment:
450+
```
451+
Set-Cookie: flagger-cookie=McxKdLQoIN; Max-Age=21600
452+
```

0 commit comments

Comments
 (0)