Hi, I have been trying to enable sticky sessions with Traefik for a while without success. I dove into documentation, performed multiple experiments and I got to this point where I think it should have worked but it's not.
First of all, some context. What I am trying to achieve is a front-end to backend communication via WebSocket. Because there are multiple back-end replicas the scokets keep reconnecting. Reducing to 1 replica and everything works.
Second, I only use Kubernetes objects because using Traefik custom CRDs mean that I will loose compatibility with some services that require them like cert-manager or linkerd and there may be more, so I don't think it's a good idea to make the architecture future proof to use CRDs to define Services and Ingresses.
Having that said I reached the conclusion (through extensive documentation research) that on Traefik v2.1.2 That I am currently on, I can only achieve this through dynamic configuration files (as sticky apparently is only supported on Traefik's CRDs).
To make this a bit more flexible and done in Kubernetes way I am mounting ConfigMaps as config files in Traefik pod. The problem is that I have no idea how to check if the configuration I am using has been properly processed. I followed the guide here (https://docs.traefik.io/v2.1/user-guides/crd-acme/) to setup Traefik but customized the deployment so it looks like this:
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: traefik
name: traefik-ingress-controller
---
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: traefik
name: traefik
labels:
app: traefik
spec:
replicas: 3
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
serviceAccountName: traefik-ingress-controller
containers:
- name: traefik
image: traefik:v2.1
args:
- --api=true
- --api.insecure=true
- --api.dashboard=true
- --accesslog=true
- --entrypoints.web.Address=:8000
- --entrypoints.websecure.Address=:4443
- --providers.kubernetescrd
- --providers.kubernetesingress=true
- --providers.kubernetescrd.ingressclass=traefik
- --providers.file.directory=/config #<-- Where I am putting the configmap mounts
- --providers.file.watch=true
ports:
- name: web
containerPort: 8000
- name: websecure
containerPort: 4443
- name: admin
containerPort: 8080
volumeMounts:
- name: config-vol
mountPath: /config
volumes:
- name: config-vol
configMap:
name: traefik-config
items:
- key: sticky-services
path: sticky-services.yaml
That leads to mount the ConfigMap below in the path /config/sticky-services.yaml, I verified in the pod that the file exists and I can read the file.
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-config
namespace: traefik
data:
sticky-services: |
http:
services:
my-service.othernamespace.svc.cluster.local:
loadBalancer:
sticky:
cookie: {}
Where my-service is the backend service the frontend maintains a websocket connection to.
The end result is that nothing changes. A cookie is not sent and the socket keeps disconnecting and reconnecting again.
The application works fine under one replica, TLS is enabled so certificate generation works fine under this setup and I have no CORS problems, so I get authentication cookies fine.
Is there anything that I am overlooking here?
Thank you for any help that you can provide.
Cheers,
Fábio