Sticky session for ASP.NET Core on Kubernetes deployment

3/14/2019

I try to port an ASP.NET Core 1 application with Identity to Kubernetes. The login doesn't work and I got different errors like The anti-forgery token could not be decrypted. The problem is that I'm using a deployment with three replica sets so that further request were served by different pods that don't know about the anti-forgery token. Using replicas: 3 it works.

In the same question I found a sticky session documentation which seems a solution for my problem. The cookie name .AspNetCore.Identity.Application is from my browser tools.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myapp-k8s-test
  annotations:
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: ".AspNetCore.Identity.Application"
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: myapp-k8s
    spec:
      containers:
      - name: myapp-app
        image: myreg/myapp:0.1
        ports:
        - containerPort: 80
        env:
        - name: "ASPNETCORE_ENVIRONMENT"
          value: "Production"
      imagePullSecrets:
      - name: registrypullsecret

This doesn't work, either with or without leading dot at the cookie name. I also tried adding the following annotations

kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/session-cookie-hash: sha1

What is required to allow sticky sessions on Kubernetes with ASP.NET Core?

-- Daniel
asp.net-core
kubernetes
kubernetes-deployment
kubernetes-ingress
nginx

1 Answer

3/14/2019

Found out that I made two logical mistakes:

  1. Sticky sessions doesn't work this way

I assumed that Kubernetes will look into the cookie and create some mapping of cookie hashes to pods. But instead, another session is generated and append to our http header. nginx.ingress.kubernetes.io/session-cookie-name is only the name of those generated cookie. So per default, it's not required to change them.

  1. Scope to the right object

The annotations must be present on the ingress, NOT the deployment (stupid c&p mistake)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: myapp-k8s-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-hash: sha1

spec:
  tls:
  - hosts:
    - myapp-k8s.local
  rules:
  - host: myapp-k8s.local
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-svc
          servicePort: 80

This works as expected.

-- Daniel
Source: StackOverflow