This demo shows how to enable sticky learn session persistence for an Ingress resource with the sessions shared among multiple NGINX Plus Ingress Controller pods.
- Deploy the Ingress Controller as a deployment -- https://github.com/nginxinc/kubernetes-ingress/blob/master/docs/installation.md
- Deploy a headless service for the Ingress Controller that will be used for zone synchronization:
$ kubectl apply -f nginx-ingress-zonesync.yaml
- Apply the ConfigMap with the
stream-snippets
for configuring zone synchronization and a custom template for custom sticky learn annotations. Note that we also addedadd_header nginx-ingress-hostname $hostname;
to the location block in the template to allow us to understand which NGINX Plus IC pod sends a response:$ kubectl apply -f nginx-config.yaml
- Scale the number of the Ingress Controller pods to 3:
$ kubectl scale deploy nginx-ingress --replicas=3 -n nginx-ingress
- Deploy the backend app and the Ingress resource:
$ kubectl apply -f backend.yaml $ kubectl apply -f ingress.yaml
Notes:
- We assume that NGINX Plus Ingress Controller pods are exposed through a load balancer with the IP saved into
$IC_IP
variable. - The backend app sets the cookie session. If a request includes the cookie session, the backend will not set the session cookie.
-
Send two requests to
example.com
and see that the responses come from different backend pods through different NGINX Plus IC pods:$ curl $IC_IP -H "host: example.com" -v * Rebuilt URL to: <REDACTED>/ * Trying <REDACTED>... * TCP_NODELAY set * Connected to <REDACTED> (<REDACTED>) port 80 (#0) > GET / HTTP/1.1 > host: example.com > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.15.10 < Date: Thu, 13 Jun 2019 11:26:05 GMT < Content-Type: text/plain < Content-Length: 59 < Connection: keep-alive < Set-Cookie: session=b66b69306c303c72d7876b0297dd334a < nginx-ingress-hostname: nginx-ingress-6c9c85d755-mn24r < Response from 10.60.1.33:80 (backend-app-85f495985c-whftm)
The response came from 10.60.1.33:80 (backend-app-85f495985c-whftm) backend through nginx-ingress-6c9c85d755-mn24r.
curl $IC_IP -H "host: example.com" -v * Rebuilt URL to: <REDACTED>/ * Trying <REDACTED>... * TCP_NODELAY set * Connected to <REDACTED> (<REDACTED>) port 80 (#0) > GET / HTTP/1.1 > host: example.com > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.15.10 < Date: Thu, 13 Jun 2019 11:26:06 GMT < Content-Type: text/plain < Content-Length: 59 < Connection: keep-alive < Set-Cookie: session=8e985030b254c50a817273a6a8572a37 < nginx-ingress-hostname: nginx-ingress-6c9c85d755-99cvf < Response from 10.60.2.50:80 (backend-app-85f495985c-vkhg4)
The response came from 10.60.2.50:80 (backend-app-85f495985c-vkhg4) backend through nginx-ingress-6c9c85d755-99cvf.
-
Send one request and then send a few requests with the session cookie from the response to the first request. All the responses should come from the same backend pod but through different NGINX Plus IC pods:
curl $IC_IP -H "host: example.com" -v * Rebuilt URL to: <REDACTED>/ * Trying <REDACTED>... * TCP_NODELAY set * Connected to <REDACTED> (<REDACTED>) port 80 (#0) > GET / HTTP/1.1 > host: example.com > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.15.10 < Date: Thu, 13 Jun 2019 11:33:23 GMT < Content-Type: text/plain < Content-Length: 59 < Connection: keep-alive < Set-Cookie: session=6300a29c34f19718f85955b4b23ca609 < nginx-ingress-hostname: nginx-ingress-6c9c85d755-4w767 < Response from 10.60.1.33:80 (backend-app-85f495985c-whftm) * Connection #0 to host <REDACTED> left intact
$ curl $IC_IP -H "host: example.com" -v --cookie session=6300a29c34f19718f85955b4b23ca609 * Rebuilt URL to: <REDACTED>/ * Trying <REDACTED>... * TCP_NODELAY set * Connected to <REDACTED> (<REDACTED>) port 80 (#0) > GET / HTTP/1.1 > host: example.com > User-Agent: curl/7.54.0 > Accept: */* > Cookie: session=6300a29c34f19718f85955b4b23ca609 > < HTTP/1.1 200 OK < Server: nginx/1.15.10 < Date: Thu, 13 Jun 2019 11:33:53 GMT < Content-Type: text/plain < Content-Length: 59 < Connection: keep-alive < nginx-ingress-hostname: nginx-ingress-6c9c85d755-99cvf < Response from 10.60.1.33:80 (backend-app-85f495985c-whftm)
$ curl $IC_IP -H "host: example.com" -v --cookie session=6300a29c34f19718f85955b4b23ca609 * Rebuilt URL to: <REDACTED>/ * Trying <REDACTED>... * TCP_NODELAY set * Connected to <REDACTED> (<REDACTED>) port 80 (#0) > GET / HTTP/1.1 > host: example.com > User-Agent: curl/7.54.0 > Accept: */* > Cookie: session=6300a29c34f19718f85955b4b23ca609 > < HTTP/1.1 200 OK < Server: nginx/1.15.10 < Date: Thu, 13 Jun 2019 11:33:56 GMT < Content-Type: text/plain < Content-Length: 59 < Connection: keep-alive < nginx-ingress-hostname: nginx-ingress-6c9c85d755-4w767 < Response from 10.60.1.33:80 (backend-app-85f495985c-whftm)
Currently, the custom annotation custom.nginx.org/sticky-learn
enables session persistence for every service in an Ingress resource. If you would like to enable session persistence per service, use Mergeable Ingresses to split one Ingress resource into multiple Mergeable minions and change the custom annotation to support Mergeable Ingesses -- https://github.com/nginxinc/kubernetes-ingress/blob/master/docs/custom-annotations.md#custom-annotations-with-mergeable-ingress-resources Once this is done, you can enable session persistence only for services of particular minions.
Is this feature available in NGINX OSS