<h2>Background</h2>

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

<p>The external IP exposed to the world via Cloudflare:</p>

<pre><code>Client ---&gt; Cloudflare ---&gt; k8 service ---&gt; pod
</code></pre>

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

<pre><code>kubectl patch service MYSERVICE  -p '{"spec":{"sessionAffinity":"ClientIP"}}'
</code></pre>

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

<h2>Investigation</h2>

<p>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.</p>

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

<h2>Possible solutions</h2>

<ol>
<li>I found that it may be possible to loadbalance traffic according to
Cookie. Founded this <a href="https://cloud.google.com/kubernetes-engine/docs/how-to/configure-backend-service#setting_generated_cookie_affinity" rel="nofollow noreferrer">source</a>. But it using advanced Kubernetes
components, like BackendService and Ingress, that needs to be
well-defined. Do you have more simple solution?</li>
<li>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?</li>
</ol>

<p>The easiest way to use <a href="https://github.com/kubernetes/ingress-nginx" rel="nofollow noreferrer">Nginx Ingress Controller</a> with below official example of ingress resource.</p>

<pre><code>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: /
</code></pre>

<p>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 <a href="https://stackoverflow.com/questions/56353972/procedure-to-install-an-ingress-controller/56378650#56378650">post</a> to follow installation instructions. Then apply above ingress object.</p>

<p>You can read also from this <a href="https://medium.com/@zhimin.wen/sticky-sessions-in-kubernetes-56eb0e8f257d" rel="nofollow noreferrer">blog</a> to get more information how to use sticky sessions in Kubernetes.</p>

<p>Also feel free to explore other <a href="https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md" rel="nofollow noreferrer">nginx ingress annotations</a> if you can use them.</p>

<p>Hope it helps!</p>
