Google Cloud Kubernetes - Load Balancer session affinity with Cloudflare

6/5/2019

Background

I have web application which deployed to deployment with multiple pods. The deployment is exposed to the internet with kubernetes service with external IP.

The external IP exposed to the world via Cloudflare:

Client ---> Cloudflare ---> k8 service ---> pod

This web application needs to be defined with sticky sessions. So I patched my service with sessionAffinity: ClientIP, like this:

kubectl patch service MYSERVICE  -p '{"spec":{"sessionAffinity":"ClientIP"}}'

I checked it on development environment and found that the session affinity is not working well.

Investigation

I looked for the problem with the sticky sessions. Then I found that Cloudflare caller IP can be changed from time to time - randomly. This will redirect all the users to another pod - exactly what Sticky Session should solve.

So, the problem is that my Loadbalancer service redirect traffic according to Cloudflare IP and it random.

Possible solutions

  1. I found that it may be possible to loadbalance traffic according to Cookie. Founded this source. But it using advanced Kubernetes components, like BackendService and Ingress, that needs to be well-defined. Do you have more simple solution?
  2. Cloudflare attaching the real client IP to the request in headers. Is this possible to define the loadbalancing to look on this header and redirect the traffic according to it's value?
-- No1Lives4Ever
google-cloud-platform
google-kubernetes-engine
kubernetes
load-balancing

1 Answer

6/10/2019

The easiest way to use Nginx Ingress Controller with below official example of ingress resource.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-test
  annotations:
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "route"
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"    
spec:
  rules:
  - host: stickyingress.example.com
    http:
      paths:
      - backend:
          serviceName: http-svc # k8 service name
          servicePort: 80 # k8 service port
        path: /

In order to use it, you have to have Nginx Ingress Controller installed on your Kubernetes cluster. You can follow instructions in answer of this post to follow installation instructions. Then apply above ingress object.

You can read also from this blog to get more information how to use sticky sessions in Kubernetes.

Also feel free to explore other nginx ingress annotations if you can use them.

Hope it helps!

-- coolinuxoid
Source: StackOverflow