Client IP Address Appears as Traefik Pod IP

Hello everyone,

After many hours of testing and searching on this forum, I have not found a solution to my problem.

I have a K3S Cluster (1 control plane and 2 worker). Traefik (v3.2.0) is deployed as a Daemonset. A Traefik loadbalancer Service is deployed on my Cluster (metallb) with externalTrafficPolicy to Local.

A client (outside the cluster) is trying to make connections to an application (within my cluster) through Traefik loadblancer service. This flow works well, but the issue is that the source IP seen from the application corresponds to the IP of one of the Traefik pods (not the real client's).

I have tried:

  • proxy protocol on entry point
  • proxy protocol on ingressRouteTcp
  • externalTrafficPolicy to Local to my Traefik service

None of these solutions work. However, Traefik does see the remote address as the client one.

If I don’t go through Traefik to access my application and I expose a service of type LoadBalancer with externalTrafficPolicy set to Local, the client IP is correct.

Any help would be greatly appreciated.

Here is my configuration:

Traefik:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  namespace: traefik
  name: traefik
  labels:
    app: traefik
spec:
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      labels:
        app: traefik
    spec:
      tolerations:
        - key: "node-role.kubernetes.io/control-plane"
          operator: "Exists"
          effect: "NoSchedule"
      serviceAccountName: traefik-ingress-controller
      volumes:
        - name: docker-socket
          hostPath:
            path: /var/run/docker.sock
      containers:
      - name: traefik
        image: storage.registry:5001/traefik:v3.2.0
        imagePullPolicy: Always
        envFrom:
          - configMapRef:
              name: traefik-entrypoints-global
        env:
          - name: TRAEFIK_ACCESSLOG
            value: "true"
          - name: TRAEFIK_API_DASHBOARD
            value: "true"
          - name: TRAEFIK_API_INSECURE
            value: "true"
          - name: TRAEFIK_ACCESSLOG
            value: "true"
          - name: TRAEFIK_LOG_LEVEL
            value: "TRACE"
          - name: TRAEFIK_PROVIDERS_DOCKER
            value: "true"
          - name: TRAEFIK_PROVIDERS_KUBERNETESCRD
            value: "true"
          - name: TRAEFIK_PROVIDERS_KUBERNETESCRD_ALLOWCROSSNAMESPACE
            value: "true"
          - name: TRAEFIK_ENTRYPOINTS_TOOLS_ADDRESS
            value: ":4444"
          - name: TRAEFIK_ENTRYPOINTS_TOOLS_PROXYPROTOCOL
            value: "true"
          - name: TRAEFIK_ENTRYPOINTS_TOOLS_PROXYPROTOCOL_INSECURE
            value: "true"
        volumeMounts:
          - mountPath: /var/run/docker.sock
            name: docker-socket

Traefik service:

apiVersion: v1
kind: Service
metadata:
  name: traefik
  namespace: traefik
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
    - protocol: TCP
      name: tools
      port: 4444
      targetPort: 4444
    - protocol: TCP
      name: dashboard
      port: 8080
      targetPort: 8080

  selector:
    app: traefik

IngressRouteTcp:

apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: myapp-service-traefik-tcp
spec:
  entryPoints:
    - tools
  routes:
    - match: ClientIP(`10.10.205.30`)
      priority: 50
      services:
        - name: myapp-service-traefik
          port: 8080
          proxyProtocol:
            version: 1

Thanks !

Try this configuration:

deployment:
  kind: DaemonSet

service:
  spec:
    externalTrafficPolicy: "Local"

(the values are for the Helm chart). This works for me. The daemonset ensures that the external load balancer always finds an instance of traefik on any node and the traffic does not have to be forwarded thru the cluster.