Treafik for load balancing Galera Cluster

Hello,

I currently have a working Traefik configuration and a separate Galera cluster using HAProxy as a load balancer.

Is it possible for Traefik to also handle the load balancing for the Galera cluster, replacing HAProxy for this role?

Regards,

Traefik can potentially be used as a plain TCP load-balancer, but it only provides weighted-round-robin, no least-connection or other methods (doc).

ok, sounds great, but I need to expose the port 3306 in traefik config but traefik knows to forward incoming 3306 connection to the tcp services configured as loadlbalancers ?

Regards,

You need to create entrypoint in static config, router and service in dynamic config file.

something went wrong… the log show:

ERR error="invalid rule: \"Host(`galera-cluster.foo.com`)\" , unsupported function: Host" entryPointName=galera routerName=galera-cluster@file

dynamic.yaml:

tcp:
  routers:
    galera-cluster:
      entryPoints:
        - "galera"
      rule: "Host(`galera-cluster.foo.com`)"
      service: "galera-cluster"

  services:
    galera-cluster:
      weighted:
        services:
        - name: mariadb1
          weight: 1
        - name: mariadb2
          weight: 1
        - name: mariadb3
          weight: 1

    mariadb1:
      loadBalancer:
        servers:
        - address: "1.1.1.1:3306"

    mariadb2:
      loadBalancer:
        servers:
        - address: "1.1.1.2:3306"

    mariadb3:
      loadBalancer:
        servers:
        - address: "1.1.1.3:3306"

docker-compose.yaml:

services:
  traefik:
    image: traefik:latest

    networks:
      # Connect to the 'traefik_proxy' overlay network for inter-container communication across nodes
      - traefik_proxy

    environment:
      - "TZ=Europe/Luxembourg"

    ports:
      # Expose Traefik's entry points to the Swarm
      # Swarm requires the long syntax for ports.
      - target: 80
        published: 80
        protocol: tcp
        mode: host

      - target: 443
        published: 443
        protocol: tcp
        mode: host

      - target: 3306
        published: 3306
        protocol: tcp
        mode: host

      - target: 8080
        published: 8080
        protocol: tcp
        mode: host

    volumes:
      # Mount the Docker socket for the Swarm provider
      # This MUST be run from a manager node to access the Swarm API via the socket.
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./certs:/certs"
      - "./config:/config:ro"
      - "./logs:/logs"

    command:
      - "--serversTransport.insecureSkipVerify=true"

      # TCP Entrypoint
      - "--entrypoints.galera.address=:3306"

      # HTTP EntryPoint
      - "--entrypoints.web.address=:80"

      # Configure HTTP to HTTPS Redirection
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"

      # HTTPS EntryPoint
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls=true"

      # Attach dynamic TLS file
      - "--providers.file.filename=config/dynamic.yaml"

      # Let's encrypt configuration
      - "--certificatesresolvers.le.acme.email=@"
      - "--certificatesresolvers.le.acme.storage=certs/acme.json"
      - "--certificatesresolvers.le.acme.dnschallenge.provider=ovh"
      - "--certificatesresolvers.le.acme.dnschallenge.delaybeforecheck=10"

      # Providers

      # Enable the Docker Swarm provider (instead of Docker provider)
      - "--providers.swarm.endpoint=unix:///var/run/docker.sock"

      # Watch for Swarm service changes (requires socket access)
      - "--providers.swarm.watch=true"

      # Recommended: Don't expose services by default; require explicit labels
      - "--providers.swarm.exposedbydefault=false"

      # Specify the default network for Traefik to connect to services
      - "--providers.swarm.network=traefik_proxy"

      # API & Dashboard
      - "--api.dashboard=true"
      - "--api.insecure=true"

      # Observability
      - "--log.level=INFO"
      - "--log.filepath=logs/traefik.log"
      - "--accesslog=true"
      - "--accesslog.filepath=logs/access.log"
      - "--accesslog.fields.names.StartUTC=drop"
      - "--metrics.prometheus=true"

    deploy:
      mode: replicated
      replicas: 1
      placement:

      # Placement constraints restrict where Traefik tasks can run.
      # Running on manager nodes is common for accessing the Swarm API via the socket.
        constraints:
          - node.role == manager

      # Traefik Dynamic configuration via labels
      # In Swarm, labels on the service definition configure Traefik routing for that service.
      labels:
        - "traefik.enable=true"
        # Dashboard router
        - "traefik.http.routers.dashboard.rule=Host(`traefik.foo.com`)"
        - "traefik.http.routers.dashboard.entrypoints=websecure"
        - "traefik.http.routers.dashboard.service=api@internal"
        - "traefik.http.routers.dashboard.tls=true"
        - "traefik.http.routers.dashboard.tls.certresolver=le"

        # Basic‑auth middleware
        # - "traefik.http.middlewares.dashboard-auth.basicauth.users=<PASTE_HASH_HERE>"
        # - "traefik.http.routers.dashboard.middlewares=dashboard-auth@swarm"

        # Service hint
        - "traefik.http.services.traefik.loadbalancer.server.port=8080"

# Define the overlay network for Swarm
networks:
  traefik_proxy:
    external: true
    driver: overlay
    attachable: true

                                                                                                                                                                                                  

For a TCP router you need to use HostSNI(`example.com`) when TLS is enabled. Or HostSNI(`*`) for a catch-all on that entrypoint/port, when plain TCP/IP is used.