Successfully using Ingress-NGINX and SessionAffinity with Regex paths

Paul Dally
2 min readMay 5, 2023

--

Photo by Girl with red hat on Unsplash

First, please consider enhancing your application so that it doesn’t require session affinity!

The Problem

If you absolutely must move forward with session affinity using Ingress-NGINX Controller, you may find that it doesn’t work initially. Consider the following Ingress object:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: helloworld-deployment-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/affinity: "cookie"
spec:
ingressClassName: myingressclass
rules:
- http:
paths:
- path: /helloworld/(.*)
pathType: Prefix
backend:
service:
name: helloworld-deployment-svc
port:
number: 8080

When this Ingress is accessed, your first request is handled by one Pod:

Hello, world!
Hostname: helloworld-deployment-cdc7bf697-9rnbb

and your next request might be handled by another Pod:

Hello, world!
Hostname: helloworld-deployment-cdc7bf697-r79kj

Persistence (stickiness) is clearly not working!

The issue is how Ingress-NGINX is creating the cookie (you can see this, for example, with Chrome Developer Tools — Ctrl-Shift-I):

Set-Cookie: INGRESSCOOKIE=1683294502.046.28868.397950|a70374fa4f94f7a90dd3fcc9411153f9; 
Path=/helloworld/(.*); HttpOnly

Because the Path attribute doesn’t match the URL the browser sees (cookie Path matching doesn’t use regular expressions, and so the (.*) would have to literally match the content of the URL), on the next request the browser does not send the cookie — effectively disabling session affinity.

The Solution

The cookie Path is defaulting to the path in the Ingress, which since it is specified as a regex, is not a valid cookie Path. If you add the following annotation, persistence will start working as expected:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: helloworld-deployment-ingress
annotations:
nginx.ingress.kubernetes.io/session-cookie-path: /helloworld/
<snip>

The resulting Set-Cookie header will now look like this:

Set-Cookie: INGRESSCOOKIE=1683294502.046.28868.397950|a70374fa4f94f7a90dd3fcc9411153f9; 
Path=/helloworld/; HttpOnly

Now that the cookie’s Path attribute actually matches the path that the browser sees, it will start sending the cookie back to the Ingress controller , enabling the Ingress controller to direct the request back to the original Pod.

--

--

Paul Dally
Paul Dally

Written by Paul Dally

AVP, IT Foundation Platforms Architecture at Sun Life Financial. Views & opinions expressed are my own, not necessarily those of Sun Life

No responses yet