[SOLVED] How to get traefik ingress to load balance across several ClusterIP services

Using traefik 2.2.8 and ingress traefik.containo.us/v1alpha1 from helm traefik 9.1.0, I want to be able to load balance several nodes of a backend service represented by ClusterIP services using a traefik.containo.us/v1alpha1 ingress. I know that ClusterIP service can load balance easily with deployments and ReplicaSet but the way this application is designed each node needs to be it's own Deployment as it is a stateful node.

So I either need a way to have the flow be:

Ingress --> [ClusterIP-Node1, ClusterIP-Node2, ClusterIP-Node3, ClusterIP-Node4] 

or

Ingress --> ClusterIP-LoadBalancer --> [ClusterIP-Node1, ClusterIP-Node2, ClusterIP-Node3, ClusterIP-Node4] 

How can I use traefik.containo.us/v1alpha1 to automatically loadbalance between these ClusterIP services?

For example, if I currently have one Ingress for each `ClusterIP, like this:

...
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: my-service-node1-ingress
spec:
  entryPoints:
    - web
    - websecure
  routes:
    - kind: Rule
      match: Host(`myservice-node1.mycompany.example`)
      services:
        - kind: Service
          name: myservice-node1-clusterip
          passHostHeader: true
          port: 80

---
apiVersion: v1
kind: Service
metadata:
  name: myservice-node1-clusterip
  labels:
    app: myservice
    tier: backend
    name: myservice-node1
spec:
  selector:
    app: myservice
    tier: backend
    name: myservice-node1-deployment
  type: ClusterIP
  ports:
    - name: rpc-listener
      protocol: TCP
      port: 80
      targetPort: 8545
... N+1

And I want to change that to a single Ingress Point similar to this:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: my-service-ingress
spec:
  entryPoints:
    - web
    - websecure
  routes:
    - kind: Rule
      match: Host(`myservice.mycompany.example`)
      services:
        - kind: Service
          name: myservice-node1-clusterip
          passHostHeader: true
          port: 80

Is it possible to have the traefik.containo.us/v1alpha1 load balance across the services similar to this? I saw something that looked promising on this page in the docs that you can have n number of services[n].name for a matching route routes[n].services. Does that mean you can do something similar to the following?

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: my-service-ingress
spec:
  entryPoints:
    - web
    - websecure
  routes:
    - kind: Rule
      match: Host(`myservice.mycompany.example`)
      services:
        - kind: Service
          name: myservice-node1-clusterip
          passHostHeader: true
          port: 80
        - kind: Service
          name: myservice-node2-clusterip
          passHostHeader: true
          port: 80
        - kind: Service
          name: myservice-node3-clusterip
          passHostHeader: true
          port: 80
        - kind: Service
          name: myservice-node4-clusterip
          passHostHeader: true
          port: 80

Also, is there a way to pass the sessionAffinity with it like there are in services sessionAffinity: ClientIP?

Thanks!

I was able to get it to work with the setup I described above and it is show in the Docs here

The load balancing seems random, which is fine, although I'd like it to prefer to have sessionAffinity setup so like requests are routed to the same service when possible.

1 Like

Glad to hear that you have found the solutions. I highly recommend considering an upgrade of your Traefik instance to 2.4.x.